
Una herramienta de creación de paquetes para Linux.
Pig (que puede entenderse como Packet intruder generator) es una herramienta de creación de paquetes para Linux.
Puedes usar Pig para probar tu IDS/IPS, entre otras cosas.
Pig incluye un conjunto de firmas de ataque conocidas listas para usar y puedes ampliar esta colección
con cosas más específicas según tus necesidades.
Hasta ahora es posible crear firmas IPv4 con capa de transporte basada en TCP, UDP e ICMP.
También puedes crear firmas basadas en el protocolo ARP, además de construir el paquete desde su trama Ethernet.
Si llegaste aquí por mi artículo de 2600 del número SPRING 2016 issue
sigue leyendo las siguientes secciones de documentación porque este pequeño Pig ha ido evolucionando desde entonces.
Es bastante sencillo:
[email protected]:~/src# git clone https://github.com/rafael-santiago/pig pig
[email protected]:~/src# cd pig
[email protected]:~/src/pig# git submodule update --init
Necesitas usar Hefesto para compilar pig. Después de seguir
los pasos para poner Hefesto en funcionamiento en tu sistema, dirígete al subdirectorio pig llamado src y ejecuta
el siguiente comando:
[email protected]:~/src/pig/src# hefesto
Después de este comando deberías encontrar el binario pig en la ruta src/bin. Puedes usar el binario de manera relativa desde
src/bin o instalarlo.
Si por alguna razón tienes problemas de compilación, deberías leer algunos comentarios presentes en BUILD.md.
Para instalarlo debes estar dentro del subdirectorio src y ejecutar:
[email protected]:~/src/pig/src# hefesto --install
Para desinstalarlo, estando dentro del subdirectorio src, debes ejecutar:
[email protected]:~/src/pig/src# hefesto --uninstall
Los archivos pigsty son archivos de texto plano donde puedes definir un conjunto de firmas de paquetes. Hay una sintaxis específica que debe
seguirse. Observa un ejemplo de un archivo pigsty:
[ signature = "Hello",
ip.version = 4,
ip.ihl = 5,
ip.tos = 0,
ip.src = 192.30.70.10,
ip.dst = 192.30.70.3,
ip.protocol = 17,
udp.dst = 1008,
udp.src = 32000,
udp.payload = "Hello!!" ]
Básicamente, todos los datos de la firma deben ir entre corchetes: [ ... ].
Dentro de esta área, la información se proporciona mediante el esquema campo = dato.
Si tienes algo de experiencia con Redes de Computadoras, seguramente la mayoría de los campos listados en la Tabla 1
tienen un significado claro para ti. Debes usar estos campos para crear tus futuras firmas.
Tabla 1: Campos de firma de pig.
Al crear una firma no es necesario especificar todos los datos. Si especificas solo las partes más relevantes del paquete,
las partes restantes se rellenarán con valores predeterminados. Los checksums se siempre recalculan.
Consejo: echa un vistazo al subdirectorio pigsty. Encontrarás muchos archivos de firmas y verás que es
bastante simple definir nuevas.
Sí, es posible. Para usar esta función solo debes especificar los valores listados en la Tabla 2
en los campos de tipo dirección IP.
Tabla 2: IPs por área geográfica.
| Valor a usar |
|---|
Debes usar en cualquier campo de tipo dirección IP el valor user-defined-ip. Ten en cuenta que necesitas usar la
opción de línea de comandos --targets en este caso. Consulta la sección Usando pig para más información.
Si creas archivos pigsty que consideres relevantes más allá de tu propio entorno, abre un pull request para incluir
estos archivos útiles aquí. ¡Gracias de antemano!
El uso de Pig es muy sencillo, siendo necesario proporcionar cuatro opciones básicas:
--signatures--gateway--net-mask--lo-iface¿Quieres saber más sobre cada opción, eh?... Pues vamos allá:
--signatures recibe una lista de rutas de archivos hacia archivos pigsty.--gateway es donde especificas la dirección de tu puerta de enlace. Ten en cuenta que pig genera o al menos intenta generar las tramas ethernet también. Debido a esto, la dirección de la puerta de enlace es bastante importante para componer correctamente los datos de la capa-1.--net-mask para problemas de enrutamiento debe recibir tu máscara de red.--lo-iface es el lugar donde debes informar el nombre de la interfaz de red local que usarás para "drenar" los paquetes generados.--no-gateway indica que ningún paquete se enviará fuera de la red.Suponiendo que queremos generar tráfico basado en DDos:
[email protected]:~# pig --signatures=pigsty/ddos.pigsty\
> --gateway=10.0.2.2\
> --net-mask=255.255.255.0 --lo-iface=eth0
Ahora queremos desordenar todo:
[email protected]:~# pig --signatures=pigsty/ddos.pigsty,pigsty/attackresponses.pigsty,\
> pigsty/badtraffic.pigsty,pigsty/backdoors.pigsty\
> --gateway=10.0.2.2 --net-mask=255.255.255.0 --lo-iface=eth0
Para ello usa la opción --timeout=<milisegundos>
Usa la opción --no-echo.
Usa la opción --targets. Puedes especificar una lista basada en IPs exactas, máscaras IP y CIDRs.
Mira esto:
[email protected]:~# pig --signatures=pigsty/local-mess.pigsty\
> --targets=192.30.70.3,192.30.70.*,192.30.70.0/9\
> --gateway=10.0.2.2\
> --net-mask=255.255.255.0\
> --lo-iface=eth0
Esto es útil cuando las firmas cargadas no enviarán datos fuera de la red actual. Para señalarlo necesitas usar
la opción --no-gateway. Cuando se usa la opción --no-gateway no necesitas especificar la dirección de la puerta de enlace
porque los paquetes no fluirán fuera del segmento actual. Como resultado, informar la máscara de red también se vuelve irrelevante.
Por ejemplo:
[email protected]:~# pig --signatures=pigsty/local_traffic.pigsty --no-gateway --lo-iface=eth2
En el ejemplo anterior, la trama ethernet ya no será responsabilidad de pig. Por esta razón pig no se quejará
de la falta de las opciones --gateway y --net-mask.
La opción --no-gateway es bastante útil en casos donde necesitas generar tráfico ARP. Echa un vistazo a este otro
documento que explica cómo realizar spoofing ARP con pig.
Quizás necesites enviar solo una firma y luego volver al llamador para verificar qué sucedió después. Este tipo de
requisito es común cuando usas esta aplicación como soporte para pruebas de sistema o pruebas unitarias. Por lo tanto, si necesitas
hacer esto, deberías probar la opción --single-test:
[email protected]:~# pig --signature=pigsty/syn-scan.pigsty --targets=127.0.0.1 --single-test\
> --gateway=10.0.2.2 --net-mask=255.255.255.0 --lo-iface=eth0
Después de ejecutar este comando, pig seleccionará solo una firma del archivo syn-scan.pigsty e intentará enviarla y luego saldrá.
Si ocurre algún error durante el proceso, pig saldrá con código de salida igual a 1; de lo contrario, pig saldrá
con código de salida igual a 0.
El modo de operación básico de pig se trata de un bucle infinito que escupe toneladas de paquetes a la red respetando un
tiempo de espera previamente definido.
Puedes definir cómo pig recorre los paquetes cargados para enviarlos usando la opción --loop=<modo>. Hasta ahora
los modos son dos: random (el predeterminado) y sequential.
El modo sequential volverá a iterar las firmas cuando llegue al final de la lista de firmas de paquetes cargadas.
Las subtareas son tareas menores útiles relacionadas con la creación de paquetes que vienen incluidas en pig para ayudarte
en tu sesión de creación. Estas tareas se pueden acceder mediante la opción --sub-task=<nombre-de-tarea>.
Debido a que prácticamente son subprogramas, las subtareas tienen sus propias idiosincrasias y, por lo tanto,
los detalles sobre ellas se encuentran en su propio manual. Echa un vistazo a la Tabla 3 para continuar.
Tabla 3: Las subtareas de pig.
Hasta ahora puedes construir paquetes basados en IPv4 con UDP o TCP en su capa de transporte. También puedes construir
paquetes ARP.
Sin embargo, aún puedes construir paquetes comenzando desde la trama Ethernet. Lo bueno de esto es la posibilidad
de construir virtualmente cualquier cosa sobre la carga útil de Ethernet.
Por ejemplo, aunque pig hasta ahora no ofrece soporte para la construcción de IPv6 "cocinado", aún puedes
construirlo usando un pigsty basado en Ethernet en bruto. Mira:
[ eth.hwdst = "5C:AC:4C:AA:F5:B5",
eth.hwsrc = "08:95:2A:AD:D6:4F",
eth.type = 0x86DD,
eth.payload = "\x60\x00\x00\x00\x00\x20\x3a\xff\xfe\x80\x00\x00\x00\x00\x00\x00\x0a\x95\x2a\xff\xfe\xad\xd6\x4f\xfe\x80\x00\x00\x00\x00\x00\x00\x55\x51\x00\xc2\x18\x0f\xdb\x46\x88\x00\x32\x01\xe0\x00\x00\x00\xfe\x80\x00\x00\x00\x00\x00\x00\x0a\x95\x2a\xff\xfe\xad\xd6\x4f\x02\x01\x08\x95\x2a\xad\xd6\x4f",
signature = "IPv6 from Sparta" ]
Teniendo en cuenta que la inclusión de las direcciones MAC de destino y origen dentro de un "pigsty Ethernet" es
opcional, podemos realizar el trabajo incluso sin usar ningún campo de relleno.
Esto es útil cuando tienes que probar nuevos protocolos en tu entorno, entre otras cosas divertidas y anómalas. De esta manera en bruto,
pig puede seguir siendo útil para ti.
Guarda los siguientes datos como "oink.pigsty":
[ signature = "oink",
ip.version = 4,
ip.ihl = 5,
ip.tos = 0,
ip.src = 127.0.0.1,
ip.dst = user-defined-ip,
ip.protocol = 17,
udp.dst = 1008,
udp.src = 32000,
udp.payload = "Oink!!\n" ]
En otro tty ejecuta netcat en modo UDP escuchando conexiones en el puerto 1008:
[email protected]:~# nc -u -l -p 1008
Ahora ejecuta pig usando el archivo "oink.pigsty", informando como objetivo el loopback:
[email protected]:~# pig --signatures=oink.pigsty --targets=127.0.0.1\
> --gateway=10.0.2.2 --net-mask=255.255.255.0 --lo-iface=eth0
El netcat debería comenzar a recibir varios oinks y... sí, ¡felicidades! ¡pig está funcionando en tu sistema! ;)
Intenta snifear tu red para obtener más información sobre estos paquetes UDP que están fluyendo por tus interfaces...
¡Diviértete!
| Campo | Significado | Protocolo | Tipo de dato | Definición de ejemplo |
|---|
signature | El nombre de la firma | - | string | signature = "Udp flood" |
eth.hwdst | MAC destino Ethernet | Ethernet | MAC | eth.hwdst = "00:de:ad:be:ef:00" |
eth.hwsrc | MAC origen Ethernet | Ethernet | MAC | eth.hwsrc = "00:de:ad:be:ef:00" |
eth.type | Tipo Ether | Ethernet | número | eth.type = 0x0800 |
eth.payload | Carga útil Ethernet | Ethernet | string | eth.payload = "f\x00ob\x04r" |
ip.version | Versión IP | IP | número | ip.version = 4 |
ip.ihl | Longitud del encabezado IP | IP | número | ip.ihl = 5 |
ip.tos | Tipo de servicio | IP | número | ip.tos = 0 |
ip.tlen | Longitud total | IP | número | ip.tlen = 20 |
ip.id | ID del paquete | IP | número | ip.id = 0xbeef |
ip.flags | Banderas IP | IP | número | ip.flags = 4 |
ip.offset | Desplazamiento de fragmento | IP | número | ip.offset = 0 |
ip.ttl | Tiempo de vida | IP | número | ip.ttl = 64 |
ip.protocol | Protocolo | IP | número | ip.protocol = 6 |
ip.checksum | Checksum | IP | número | ip.checksum = 0 |
ip.src | Dirección origen | IP | dirección IP | ip.src = 192.30.70.3 |
ip.dst | Dirección destino | IP | dirección IP | ip.dst = 192.30.70.3 |
ip.payload | Carga útil IP | IP | string | ip.payload = "\x01\x02" |
tcp.src | Puerto origen | TCP | número | tcp.src = 80 |
tcp.dst | Puerto destino | TCP | número | tcp.dst = 21 |
tcp.seqno | Número de secuencia | TCP | número | tcp.seqno = 10202 |
tcp.ackno | Número de acuse de recibo | TCP | número | tcp.ackno = 10200 |
tcp.size | Longitud TCP | TCP | número | tcp.size = 4 |
tcp.reserv | Campo reservado TCP | TCP | número | tcp.reserv = 0 |
tcp.urg | Bandera urg. TCP | TCP | bit | tcp.urg = 0 |
tcp.ack | Bandera ack. TCP | TCP | bit | tcp.ack = 1 |
tcp.psh | Bandera psh. TCP | TCP | bit | tcp.psh = 0 |
tcp.rst | Bandera rst. TCP | TCP | bit | tcp.rst = 0 |
tcp.syn | Bandera syn. TCP | TCP | bit | tcp.syn = 0 |
tcp.fin | Bandera fin. TCP | TCP | bit | tcp.fin = 0 |
tcp.wsize | Tamaño de ventana TCP | TCP | número | tcp.wsize = 0 |
tcp.checksum | Checksum | TCP | número | tcp.checksum = 0 |
tcp.urgp | Puntero urgente | TCP | número | tcp.urgp = 0 |
tcp.payload | Carga útil | TCP | string | tcp.payload = "\x01abc" |
udp.src | Puerto origen | UDP | número | udp.src = 53 |
udp.dst | Puerto destino | UDP | número | udp.dst = 7 |
udp.size | Longitud UDP | UDP | número | udp.size = 8 |
udp.checksum | Checksum | UDP | número | udp.checksum = 0 |
udp.payload | Carga útil | UDP | número | udp.payload = "boo!" |
icmp.type | Tipo ICMP | ICMP | número | icmp.type = 0 |
icmp.code | Código ICMP | ICMP | número | icmp.code = 0 |
icmp.checksum | Checksum | ICMP | número | icmp.checksum = 0 |
icmp.payload | Carga útil | ICMP | string | icmp.payload = "ping!" |
arp.hwtype | Tipo de hardware ARP | ARP | número | arp.hwtype = 0x1 |
arp.ptype | Tipo de protocolo ARP | ARP | número | arp.ptype = 0x0800 |
arp.hwlen | Longitud de hardware ARP | ARP | número | arp.hwlen = 6 |
arp.opcode | Código de operación ARP | ARP | número | arp.opcode = 2 |
arp.hwsrc | Dirección hw origen ARP | ARP | MAC | arp.hwsrc = "de:ad:be:ef:0:0" |
arp.psrc | Dirección proto origen ARP | ARP | dirección IP | arp.psrc = 192.30.70.3 |
arp.hwdst | Dirección hw destino ARP | ARP | MAC | arp.hwdst = "de:ad:be:ef:0:0" |
arp.pdst | Dirección proto destino ARP | ARP | dirección IP | arp.pdst = 192.30.70.3 |
| Significado |
|---|
north-american-ip | Direcciones IP de Norteamérica |
south-american-ip | Direcciones IP de Sudamérica |
asian-ip | Direcciones IP de Asia |
european-ip | Direcciones IP de Europa |
| Subtarea | ¿Qué hace? | Manual |
|---|
pcap-import | Importa paquetes de un archivo PCAP a un archivo pigsty | cat doc/pcap-import.md |
shell | Ejecuta pig en modo interactivo | cat doc/shell.md |