open atlas
↑ К треку
Наступательная безопасность RED · 04 · 02

Payloads and shells

Шелл — это код, который выполняется после того, как эксплойт сработал. Reverse против bind — это вопрос о том, кто кому звонит, и именно этот выбор ловят egress-фильтрация и EDR. Изучи механизм, чтобы суметь разорвать канал.

RED Middle ◷ 15 min
Уровень
ОсновыJuniorMiddleSenior

На авторизованном пентесте эксплойт сработал. Указатель инструкций твой — но перехваченный адрес возврата — это поток, который проживёт несколько микросекунд, а потом процесс либо упадёт, либо пойдёт дальше. У тебя есть контроль над выполнением и почти нечего с ним делать. На самом деле тебе нужен разговор: терминал, в который можно печатать с другого конца сети и который переживёт возврат из функции. Этот второй этап — код, превращающий мимолётный миг контроля в устойчивую интерактивную сессию, — называется payload (полезная нагрузка), а сессия, которую он даёт, — это шелл. Интересно тут не то, как его написать. Интересно то, что в тот же миг, как твой payload пытается открыть этот разговор, он обязан установить сетевое соединение или открыть порт — а это ровно та единственная вещь, которую файрвол защитника и EDR были построены, байт за байтом, замечать.

К концу урока ты будешь знать, что такое payload и шелл на самом деле, почему «reverse против bind» сводится к тому, кто кому звонит, и как egress-фильтрация и EDR обнаруживают канал, — чтобы уметь рассуждать о его разрыве с любой из сторон.

Сначала авторизация — это механизм, а не оружие

Всё ниже — это теория того, как формируется канал пост-эксплуатации и как защитники его видят. Здесь нет рабочего payload, и он не нужен: можно полностью понять reverse-шеллы, bind-шеллы и то, как их ловят, ни разу не направив ни один на систему, которой ты не владеешь. Единственные законные места, где можно наблюдать, как шелл дозванивается обратно, — это CTF-машина, намеренно уязвимая VM, которую ты сам поднял, или входящий в скоуп пентест с письменной авторизацией. В терминах MITRE ATT&CK эксплойт купил нам плацдарм; payload — это то, что устанавливает Execution (выполнение), а затем Persistence (TA0003) — удержание этого кода доступным. Мы изучаем соединение и дерево процессов именно для того, чтобы защитник мог разорвать цепочку в самой узкой точке. Запусти шелл против цели, на которую у тебя нет авторизации, — и ты не изучаешь безопасность, а совершаешь преступление.

Payload — это что-выполнится-дальше; шелл — это разговор

Эксплойт отвечает на вопрос «как перенаправить выполнение». Payload отвечает на вопрос «выполнение моё — что теперь делать?». При переполнении стека байты, перезаписавшие адрес возврата, указывали куда-то; payload — это код, который ждёт в этой точке назначения. Исторически это был сырой shellcode, внедрённый в тот же буфер; на современных системах с неисполняемым стеком это чаще цепочка, вызывающая существующую функцию, чтобы породить дочерний процесс. В любом случае цель самого распространённого payload скромна и разрушительна: запустить командный интерпретатор — /bin/sh, bash, cmd.exe, powershell — и подключить его стандартный ввод и вывод к сетевому сокету. Эта подводка — вся суть. Локальный шелл бесполезен удалённому атакующему; шелл, чья клавиатура и экран — это TCP-соединение, — это удалённый терминал.

Шелл, таким образом, — это просто интерактивный командный интерпретатор, чей ввод-вывод перенаправлен по сети. Как только он у тебя есть, ты печатаешь команду на своей машине, она выполняется на их, а вывод возвращается обратно. Всё остальное в пост-эксплуатации — повышение привилегий, латеральное движение, доставка инструментов — происходит через этот канал. Вот почему именно сам канал — это место, где ведётся вся битва за обнаружение.

Reverse против bind: кто кому звонит

Подключить этот сокет можно двумя способами, и разница целиком в направлении, в котором инициируется соединение, — а это оказывается самым важным фактом в вопросе, переживёт ли канал реальную сеть.

Bind-шелл открывает слушающий порт на жертве и ждёт. Атакующий подключается входящим соединением к этому порту. Концептуально это самый простой вариант — и почти всегда неправильный на практике: входящие соединения из интернета на случайный высокий порт внутреннего хоста — это ровно то, что периметровый файрвол и NAT существуют блокировать. Жертва обычно за NAT, без публичного IP и без проброса входящих портов, так что подключаться попросту не к чему.

Reverse-шелл переворачивает направление. Жертва сама звонит наружу атакующему, который слушает. Это проходит мимо двух вещей, убивающих bind-шеллы: мимо NAT (исходящие соединения — это как работает любой нормальный клиент) и мимо входящих правил файрвола (которые обычно по умолчанию пропускают исходящий трафик). Вот почему «reverse» — это дефолт почти на каждом реальном пентесте: не потому, что он скрытнее, а потому, что это единственный, который вообще соединяется. Атакующий часто слушает на 443, чтобы трафик сливался с HTTPS и обычно выпускался наружу.

Как защитник его ловит: egress-фильтрация и EDR

Reverse-шелл работает только благодаря одному обычно-верному допущению: исходящий трафик разрешён по умолчанию. Большинство сетей жёстко контролируют то, что входит, и едва смотрят на то, что выходит. Egress-фильтрация — это поправка защитника: относиться к исходящему трафику с тем же подозрением, что и к входящему. Сделанная хорошо, она означает, что хост может дотянуться только до явного allowlist пунктов назначения и портов; всё остальное отбрасывается. Против этого жертва звонит наружу — и пакет упирается в стену: слушателя атакующего нет в allowlist, поэтому соединение никогда не завершается. Всё преимущество reverse-шелла — «исходящее бесплатно» — испаряется. Именно поэтому атакующие туннелируют через 443, DNS или настоящий облачный сервис: они пытаются выглядеть как трафик, который allowlist уже пропускает.

Вторая линия — это EDR (Endpoint Detection and Response) — агент, наблюдающий за самим хостом, а не за проводом. Даже идеально TLS-зашифрованный reverse-шелл на 443 оставляет на эндпойнте отпечатки, которых сеть никогда не видит:

  • Аномальное дерево процессов. Процесс веб-сервера (nginx, php-fpm, java) не должен быть родителем /bin/sh или cmd.exe. Это ребро «родитель — потомок» — одно из самых сигнальных обнаружений вообще: оно означает, что сервис, обрабатывающий запросы, только что породил интерактивный шелл.
  • Шелл с сокетом в качестве стандартного ввода-вывода. У нормального bash на файловых дескрипторах терминал. У reverse-шелла на stdin/stdout — сетевой сокет. EDR, инспектирующий, на что указывают дескрипторы шелла, видит это сразу.
  • Поведенческая последовательность. Породился шелл, потом whoami, потом сетевая разведка, потом загрузка — сам плейбук пост-эксплуатации и есть сигнатура.
Тип шеллаКто инициируетОбходит NAT / входящий файрвол?Что его останавливает
Bind-шеллАтакующий звонит внутрь (входящее)Нет — входящее на высокий порт блокируетсяПериметровый файрвол + NAT (уже)
Reverse-шеллЖертва звонит наружу (исходящее)Да — пользуется «исходящее разрешено по умолчанию»Egress-фильтрация (исходящий allowlist)
Reverse через 443/DNSЖертва звонит наружу, похоже на HTTPS/DNSДа — сливается с разрешённым трафикомEgress + EDR (дерево процессов, сокет-как-stdio)
Почему это работает

Почему атакующие всё время лезут выше по стеку — сырой TCP, потом 443, потом DNS-туннелирование, потом вебхук Slack/Telegram/Discord как командный канал? Потому что каждый шаг — это ответ на egress-фильтрацию. Плоская блокировка исходящего убивает сырой TCP на случайный порт. Тогда канал мигрирует на порты, которые обязаны быть открыты (443, 53), а затем на пункты назначения, которые уже в allowlist (SaaS-API, которым компания реально пользуется). Контр-ответ защитника тоже обязан расти: не просто «разрешён ли порт», а «должен ли этот хост вообще разговаривать с этим назначением, в таком объёме, с такой периодичностью». Именно поэтому современное обнаружение опирается на EDR и поведенческие базовые линии, а не только на правила портов, — канал всегда может одолжить порт, но подделать дерево процессов ему куда тяжелее.

Как рассуждает зрелый инженер

Будь ты атакующим на авторизованном пентесте или защитником, урок один и тот же: payload — это легко; канал — это узкое место. Атакующий, знающий лишь «reverse-шелл на 443», встаёт намертво перед сетью с исходящим allowlist и EDR. Защитник, блокирующий только входящее, оставил дверь reverse-шелла нараспашку. Устойчивая ментальная модель — мыслить в терминах направления соединения, его пункта назначения и процесса, которому оно принадлежит, — потому что каждое из этого есть место, где можно либо спрятаться, либо обнаружить. Дефолты тут важнее всего: сеть, разрешающая весь исходящий трафик, — это сеть, допускающая, что reverse-шелл сработает, а хост, чей веб-сервер может породить шелл незаметно, — это хост, допускающий, что payload выполнится тихо.

Выбери лучший вариант

Ты харденишь внутренний сервер приложения так, чтобы даже при компрометации reverse-шелл не смог дозвониться домой. Хост за NAT с политикой «исходящее разрешено по умолчанию». Выбери контроль, который реально ломает канал reverse-шелла.

Викторина

Почему reverse-шелл — дефолтный выбор поверх bind-шелла почти на каждом реальном пентесте?

Викторина

Атакующий запускает полностью TLS-зашифрованный reverse-шелл наружу через порт 443, так что сеть не может прочесть payload. Как EDR всё равно может пометить его на эндпойнте?

Расставь шаги по порядку

Упорядочь этапы установления reverse-шелла и его последующего обнаружения, от первого к последнему:

  1. 1 Эксплойт срабатывает, выполнение перенаправляется на payload
  2. 2 Payload порождает командный интерпретатор (например, /bin/sh)
  3. 3 stdin/stdout интерпретатора подключаются к исходящему сокету
  4. 4 Жертва звонит наружу на слушатель атакующего на 443
  5. 5 Egress-allowlist отбрасывает соединение или EDR помечает дерево процессов
Вспомните перед уходом
  1. 01
    Объясни разницу между bind-шеллом и reverse-шеллом и почему reverse — дефолт на реальных пентестах.
  2. 02
    Reverse-шелл полностью TLS-зашифрован и идёт наружу через 443. Назови два защитных слоя, которые всё равно могут его остановить или обнаружить, и на что опирается каждый.
Итог

Payload — это код, который выполняется в тот же миг, как эксплойт перенаправляет выполнение; самый распространённый порождает командный интерпретатор и подключает его стандартный ввод и вывод к сетевому сокету, давая атакующему шелл — удалённый интерактивный терминал. Выбор между bind-шеллом (жертва слушает, атакующий подключается входящим) и reverse-шеллом (жертва звонит наружу атакующему) — целиком про направление соединения, и reverse выигрывает на практике, потому что NAT и файрволы с «исходящее разрешено по умолчанию» пропускают исходящее соединение, убивая входящее; атакующие часто пользуются 443, чтобы слиться с HTTPS. У защитника два контр-ответа, точно ложащихся на то, что раскрывает канал: egress-фильтрация превращает исходящее в default-deny allowlist, так что reverse-соединению некуда идти, а EDR игнорирует зашифрованный провод и смотрит на хост — помечая аномальное дерево процессов (веб-сервер как родитель /bin/sh), шелл, чьи дескрипторы — это сокет, и поведенческую последовательность пост-эксплуатации. Поэтому, увидев хост с разрешённым всем исходящим и веб-сервером, который может породить шелл незаметно, твой первый вопрос: в каком направлении идёт соединение, куда ему разрешено идти и какой процесс им владеет, — потому что именно там ты либо прячешь канал, либо его ломаешь.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 6 завершено
Связанные уроки

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.