Una de las mejores formas de entender un sistema o una arquitectura de servicios, es simplemente enviando paquetes (correctamente formados y mal formados) para posteriormente analizar los paquetes de respuestas. En concreto resulta de especial interés saber cuales son los mensajes que el servicio ha enviado como respuesta a un petición previa, así como también buscar cualquier otra información que revele más sobre el emisor de dichos paquetes, en esencia el análisis de paquetes y su posterior interpretación es el primer paso para realizar procedimientos de descubrimiento y recolección de información en entornos de red, esto es posible conseguirlo en Scapy gracias a las funciones explicadas en la publicación anterior, tales como send, sendp, sr, srp, sr1, etc.
Ahora es el momento de utilizar estas funciones para realizar tareas concretas (como por ejemplo, escanear puertos) y entender como son frecuentemente utilizadas. En primer lugar es importante comprender que cuando se usan estos comandos, el orden en el que se especifican los paquetes es importante, por ejemplo si se ejecuta el siguiente comando se enviaran 2 paquetes destinados a la dirección 192.168.1.1 en los puertos 21 y 22
>>>sr(IP(dst=»192.168.1.1″)/TCP(dport=[21,22])) Begin emission: ….*Finished to send 2 packets. * Received 6 packets, got 2 answers, remaining 0 packets (<Results: TCP:2 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>) |
Como puede verse, el comando ha retornado 2 paquetes TCP con respuestas por parte del destino (192.168.1.1), sin embargo si el orden de estos paquetes fuese distinto, aunque contaran con las mismas propiedades el resultado seria el siguiente:
>>>sr(TCP(dport=[21,22])/IP(dst=»192.168.1.1″)) Begin emission: WARNING: Mac address to reach destination not found. Using broadcast. .WARNING: No IP underlayer to compute checksum. Leaving null. .WARNING: Mac address to reach destination not found. Using broadcast. WARNING: No IP underlayer to compute checksum. Leaving null. Finished to send 2 packets. ……………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………..^C Received 397 packets, got 0 answers, remaining 2 packets (<Results: TCP:0 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:2 UDP:0 ICMP:0 Other:0>) |
La capa TCP se ha definido por encima de la capa IP, lo que ha dado como resultado en primer lugar algunos mensajes de WARNING indicando que no se ha declarado una capa IP subyacente y por otro lado, las respuestas de dichos paquetes nunca son capturadas, por lo que hay que interrumpir el comando dado que se entra en un ciclo indefinido, se trata de un error bastante comun, especialmente cuando no se entiende el modelo TCP/IP y tal como puede apreciarse, el listado de paquetes sin respuesta esta compuesto por 2 paquetes TCP. La razón de esto es que se deben establecer en primera instancia los tipos de paquetes que correspondan a las capas más bajas del modelo TCP/IP para que Scapy pueda componer correctamente los paquetes que intenta enviar, en una publicación anterior se ha se ha enseñado la siguiente imagen, nuevamente se vuelve a enseñar dado que es importante conocerla y comprenderla.
Ahora bien, para realizar diferentes tipos de escaneos, se puede utilizar el campo “flags” de cualquier paquete del tipo TCP, por ejemplo para ejecutar un escaneo SYN
>>> sr(IP(dst=»192.168.1.1″)/TCP(dport=[21,22], flags=»S»)) Begin emission: …*Finished to send 2 packets. * Received 5 packets, got 2 answers, remaining 0 packets (<Results: TCP:2 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>) >>> ans,nans=_ >>> ans.show() 0000 IP / TCP 192.168.1.33:ftp_data > 192.168.1.1:ftp S ==> IP / TCP 192.168.1.1:ftp > 192.168.1.33:ftp_data SA / Padding 0001 IP / TCP 192.168.1.33:ftp_data > 192.168.1.1:ssh S ==> IP / TCP 192.168.1.1:ssh > 192.168.1.33:ftp_data SA / Padding |
Como se puede apreciar, en los dos paquetes de respuesta se encuentra establecida la flag “SA” (SYN/ACK) lo que indica que el servicio remoto se encuentra activo. En el campo flags se puede establecer cualquiera de los valores posibles soportados en los paquetes TCP, por ejemplo “PA” (Push) , “UA” (Urgent), “SA” (SYN/ACK), “RA” (RESET), “A” (ACK)
Por otro lado, también es posible definir un rango de puertos de forma secuencial o especifica utilizando los caracteres “[“ y “]” para definir un conjunto de valores o “(“ y “)” para definir un rango secuencial de valores desde un rango inicial hasta un tope, de esta forma se puede realizar un escaneo de puertos por rangos o por puertos concretos
>>> sr(IP(dst=»192.168.1.1″)/TCP(sport=RandShort(),dport=[440:443],flags=»S»)) Begin emission: ……*..*…*.Finished to send 4 packets. * Received 16 packets, got 4 answers, remaining 0 packets (<Results: TCP:4 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>) >>> ans,unans = _ >>> ans.summary() IP / TCP 192.168.1.33:6623 > 192.168.1.1:440 S ==> IP / TCP 192.168.1.1:440 > 192.168.1.33:6623 RA / Padding IP / TCP 192.168.1.33:49297 > 192.168.1.1:441 S ==> IP / TCP 192.168.1.1:441 > 192.168.1.33:49297 RA / Padding IP / TCP 192.168.1.33:9669 > 192.168.1.1:442 S ==> IP / TCP 192.168.1.1:442 > 192.168.1.33:9669 RA / Padding IP / TCP 192.168.1.33:58570 > 192.168.1.1:https S ==> IP / TCP 192.168.1.1:https > 192.168.1.33:58570 RA / Padding >>> ans.summary( lambda(s,r): r.sprintf(«%TCP.sport% \t %TCP.flags%») ) 440 RA 441 RA 442 RA https RA >>> sr(IP(dst=»192.168.1.1″)/TCP(sport=RandShort(),dport=(10,25),flags=»S»)) Begin emission: ……*…***..*.***……*..*.*.*.*…*…*.Finished to send 16 packets. * Received 46 packets, got 16 answers, remaining 0 packets (<Results: TCP:16 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>) >>> ans,unans = _ >>> ans.summary( lambda(s,r): r.sprintf(«%TCP.sport% \t %TCP.flags%») ) 10 RA systat RA 12 RA daytime RA 14 RA netstat RA 16 RA qotd RA msp RA chargen RA ftp_data RA ftp SA ssh SA telnet SA 24 RA smtp RA |
Probablemente lo más interesante de los comandos anteriores ha sido la capacidad de utilizar puertos específicos para el escaneo y rangos de puertos, además del uso de algunas funciones para ordenar y visualizar la información retornada, en este caso, se ha utilizado la función “lambda” y sprintf para listar los servicios y las flags retornadas en las repuestas.
En la próxima publicación se hablará un poco más sobre funciones avanzadas en Scapy.