Estamos acostumbrados a ejecutar ataques de reconocimiento y escaneo de puertos desde herramientas como Nmap de una forma casi automática, hasta el punto en el que muchas ocasiones se suele caer en el “olvido” de los tipos de escaneo que pueden llevarse a cabo con dichas herramientas y en que circunstancias es apropiado su uso. Los tipos de escaneos que pueden llevarse a cabo desde Nmap, también se pueden llevar a cabo desde Scapy simplemente manipulando los campos de los paquetes que se envían a los objetivos, la ventaja de tener este conocimiento sobre el uso clásico de Nmap, es que como se ha comentado desde la primera publicación de esta serie, con Scapy tenemos las respuestas de los objetivos en estado “crudo” lo que quiere decir que el trabajo interpretativo se deja plenamente al programador, mientras que con Nmap, solamente se obtienen estados deterministas que son Abierto|Cerrado|Filtrado y que en muchas ocasiones resultan confusos y no dan demasiada información de lo que realmente ha sucedido con un puerto determinado.

Ahora, para refrescar un poco la memoria y los conceptos, se hablará sobre los escaneos típicos y como se pueden llevar a cabo desde Scapy.

Escaneo XMAS

Se trata de un escaneo en el que los paquetes que se le envían al objetivo tienen las flags “PUSH”, “URG” y “FIN” habilitadas, con lo cual se realiza un escaneo silencioso, ya que realmente no se establece ninguna conexión como ocurre cuando se envía un paquete con “SYN” habilitado. Con este tipo de escaneo pueden ocurrir dos cosas:

  1. La respuesta por parte del destinatario será un paquete con la flag RST indicando que la conexión debe resetearse dado que el puerto se encuentra cerrado

  2. No se recibirán respuestas, dado que el paquete será ignorado, esto indica que el puerto se encuentra abierto

Se trata de un escaneo bastante simple de llevar a cabo y también muy fácil de detectar por un IDS/IPS o un Firewall, lo que quiere decir, que si un paquete utilizando esta combinación flags (PUSH, URG y FIN) es capturado por un Firewall/IDS/IPS no habrá ninguna respuesta, con lo cual se producirá un falso positivo, ya que como se explico anteriormente, se asume que si no se tiene una respuesta el puerto esta abierto, lo cual puede ser falso en el caso de que el paquete haya sido filtrado.

Ahora bien, para aplicar estos Flags desde Scapy basta con enviar un paquete como el siguiente utilizando la función sr

>ans,unans = sr(IP(dst=»192.168.1.1″)/TCP(dport=22,flags=»FPU»))

Con lo anterior, se realiza un escaneo XMAS enviando el paquete al puerto 22 de la máquina 192.168.1.1

Escaneo ACK

Con escaneo XMAS se puede determinar fácilmente y de forma silenciosa si un puerto se encuentra abierto, sin embargo también es fácilmente detectado por mecanismos de defensa como Firewalls, en estos casos, es posible utilizar un escaneo ACK, que permite determinar de una forma más o menos precisa si un determinado objetivo tiene instalado un Firewall que filtre las peticiones enviadas. Un escaneo del tipo ACK no determina si un puerto se encuentra abierto o cerrado, simplemente determina si se encuentra filtrado o no (que no es lo mismo que abierto o cerrado). Su funcionamiento se basa en que, cuando se envía un paquete ACK a un destino determinado, este en situaciones normales debe responder con un paquete RST indicando que no se ha iniciado aun una conexión con el envío de un paquete SYN inicial, que es lo que realmente espera recibir el destinatario y en dichos casos se suele afirmar que el puerto se encuentra no filtrado, sin embargo si el destinatario tiene un firewall o algún mecanismo de filtrado o inspección de paquetes, lo que ocurrirá será que el paquete enviado por el atacante es capturado e ignorado, con lo cual no se obtendrá ninguna respuesta, en tales casos se puede determinar que el puerto se encuentra filtrado.

Desde scapy es fácil efectuar este tipo de escaneos, tal como se enseña a continuación

>>>ans,unans = sr(IP(dst=»www.google.com»)/TCP(dport=[80],flags=»A»))

Con este sencillo paquete al destino www.google.com en el puerto 80 con la flag “A” activada, es posible determinar si dicho puerto se encuentra filtrado o no. Posteriormente para analizar las respuestas solamente es necesario utilizar los objetos ans y unans

</p>
<p align="JUSTIFY"><strong>>>> for s,r in ans:</strong></p>
<p align="JUSTIFY"><strong>… if s[TCP].dport == r[TCP].sport:</strong></p>
<p align="JUSTIFY"><strong>… print str(s[TCP].dport) + ‘No filtrado'</strong></p>
<p align="JUSTIFY"><strong>… </strong></p>
<p align="JUSTIFY">

Escaneo ARP (Ping)

Con este tipo de escaneo, es posible reconocer de una forma rápida y fiable, cuales hosts se encuentran activos en un segmento de red determinado, es bastante útil para localizar máquinas activas y detectar cuales no lo están, sin embargo, la desventaja que tiene es que es muy “ruidoso” y genera demasiado trafico que puede alertar a un administrador de red. Desde herramientas como Nmap es muy fácil de utilizar y desde Scapy también lo es, simplemente es necesario utilizar un paquete Ether con la dirección de broadcast y posteriormente un paquete ARP con el rango de direcciones IP que se espera escanear, por ejemplo

>>>ans,unans=srp(Ether(dst=»ff:ff:ff:ff:ff:ff»)/ARP(pdst=»192.168.1.0/24″),timeout=2)

Con lo anterior, simplemente se ha definido que el paquete Ether será destinado a la dirección de broadcast y el paquete ARP a todas las direcciones IP del segmento de red 192.168.1.* (partiendo desde la máquina 0 hasta la 255).

Ahora bien, para analizar las respuestas recibidas, solamente hace falta recorrer los objetos ans y unans

>>>ans.summary(lambda (s,r): r.sprintf(«%Ether.src% %ARP.psrc%») )

Otra forma de realizar este mismo tipo de escaneo con Scapy, es utilizando la función arping() la cual recibe como parámetro la dirección o conjunto de direcciones IP que se desea chequear.

>>>arping(«192.168.1.0/24»)

Begin emission:

*Finished to send 256 packets.

Received 1 packets, got 1 answers, remaining 255 packets

64:68:0c:45:71:88 192.168.1.1

(<ARPing: TCP:0 UDP:0 ICMP:0 Other:1>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:255>)

Escaneo ICMP (Ping)

Este tipo de escaneo es muy similar al escaneo utilizando paquetes ARP, solamente que en esta ocasión, simplemente se utilizan paquetes IP y el protocolo ICMP para el reconocimiento de hosts activos en un segmento de red determinado (o conjunto definido de máquinas). Hacer este escaneo en Scapy puede ser tan sencillo como lo siguiente

>>> ans,unans=sr(IP(dst=»192.168.1.1-254″)/ICMP())

Esto enviará paquetes ICMP a todas las máquinas del segmento de red 192.168.1.* desde la 1 hasta la 254

Para consultar las máquinas que han respondido a las peticiones en este rango:

>>>ans.summary(lambda (s,r): r.sprintf(«%IP.src%») )

Con esto se obtienen las direcciones IP de aquellas máquinas que han respondido al paquete ICMP enviado.

Escaneo TCP /UDP (Ping)

Se trata de un tipo de escaneo que puede utilizarse en el caso de que los pings con ICMP no sean permitidos o se encuentren bloqueados en el segmento de red que se desea investigar. En el caso de un escaneo Ping TCP, se pueden utilizar paquetes con la flag SYN para establecer un 3-way handshake con el destino, en Scapy esto se puede conseguir de la siguiente forma

>>>ans,unans=sr( IP(dst=»192.168.1.*»)/TCP(dport=80,flags=»S») )

Escaneo IP (Ping)

Un escaneo por IP, del mismo modo que sucede con Nmap, permite identificar dentro de un rango de direcciones IP, cuales máquinas se encuentran activas y cuales no. Se diferencia de los escaneos anteriores, en el sentido de que el escaneo IP, se lleva a cabo en las capas bajas del modelo de referencia OSI. Para hacer un escaneo IP en Scapy se utiliza simplemente un paquete IP y la opción protocol de la siguiente manera.

>>>ans,unans=sr(IP(dst=»192.168.1.1″,proto=(0,255))/”SCAN”,retry=2)

TAREAS DE ADMINISTRACIÓN UTILIZANDO SCAPY

Es posible ejecutar scripts con Python muy simples utilizando Scapy, de tal forma que sea posible detectar posibles amenazas (desde la perspectiva de un administrador de Red) o ejecutar ataques activos (desde la perspectiva de un atacante)

Descubriendo de servidores DHCP

Aunque no se trata de un escaneo común, es bastante útil ya que permite determinar si existe algún servidor DHCP en el segmento de red local, de esta forma un administrador de red puede saber cuales servidores DHCP se encuentran en ejecución en su red y determinar cuales son “suyos” y cuales se están ejecutando posiblemente sin autorización.

>>> conf.checkIpaddr= False

>>> f,h=get_if_raw_hwaddr(conf.iface)

>>>dhcp_discover=Ether(dst=»ff:ff:ff:ff:ff:ff»)/IP(src=»0.0.0.0″,dst=»255.255.255.255″)/UDP(sport=68,dport=67)/BOOTP(chaddr=h)/DHCP(options=[(«message-type»,»discover»),»end»])

>>> ans, unans = srp(dhcp_discover,multi=True)

En primer lugar, la propiedad checkIpaddr ha sido asignada con el valor de False, principalmente porque Scapy por defecto se asegura que las replicas sean desde la misma dirección IP a la que el “estimulo” fue enviado, dado que la dirección utilizada para el estimulo ha sido la dirección de broadcast, respuestas desde otras direcciones (como por ejemplo la 192.168.1.1) serán descartadas, situación que se evita estableciendo a False la propiedad anteriormente indicada.

Como se puede apreciar la pila de paquetes están destinadas a la dirección de broadcast y se ha utilizado la función get_if_raw_hwaddr para componer un paquete del tipo BOOTP que permite definir la(s) dirección(es) MAC de origen para la petición DHCP, posteriormente, se crea un paquete DHCP que toma como insumo todas las opciones de los paquetes que se han ido apilando y ademas, incluye dentro de sus opciones, que incluya los tipos de mensaje “discover”.

Por otro lado, la opción multi=True en la función srp permite que Scapy pueda esperar por más respuestas después de que la primera ha sido recibida.

Ataque DHCP Starvation con Scapy

Se trata de un tipo de ataque que entra en la categoría de ataques por denegación de servicio, que consiste en el envío constante de peticiones DHCP Request con direcciones MAC falsas, esta situación hace que el servidor DHCP “agote” su espacio de direcciones IP disponibles para posterior asignación a futuros clientes. Este tipo de ataques normalmente suelen venir acompañados de ataques MITM implantando un Fake DHCP Server con el fin de capturar todas las peticiones DHCP de los clientes en la red interna. Con Scapy llevar a cabo este tipo de ataque es muy simple, siguiendo la misma linea de la explicación anterior sobre el descubrimiento de servidores DHCP, se puede generar de forma aleatoria diferentes MAC que serán incluidas en los paquetes.

>>> conf.checkIpaddr= False

>>>dhcp_discover=Ether(dst=»ff:ff:ff:ff:ff:ff»)/IP(src=»0.0.0.0″,dst=»255.255.255.255″)/UDP(sport=68,dport=67)/BOOTP(chaddr=RandString(12,’0123456789abcdef’))/DHCP(options=[(«message-type»,»discover»),»end»])

>>> sendp(dhcp_discover,loop=1)

Con las lineas anteriores, se puede llevar a cabo un ataque de DHCP Starvation muy fácilmente, como se puede apreciar las lineas anteriores no son muy distintas de las que se han empleado en la detección de servidores DHCP en el segmento de red, excepto por dos cosas:

  1. El paquete BOOTP utiliza una cadena aleatoria para definir la dirección MAC que será utilizada para la petición DHCP

  2. Se crea un ciclo indefinido de peticiones DHCP contra el servidor (hasta que el atacante decida interrumpir el proceso manualmente).

Se utiliza la función RandString de python para la generación aleatoria de 12 caracteres usando solamente los caracteres que son validos para una dirección MAC (Es decir, aquellos que se incluyen en código Hexadecimal)

En una próxima publicación sobre esta serie, se hablará un poco más sobre tareas de administración y ataques en entornos de red con Scapy.