
Uma ferramenta de criação de pacotes para Linux.
Pig (que pode ser entendido como Packet intruder generator) é uma ferramenta Linux de criação de pacotes.
Você pode usar Pig para testar seu IDS/IPS entre outras coisas.
Pig traz um monte de assinaturas de ataque conhecidas prontas para uso e você pode expandir essa coleção
com coisas mais específicas de acordo com suas necessidades.
Até agora é possível criar assinaturas IPv4 com camada de transporte baseada em TCP, UDP e ICMP.
Você também pode criar assinaturas baseadas no protocolo ARP, além de montar o pacote desde seu quadro Ethernet.
Se você chegou aqui pelo meu artigo da 2600 da edição SPRING 2016 número, continue lendo as próximas seções da documentação porque este pequeno Pig tem evoluído desde então.
É bem simples:
[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
Você precisa usar o Hefesto para compilar pig. Após seguir
os passos para colocar Hefesto funcionando no seu sistema. Vá para o subdiretório pig chamado src e execute
o seguinte comando:
[email protected]:~/src/pig/src# hefesto
Após este comando, você deve encontrar o binário pig no caminho src/bin. Você pode usar o binário relativamente a partir de
src/bin ou instalá-lo.
Se por algum motivo você estiver tendo problemas de compilação, tente ler alguns comentários presentes em BUILD.md.
Para instalar você precisa estar dentro do subdiretório src e chamar:
[email protected]:~/src/pig/src# hefesto --install
Para desinstalar, estando dentro do subdiretório src, você deve chamar:
[email protected]:~/src/pig/src# hefesto --uninstall
Arquivos Pigsty são arquivos de texto simples onde você pode definir um conjunto de assinaturas de pacotes. Há uma sintaxe específica a ser seguida. Veja um exemplo de um arquivo 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!!" ]
Basicamente, todos os dados da assinatura devem estar entre colchetes: [ ... ].
Dentro desta área, a informação é fornecida pelo esquema field = data.
Se você tem alguma experiência com Redes de Computadores, certamente a maioria dos campos listados na Tabela 1 tem um significado forte para você. Você deve usar esses campos para criar suas futuras assinaturas.
Tabela 1: Os campos de assinatura do pig.
Ao criar uma assinatura, você não precisa especificar todos os dados. Se você especificar apenas as partes mais relevantes do pacote, as partes restantes serão preenchidas com valores padrão. As checksums são sempre recalculadas.
Dica: dê uma olhada no subdiretório pigsty. Você encontrará muitos arquivos de assinatura e verá que é bem simples definir novos.
Sim, é possível. Para usar este recurso, você só precisa especificar os valores listados na Tabela 2 em campos do tipo ip address.
Tabela 2: IPs por área geográfica.
| Valor a usar |
|---|
Em qualquer campo do tipo ip address você deve usar user-defined-ip como valor. Observe que você precisa usar a opção de linha de comando --targets neste caso. Veja a seção Usando pig para mais informações.
Se você criar arquivos pigsty que julgar relevantes além do seu próprio ambiente, abra um pull request para incluir esses arquivos úteis aqui. Desde já agradeço!
O uso do Pig é muito direto, sendo necessário fornecer quatro opções básicas que são:
--signatures--gateway--net-mask--lo-ifaceQuer saber mais sobre cada opção, hein?... Então vamos lá:
--signatures recebe uma lista de caminhos de arquivos para arquivos pigsty.--gateway é onde você especifica o endereço do seu gateway. Esteja ciente de que pig também gera ou pelo menos tenta gerar os quadros ethernet. Por isso, o endereço do gateway é bastante importante para compor corretamente os dados da camada 1.--net-mask para fins de roteamento deve receber sua máscara de rede.--lo-iface é o lugar onde você deve informar o nome da interface de rede local que usará para "drenar" os pacotes gerados.--no-gateway indica que nenhum pacote será enviado para fora da rede.Supondo que queremos gerar tráfego baseado em DDoS:
[email protected]:~# pig --signatures=pigsty/ddos.pigsty\
> --gateway=10.0.2.2\
> --net-mask=255.255.255.0 --lo-iface=eth0
Agora queremos bagunçar tudo:
[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 isso use a opção --timeout=<millisecs>
Use a opção --no-echo.
Use a opção --targets. Você pode especificar uma lista baseada em IPs exatos, máscaras de IP e CIDRs.
Veja:
[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
Isso é útil quando as assinaturas carregadas não enviarão dados para fora da rede atual. Para sinalizar isso, você precisa usar a opção --no-gateway. Quando a opção --no-gateway é usada, você não precisa especificar o endereço do gateway porque os pacotes não fluirão para fora do segmento atual. Como resultado, informar a máscara de rede também se torna irrelevante.
Por exemplo:
[email protected]:~# pig --signatures=pigsty/local_traffic.pigsty --no-gateway --lo-iface=eth2
No exemplo acima, o quadro ethernet não será mais responsabilidade do pig. Por esta razão, pig não reclamará da falta das opções --gateway e --net-mask.
A opção --no-gateway é bastante útil nos casos em que você precisa gerar tráfego ARP. Dê uma olhada neste outro documento explicando como realizar ARP spoofing com pig.
Talvez você precise enviar apenas uma assinatura e então retornar ao chamador para verificar o que aconteceu depois. Esse tipo de requisito é comum quando você usa esta aplicação como suporte para testes de sistema ou testes unitários. Então, se você precisa fazer isso, tente usar a opção --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
Após executar este comando, pig selecionará apenas uma assinatura do arquivo syn-scan.pigsty e tentará enviá-la e então sairá. Se algum erro ocorrer durante o processo, pig sairá com código de saída igual a 1, caso contrário, pig sairá com código de saída igual a 0.
O modo de operação básico do pig é um loop infinito que cospe toneladas de pacotes na rede respeitando um timeout previamente definido.
Você pode definir como pig percorre os pacotes carregados para enviá-los usando a opção --loop=<mode>. Até agora são dois modos: random (o padrão) e sequential.
O modo sequential irá reiterar as assinaturas quando chegar ao fim da lista de assinaturas de pacotes carregadas.
As sub-tarefas são tarefas menores úteis relacionadas à criação de pacotes que são enviadas junto com pig para ajudá-lo em sua sessão de criação. Essas tarefas podem ser acessadas usando a opção --sub-task=<task-name>.
Pelo fato de praticamente serem subprogramas, as sub-tarefas têm suas próprias idiossincrasias e, por isso, os detalhes sobre elas seguem em seu próprio manual. Dê uma olhada na Tabela 3 para acompanhar.
Tabela 3: As sub-tarefas do pig.
Até agora você pode montar pacotes baseados em IPv4 com UDP ou TCP em sua camada de transporte. Você também pode montar pacotes ARP.
No entanto, você ainda pode montar pacotes começando pelo quadro Ethernet. O legal disso é a possibilidade de montar virtualmente qualquer coisa acima do payload do Ethernet.
Por exemplo, mesmo que pig até agora não ofereça suporte para montagem de IPv6 cozinhado, você ainda pode montá-lo usando um pigsty baseado em Ethernet bruto. Veja:
[ 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" ]
Considerando que a inclusão dos endereços MAC de destino e origem dentro de um "pigsty Ethernet" é opcional, podemos realizar o trabalho mesmo sem usar nenhum campo extra.
É bom quando você precisa testar novos protocolos em seu ambiente, entre outras coisas anômalas e divertidas. Desta forma bruta, pig pode continuar sendo útil para você.
Salve os seguintes dados 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" ]
Em outro tty execute o netcat no modo UDP ouvindo por conexões na porta 1008:
[email protected]:~# nc -u -l -p 1008
Agora execute pig usando o "oink.pigsty", informando como alvo o 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
O netcat deve começar a receber vários oinks e... sim, parabéns!! pig está funcionando no seu sistema! ;)
Tente farejar sua rede para obter mais informações sobre esses pacotes UDP que estão fluindo pelas suas interfaces...
Divirta-se!
| Campo | Significa | Protocolo | Tipo de dado | Exemplo de definição |
|---|
signature | O nome da assinatura | - | string | signature = "Udp flood" |
eth.hwdst | MAC de destino Ethernet | Ethernet | MAC | eth.hwdst = "00:de:ad:be:ef:00" |
eth.hwsrc | MAC de origem Ethernet | Ethernet | MAC | eth.hwsrc = "00:de:ad:be:ef:00" |
eth.type | Tipo Ether | Ethernet | número | eth.type = 0x0800 |
eth.payload | Payload Ethernet | Ethernet | string | eth.payload = "f\x00ob\x04r" |
ip.version | Versão IP | IP | número | ip.version = 4 |
ip.ihl | Tamanho do cabeçalho Internet | IP | número | ip.ihl = 5 |
ip.tos | Tipo de serviço | IP | número | ip.tos = 0 |
ip.tlen | Comprimento total | IP | número | ip.tlen = 20 |
ip.id | ID do pacote | IP | número | ip.id = 0xbeef |
ip.flags | Flags IP | IP | número | ip.flags = 4 |
ip.offset | Deslocamento de fragmento | IP | número | ip.offset = 0 |
ip.ttl | Tempo 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 | Endereço de origem | IP | endereço IP | ip.src = 192.30.70.3 |
ip.dst | Endereço de destino | IP | endereço IP | ip.dst = 192.30.70.3 |
ip.payload | Payload IP bruto | IP | string | ip.payload = "\x01\x02" |
tcp.src | Porta de origem | TCP | número | tcp.src = 80 |
tcp.dst | Porta de destino | TCP | número | tcp.dst = 21 |
tcp.seqno | Número de sequência | TCP | número | tcp.seqno = 10202 |
tcp.ackno | Número de confirmação | TCP | número | tcp.ackno = 10200 |
tcp.size | Comprimento TCP | TCP | número | tcp.size = 4 |
tcp.reserv | Campo reservado TCP | TCP | número | tcp.reserv = 0 |
tcp.urg | Flag urg. TCP | TCP | bit | tcp.urg = 0 |
tcp.ack | Flag ack. TCP | TCP | bit | tcp.ack = 1 |
tcp.psh | Flag psh. TCP | TCP | bit | tcp.psh = 0 |
tcp.rst | Flag rst. TCP | TCP | bit | tcp.rst = 0 |
tcp.syn | Flag syn. TCP | TCP | bit | tcp.syn = 0 |
tcp.fin | Flag fin. TCP | TCP | bit | tcp.fin = 0 |
tcp.wsize | Tamanho da janela TCP | TCP | número | tcp.wsize = 0 |
tcp.checksum | Checksum | TCP | número | tcp.checksum = 0 |
tcp.urgp | Ponteiro urgente | TCP | número | tcp.urgp = 0 |
tcp.payload | Payload | TCP | string | tcp.payload = "\x01abc" |
udp.src | Porta de origem | UDP | número | udp.src = 53 |
udp.dst | Porta de destino | UDP | número | udp.dst = 7 |
udp.size | Comprimento UDP | UDP | número | udp.size = 8 |
udp.checksum | Checksum | UDP | número | udp.checksum = 0 |
udp.payload | Payload | 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 | Payload | 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 | Comprimento do hardware ARP | ARP | número | arp.hwlen = 6 |
arp.opcode | Código de operação ARP | ARP | número | arp.opcode = 2 |
arp.hwsrc | Endereço de hardware ARP origem | ARP | MAC | arp.hwsrc = "de:ad:be:ef:0:0" |
arp.psrc | Endereço de protocolo ARP origem | ARP | endereço IP | arp.psrc = 192.30.70.3 |
arp.hwdst | Endereço de hardware ARP destino | ARP | MAC | arp.hwdst = "de:ad:be:ef:0:0" |
arp.pdst | Endereço de protocolo ARP destino | ARP | endereço IP | arp.pdst = 192.30.70.3 |
| Significa |
|---|
north-american-ip | Endereços IP da América do Norte |
south-american-ip | Endereços IP da América do Sul |
asian-ip | Endereços IP da Ásia |
european-ip | Endereços IP da Europa |
| Sub-tarefa | O que faz? | Manual |
|---|
pcap-import | Importa pacote de um arquivo PCAP para um arquivo pigsty | cat doc/pcap-import.md |
shell | Executa pig no modo interativo | cat doc/shell.md |