martes, 27 de marzo de 2012

Mejorando FakeDNS (y II)

En la anterior entrada nos quedábamos con que habíamos modificado el módulo "fakedns" de Metasploit para invertir su funcionalidad, y nos habíamos encontrado con un mensaje de error en determinadas circunstancias:

msf  auxiliary(fakedns_single) >
[-] fakedns: Resolv::ResolvError DNS result has no information for foo.pentester.es
[...]

El problema que identificamos es que el módulo tiene un error cuando intentas resolver contra él un nombre que no existe (foo.pentester.es). Esto es debido a que hemos alterado con un parche guarrindongo el funcionamiento original del módulo, así que ahora nos vemos en situaciones que el desarrollador no pensó. En este caso, la resolución real únicamente se iba a realizar para aquellos nombres que nosotros definiéramos en el "domain bypass", que evidentemente iban a ser dominios existentes, así que no se implementaron medidas que comprobaran si la resolución existe o no.

Como hemos modificado el módulo y ahora no tenemos control sobre los nombres que va a resolver y cuales no, debemos añadir un control de excepciones en la zona del código en la que se realiza la resolución:

begin
        ip = Resolv::DNS.new().getaddress(name).to_s
        answer = Resolv::DNS::Resource::IN::A.new( ip )
rescue ::Exception => e
        next
end

Con este control añadido, vamos a volver a intentar resolver algunos nombres a ver si hemos conseguido que el módulo siga funcionando a pesar de no poder resolver un nombre:

$ dig @127.0.0.1 www.pentester.es
www.pentester.es. 60 IN A 192.168.1.100
dig @127.0.0.1 foo.pentester.es
;foo.pentester.es. IN A
$ dig @127.0.0.1 www.yahoo.com
www.yahoo.com. 60 IN A 98.139.183.24

Perfecto! Ahora está resolviendo correctamente y además no casca, así que ya podemos utilizarlo para analizar las conexiones que queremos.

Esta solución es un poco chapuza, pero es funcional, y nos puede servir para interceptar solo las conexiones que queramos, con algunas limitaciones.

¿Quereis ver la solución buena? Lo veremos en el próximo post.

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.

martes, 20 de marzo de 2012

Hackers

Antes de nada, quiero adelantar que no soy persona a la que le guste escribir posts de opinión ni nada que no tenga "cacharreo" detrás, pero en esta ocasión voy a hacer una excepción que supongo que entendereis si leéis hasta el final.

En la pasada RootedCON, durante uno de los RootedPanels, uno de los moderadores preguntó ¿cuántos de aquí sois hackers? Prácticamente nadie de la audiencia levantó la mano (entre los que me incluyo). El término "Hacker" está siendo empleado por los medios como sinónimo de "Pirata Informático" o "delincuente", y con toda esa carga semántica es normal que nadie quiera levantar la mano.

La definición que más me gusta, no recuerdo donde lo leí o a quien se la escuché, o si se me ocurrió en un momento de inspiración filosófica, pero: El Hacking es el ARTE de hacer que las cosas funcionen de manera diferente a como su creador originalmente pensó. Si os fijáis, este definición no es puramente tecnológica, como otras que he visto, y se puede aplicar a aquella persona que diseña una cadena de entrada que hace que un software ejecute código cuando únicamente debería mostrar una información, pero también se puede aplicar a aquellas personas que hacen tunning de un coche, o a los compañeros de IKEA Hackers, que cogen las piezas de un mueble y las montan de forma que se obtiene algo diferente. Esto para mi es ser un Hacker, tener un conocimiento sobre tu campo suficientemente profundo como para poder hacer Hacking sobre él.

A pesar de esto, son tan malas las connotaciones que se han atribuido al término "Hacker" que los que nos dedicamos a esto empleamos el término "Hacking Ético" para venderlo ¿cómo que ético? ODIO el término "ético" porque asume que el "Hacking" de por si no es ético, algo que es totalmente falso. Es como si algunos atracadores de bancos practicaran atletismo y lo utilizaran para darse a la fuga, y los medios acabaran usando tantas veces el término "atleta" como sinónimo de "delincuente" que los que siempre lo han practicado tuvieran que empezar a decir que practican "Atletismo Ético". Absurdo ¿verdad? ¿Y "cerrajerismo ético"? También hay ladrones que abren cerraduras, y no por ello los medios han "demonizado" a este colectivo.

Pero también es culpa nuestra, porque hemos permitido que lo hagan, porque no les hemos corregido, o porque cuando una persona pregunta ¿quién aquí se considera un hacker? Todos agachamos la cabeza y fortalecemos la sensación de la sociedad de que ser un hacker es algo malo.

Yo soy un hacker, o al menos intento leer, estudiar, practicar todos los días para alcanzar los conocimientos necesarios para poder utilizar las técnicas de hacking. NO soy un delincuente, y ME NIEGO a seguir utilizando el calificativo "Ético" referido a mi trabajo.

¿Te gusta leer absolutamente todo lo que pasa por tus manos? ¿Te gusta saber como funciona todo hasta el más mínimo detalle? Y cuando ves claramente que en determinadas circunstancias podrías hacer que algo funcionara de manera diferente ¿te gusta probar si eres capaz de hacerlo? Amigo mio, eres un hacker.

-----------------------------

En memoria de Hugo Castellano, gran defensor de la comunidad hacker y padre del compañero Nico Castellano, que falleció el pasado sábado, y que nos tuvo que recordar a todos lo que somos y que hay que tener el valor de defender lo que uno es en cualquier circunstancia. Gracias Don Hugo, nunca le olvidaremos. Descanse en Paz.