lunes, 26 de marzo de 2012

Mejorando FakeDNS (I)

Como ya sabréis todos, soy un enamorado del Metasploit Framework, pero no por los exploits que incluye, sino por otras funcionalidades incluidas en el framework que me resultan muy útiles y cómodas de utilizar.

Una de las funcionalidades que uso con mucha frecuencia es la del módulo fakedns, que te permite configurar un servidor DNS en cuestión de segundos, que resolverá cualquier nombre con la IP que le digamos, salvo una lista concreta de nombres para los que se resolverán sus IPs reales.

Veamos como funciona:

# ./msfconsole
msf > use auxiliary/server/fakedns
msf  auxiliary(fakedns) > show options

Module options (auxiliary/server/fakedns):
   Name          Current Setting  Required  Description
   ----          ---------------  --------  -----------
   DOMAINBYPASS  www.google.com   yes       The list of domain names we want to fully resolve
   SRVHOST       0.0.0.0          yes       The local host to listen on.
   SRVPORT       53               yes       The local port to listen on.
   TARGETHOST                     no        The address that all names should resolve to

msf  auxiliary(fakedns) > set DOMAINBYPASS www.pentester.es
msf  auxiliary(fakedns) > set TARGETHOST 192.168.1.100
msf  auxiliary(fakedns) > run
[*] Auxiliary module execution completed

[*] DNS server initializing
[*] DNS server started

Ahora, si probamos a hacer algunos "dig" (os enseño la salida recortada), veremos como resuelve todos los nombres con la dirección 192.168.1.100, salvo el nombre www.pentester.es (o los que hubiéramos pasado separados por espacios):

$ dig @127.0.0.1 www.google.com
www.google.com. 60 IN A 192.168.1.100
$ dig @127.0.0.1 www.yahoo.com
www.yahoo.com. 60 IN A 192.168.1.100
$ dig @127.0.0.1 www.pentester.es
www.pentester.es. 60 IN A 173.194.66.121

Este funcionamiento... a mi nunca me ha terminado de convencer, lo veo demasiado "de botón gordo", ya que yo por lo general suelo querer interceptar solo una o un grupo de conexiones, y dejar que todas las demás sigan su funcionamiento normal.

Por suerte estamos trabajando con software OpenSource y tenemos la oportunidad de poder acceder al código y modificarlo según nos convenga, así que vamos a pegarle un vistazo al código (modules/auxiliary/server/fakedns.rb):


Como podemos ver, hay un punto en el código en el que se recorre la lista y se compara con la petición DNS que acaba de entrar. Si son iguales, entonces se hace una resolución "normal", mientras que si tras recorrer la lista no ha encontrado ninguno se entiende que al no estar en la lista de "bypass", se envia la respuesta "fake".

Si pensamos en una solución rápida y práctica, podemos sencillamente cambiar la condición:

[...]
if (name.to_s <=> ex) != 0
[...]

Con esto, siempre y cuando solo pongamos un elemento en la lista, vamos a tener más que suficiente, ya que va a funcionar de la forma completamente contraria: Cuando el nombre solicitado esté en la lista resolverá con fake, y cuando no lo esté funcionará normal.

Esta aproximación tan sencilla es la que he usado muchas veces cuando he querido interceptar las conexiones de algún software para analizarlas y dejar que el resto de elementos del sistema funcionen sin pasar por mis otras herramientas. Sin embargo, en algunas situaciones...

msf  auxiliary(fakedns_single) > [-] fakedns: Resolv::ResolvError DNS result has no information for foo.pentester.es /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/resolv.rb:363:in `getaddress'/opt/msf/modules/auxiliary/server/fakedns.rb:143:in `run'/opt/msf/modules/auxiliary/server/fakedns.rb:140:in `each'/opt/msf/modules/auxiliary/server/fakedns.rb:140:in `run'/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/resolv.rb:1183:in `each_question'/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/resolv.rb:1182:in `each'/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/resolv.rb:1182:in `each_question'/opt/msf/modules/auxiliary/server/fakedns.rb:115:in `run'/opt/msf/lib/msf/base/simple/auxiliary.rb:102:in `job_run_proc'/opt/msf/lib/msf/base/simple/auxiliary.rb:74:in `run_simple'/opt/msf/lib/rex/job_container.rb:36:in `call'/opt/msf/lib/rex/job_container.rb:36:in `start'/opt/msf/lib/rex/thread_factory.rb:21:in `call'/opt/msf/lib/rex/thread_factory.rb:21:in `spawn'/opt/msf/lib/msf/core/thread_manager.rb:64:in `call'/opt/msf/lib/msf/core/thread_manager.rb:64:in `spawn'/opt/msf/lib/msf/core/thread_manager.rb:57:in `initialize'/opt/msf/lib/msf/core/thread_manager.rb:57:in `new'/opt/msf/lib/msf/core/thread_manager.rb:57:in `spawn'/opt/msf/lib/rex/thread_factory.rb:21:in `spawn'/opt/msf/lib/rex/job_container.rb:31:in `start'/opt/msf/lib/rex/job_container.rb:155:in `start_bg_job'/opt/msf/lib/msf/base/simple/auxiliary.rb:71:in `run_simple'/opt/msf/lib/msf/base/simple/auxiliary.rb:89:in `run_simple'/opt/msf/lib/msf/ui/console/command_dispatcher/auxiliary.rb:103:in `cmd_run'/opt/msf/lib/rex/ui/text/dispatcher_shell.rb:380:in `send'/opt/msf/lib/rex/ui/text/dispatcher_shell.rb:380:in `run_command'/opt/msf/lib/rex/ui/text/dispatcher_shell.rb:342:in `run_single'/opt/msf/lib/rex/ui/text/dispatcher_shell.rb:336:in `each'/opt/msf/lib/rex/ui/text/dispatcher_shell.rb:336:in `run_single'/opt/msf/lib/rex/ui/text/shell.rb:199:in `run'./msfconsole:134

Ops! Cascazo! Y además la ejecución del módulo se ha ido al garete, así que como tenga en una red o host peticiones como esta... voy a estar teniendolo que rearrancar cada dos por tres. Imposible trabajar así, vamos.
En el próximo post veremos porque pasa esto y como evitarlo, y seguiremos mejorando el fakedns.

3 comentarios :

0verMain dijo...

jajajaja que bueno José.
Espero la solución en el proximo post.

PD: Me alegra ver que retomas la asiduidad en las publicaciones.

Muchas gracias.
Saludos.

Jose Selvi dijo...

@0verMain: Mañana tendrás tu solución ;)

Gracias por tu apoyo, es lo que tiene estar solo para escribir el blog, que cuando tengo temporadas de mucho ajetreo... nadie escribe xD

Gabriel dijo...

La verdad exelente el post, ahora quiero ver porque el error :D

Gracias, Saludos