
Полная версия:
Bug Hunter: От первых шагов до профессионального Bug Bounty
2.2.3. Worked-пример: разбор scope
Разберём типовую (вымышленная, обобщённая) формулировку scope, как её читает исследователь:

Что отсюда следует практически:
*.shop.example включает, например, admin.shop.example, но не включает blog.shop.example (явно исключён) и не включает api.shop.example? — включает, поддомен подходит под wildcard; при этом api.shop.example упомянут отдельно, что лишь подтверждает его в scope.
*.partners.shop.example — это другой узел дерева, явно вне scope: трогать нельзя, даже если доступен.
Мобильное приложение в scope — значит, его бэкенд-API (если на доменах в scope) тоже исследуемы, но сверяйтесь, какие именно хосты он использует.
DoS и соц. инженерия запрещены вообще — даже «лёгкая» проверка нагрузкой выходит за правила.
Safe harbor привязан к соблюдению политики: шаг на partners.* или нагрузочный тест выводит из-под неё.
Выпишите разрешённые и запрещённые узлы в заметки до работы и сверяйтесь с ними при каждой новой находке хоста в разведке (глава 5). Граница, зафиксированная заранее, защищает вас при спорах.
2.3. VDP и Bug Bounty: разные обещания
VDP (Vulnerability Disclosure Program) — это канал «сообщите об уязвимости безопасно», как правило без денежного вознаграждения, но с обещанием не преследовать. Bug Bounty добавляет к этому выплаты. Практический вывод: на VDP не стоит рассчитывать на доход, но это легальный и полезный способ сообщить о проблеме и выстроить репутацию. Не выдавайте правила одной платформы или программы за универсальные: формулировки scope, safe harbor и оценки различаются.
2.4. Safe harbor и его пределы
Safe harbor («тихая гавань») — раздел политики, где владелец обязуется не инициировать юридическое преследование исследователя, действующего добросовестно и в рамках правил. Это важная защита, но у неё есть пределы, которые нужно понимать:
Она действует только в границах программы. Шаг за scope — и защита не применяется.
Она касается отношений с этой организацией. Она не отменяет законы и не связывает третьи стороны (например, провайдера или партнёра, чьи системы вы задели).
Формулировки различаются: одни программы дают широкий safe harbor, другие — узкий и с оговорками. Читайте дословно, что именно обещано и при каких условиях.
«У них есть safe harbor» — не индульгенция. Защита обусловлена добросовестностью и соблюдением правил. Разрушение данных, выгрузка чужих персональных данных сверх необходимого, тестирование вне scope выводят вас из-под неё.
2.5. Принципы безопасного исследования
Даже имея разрешение, действуйте так, чтобы не навредить. Это и этика, и условие сохранения safe harbor.
Минимальное воздействие. Подтверждайте уязвимость минимально достаточным PoC. Нашли SQL-инъекцию — достаточно извлечь одну «несанкционированную» строку, а не выгружать базу (сравните с лабораторией L-SQLI, где мы ограничиваемся парой записей для доказательства).
Без разрушения. Не удаляйте и не портите данные, не меняйте чужие записи, не выводите сервис из строя. Если PoC требует деструктивного шага — остановитесь и опишите риск словами.
Чужие данные — бережно. Не собирайте и не храните персональные данные сверх необходимого; в доказательствах маскируйте их. Не выносите чужие данные за пределы задачи.
Без чужих учётных данных. Не вводите реальные чужие логины/пароли/токены. Для тестов используйте свои тестовые аккаунты (в HunterMart — предусмотренные учебные учётки).
Не в URL. Не помещайте персональные или секретные данные в URL и query-строки.
2.5.1. Опасные классы — особые меры
При тестировании SSRF, XXE, инъекций команд и десериализации легко случайно задеть внутреннюю инфраструктуру. Поэтому (подробно — главы 9 и 11):
используйте безопасные маркеры и, где можно, локальную лабораторию;
исключайте реальные внутренние адреса, облачные metadata-эндпоинты и чужие секреты;
не разворачивайте нагрузку, которая может нарушить работу сервиса.
В этой книге все такие демонстрации выполняются только в HunterMart на синтетических данных и локальных адресах. Это осознанный принцип, а не ограничение «для вида».
2.6. Инструменты с техническими границами
Дисциплина «не выходить за scope» должна быть не только в голове, но и в коде инструментов. Автоматика, способная обратиться к произвольной цели, рано или поздно это сделает — по ошибке в списке целей, из-за редиректа или опечатки. Поэтому инструменты книги построены вокруг обязательного allowlist.
Пример — huntkit.safe_client (глава 12): клиент выполняет запрос, только если хост и порт входят в явный allowlist; пустой allowlist не разрешает ничего.

Помимо allowlist, инструмент обеспечивает таймауты, ограничение частоты запросов, контроль редиректов (каждый хоп проверяется против allowlist) и журналирование. Эти меры — часть безопасного исследования: они не дают автоматике зашуметь цель или уйти за её пределы. Полный разбор — в главе 12.
Allowlist по хосту (example.com) не покрывает его поддомены автоматически — это осознанный выбор в пользу явности. Если вам нужен поддомен, добавьте его явно. «Умное» сопоставление поддоменов чаще расширяет границу, чем помогает.
2.7. Раскрытие и репутация
Приватность по умолчанию. Не раскрывайте уязвимость публично до исправления и явного разрешения программы. Преждевременное раскрытие вредит пользователям и вашей репутации.
Публичный write-up. После разрешённого раскрытия качественный разбор — ценный вклад и элемент портфолио. Отделяйте факты (что было) от интерпретаций и не раскрывайте лишних деталей о клиентах.
Коммуникация. С триажем общайтесь предметно и вежливо, даже при несогласии с оценкой. Репутация в этой сфере накапливается годами и открывает доступ к приватным программам и работе (глава 14).
2.7.1. Worked-пример: типичная временная линия раскрытия
Чтобы понимать, что и когда можно делать, полезно видеть процесс целиком (конкретные сроки задаёт политика программы — здесь обобщённая схема):
Обнаружение и подтверждение находки (в scope, по правилам).
Приватный отчёт через канал программы. С этого момента вы не раскрываете детали публично.
Триаж (программа подтверждает/уточняет/отклоняет; возможен дубликат).
Исправление уязвимости владельцем (может занять недели/месяцы).
Повторная проверка исправления (если программа предусматривает).
Согласованное раскрытие (coordinated disclosure): публичный write-up — только с разрешения и обычно после исправления.
Ключевые правила на этой линии: не раскрывать до исправления и разрешения (это навредит пользователям и вашей репутации); не «торопить» угрозами публикации; быть терпеливым к срокам фикса, но вправе вежливо уточнять статус. Некоторые программы задают предельные сроки раскрытия — их тоже читают в политике.
Молчание программы какое-то время — норма, а не повод для публичного раскрытия. Эскалация — через канал программы/платформы, а не через публикацию деталей.
2.8. Практикум
Уровень 1. Возьмите публичную политику любой известной VDP/Bug Bounty программы (как учебный материал для чтения, без какого-либо тестирования) и выпишите: scope, out-of-scope, запрещённые действия, наличие и формулировку safe harbor. Отметьте пункты, которые трактуете неоднозначно.
Уровень 2. Для HunterMart составьте собственный «scope»: какие эндпоинты существуют (см. карту лаборатории в главе 15), какие учётные записи вам разрешено использовать, какие действия вы считаете допустимыми в лаборатории. Это тренировка дисциплины на безопасной среде.
Уровень 4. Настройте huntkit.safe_client с allowlist только на 127.0.0.1:8000 и убедитесь, что попытка обратиться к любому другому хосту завершается DisallowedTargetError. Объясните, почему такая техническая граница надёжнее устной договорённости «я буду аккуратен».
2.8a. Дополнительные задания (уровни 1–5)
Уровень 1. Выпишите из учебной политики (как чтение) scope, out-of-scope и запреты.
Уровень 2. Для *.shop.example определите, что входит и что не входит в scope, с обоснованием.
Уровень 3. Сформулируйте, какие действия выводят вас из-под safe harbor, и почему.
Уровень 4. Настройте huntkit.safe_client на лабораторию и покажите блокировку чужого хоста.
Уровень 5. Опишите временную линию согласованного раскрытия для гипотетической находки.
2.9. Анализ ошибок новичка
Тестируют «немного за scope». Границы бинарны: либо разрешено, либо нет.
Полагаются на safe harbor как на индульгенцию. Он обусловлен добросовестностью и соблюдением правил.
Выгружают чужие данные «для убедительности». Это и вредно, и выводит из-под защиты; хватает PoC.
Раскрывают находку публично до исправления. Вредит пользователям и репутации.
Доверяют дисциплину только памяти. Границы должны быть и в коде инструментов (allowlist).
2.10. Защитные меры (для владельца программы)
Пишите scope и out-of-scope однозначно; явно перечисляйте запрещённые действия.
Давайте внятный safe harbor — это повышает качество и количество отчётов.
Предусмотрите тестовые аккаунты и окружение, чтобы исследователи не трогали реальные данные.
Быстро и предметно реагируйте на отчёты: отзывчивость программы напрямую влияет на её результаты.
2.11. Резюме
Правила программы — это договор, который читают буквально и целиком: scope, out-of-scope, запреты, раскрытие, safe harbor. Safe harbor защищает, но только в границах и при добросовестности. Безопасное исследование — это минимальное воздействие, бережное обращение с данными, отказ от чужих учётных данных и деструктивных действий, а также технические границы в инструментах (обязательный allowlist). Приватное раскрытие и корректная коммуникация формируют репутацию, которая в этой профессии стоит дорого.
2.12. Контрольные вопросы
Какие разделы политики вы читаете до начала работы и почему именно их?
Что входит и что не входит в wildcard-scope *.example.com?
Назовите три предела safe harbor.
Почему минимальное воздействие — это одновременно этика и защита вашей «тихой гавани»?
Чем технический allowlist надёжнее устного обещания «быть аккуратным»?
Когда допустимо публиковать write-up и что в нём не стоит раскрывать?
2.13. Источники
OWASP Vulnerability Disclosure Cheat Sheet — https://cheatsheetseries.owasp.org/cheatsheets/Vulnerability_Disclosure_Cheat_Sheet.html (проверено 2026-10-19).
disclose.io (шаблоны политик, safe harbor, терминология) — https://disclose.io/ (проверено 2026-10-19).
ISO/IEC 29147 (Vulnerability disclosure) и 30111 (Vulnerability handling) — стандарты процессов раскрытия и обработки; см. каталог ISO https://www.iso.org/ (проверено 2026-10-19).
«Чек-лист безопасного тестирования» — в приложениях книги.
Глава 3. HTTP, браузер, cookies, сессии, TLS и веб-архитектура
Цель главы. Дать рабочее понимание веб-стека на уровне, достаточном для исследователя: как устроена архитектура веб-приложения, как работает HTTP во всех значимых деталях, что такое cookies и сессии, как TLS защищает канал, и как всё это читать в трафике. Это фундамент для всех глав про уязвимости.
Предварительные требования. Главы 1–2. Базовое представление о том, что такое веб-страница.
Результаты обучения. Вы сможете: (1) описать путь запроса от браузера до сервера и обратно; (2) разобрать HTTP-обмен по частям и объяснить роль ключевых заголовков; (3) понимать cookies, сессии и их атрибуты безопасности; (4) объяснить, что даёт TLS; (5) анализировать security headers инструментом.
3.1. Архитектура веб-приложения
Современное веб-приложение — это распределённая система. Между вашим браузером и «сервером» обычно стоит несколько компонентов, и границы между ними — частый источник уязвимостей (главы 9, 11).
Типичный путь запроса:

Браузер — доверенная для пользователя, но недоверенная для сервера сторона. Всё, что приходит от браузера, сервер обязан считать потенциально враждебным (граница доверия, глава 1).
DNS — преобразует имя (huntermart.example) в IP-адрес.
CDN / обратный прокси — кэширование, балансировка, терминация TLS. Здесь рождаются классы вроде cache poisoning и request smuggling (главы по продвинутым темам).
Сервер приложения — исполняет бизнес-логику (в HunterMart — FastAPI).
База данных — хранилище (в HunterMart — SQLite).
Рисуйте для исследуемой системы диаграмму потоков данных с границами доверия (как DFD HunterMart в главе 1). Большинство уязвимостей живёт на границах, где данные переходят из менее доверенной зоны в более доверенную.
3.1.1. Клиент-серверная модель и SPA
Классическое приложение рендерит HTML на сервере. SPA (Single-Page Application) переносит рендеринг в браузер: сервер отдаёт JavaScript, который обращается к API (REST/GraphQL) за данными. Для исследователя это означает: много логики и эндпоинтов «спрятано» в JS-бандле (его анализ — глава 5), а безопасность смещается к API (глава 11) и клиентскому коду (глава 8).
3.2. HTTP: протокол запрос–ответ
HTTP (HyperText Transfer Protocol) — текстовый по происхождению прикладной протокол. Он без состояния (stateless): сам по себе не помнит предыдущие запросы; «память» (сессию) надстраивают поверх через cookies и токены (раздел 3.5).
3.2.1. Анатомия обмена
Любое HTTP-сообщение: стартовая строка, заголовки, пустая строка, опциональное тело. Пример на HunterMart:

Части запроса: метод (GET), цель (/api/orders/1001 + возможная строка запроса ?a=1), версия (HTTP/1.1), заголовки (Host обязателен в 1.1), тело (у GET обычно нет). Имена заголовков регистронезависимы.
3.2.2. Методы

* «Безопасный» здесь — термин HTTP (метод не меняет состояние), не про защищённость. Нельзя полагаться, что приложение честно соблюдает семантику: иногда GET меняет данные (проблема — CSRF, кэширование). Проверяйте фактическое поведение.
3.2.3. Коды состояния
2xx успех (200, 201, 204); 3xx перенаправление (301, 302, 304, 307, 308); 4xx ошибка клиента (400, 401, 403, 404, 429); 5xx ошибка сервера (500, 502, 503).
Для исследователя коды — сигнал, а не истина. 401 («не аутентифицирован») против 403 («нельзя»); 404 вместо 403 на чужом объекте — осознанная защита от перечисления (глава 6); разные коды/размеры на «есть/нет пользователя» — канал для перечисления учётных записей.
3.3. Заголовки и безопасность
Заголовки несут и метаданные, и защитные механизмы. Ключевые защитные заголовки ответа:

Некоторые заголовки, наоборот, раскрывают лишнее (Server, X-Powered-By — технология и версия). Проверять security headers вручную утомительно; инструмент huntkit.headers (глава 12) делает это по рекомендациям OWASP Secure Headers Project:

Отсутствие security-заголовка — ослабление защиты, но ещё не эксплуатируемая уязвимость. «Нет CSP» значимо, если есть точка для XSS. Пустой список отсутствующих заголовков без контекста многие программы считают информационным пунктом.
3.3.1. Worked-пример: разбор CORS
CORS (Cross-Origin Resource Sharing) — механизм, которым сервер разрешает чужим origin читать свои ответы (послабление Same-Origin Policy). Его часто путают с защитой от CSRF — это разные вещи: CORS управляет чтением ответа кросс-доменно, а не отправкой запроса. Ключевые заголовки ответа:

Опасная мисконфигурация — отражение Origin запроса в Access-Control-Allow-Origin вместе с Allow-Credentials: true:

Это позволяет странице атакующего читать ответы с учётными данными жертвы — утечка данных. Проверка: подставить произвольный Origin и посмотреть, отражается ли он в Allow-Origin при Allow-Credentials: true. Защита — allowlist доверенных origin, никогда не отражать произвольный Origin, не сочетать * с Allow-Credentials.
Access-Control-Allow-Origin: * без Allow-Credentials на публичном ресурсе (например, открытый API без сессии) обычно не уязвимость — читать там нечего приватного. Подтверждение требует доступа к приватным данным кросс-доменно.
3.4. Строка запроса, тело и форматы данных
Строка запроса (query string) — ?key=value&key2=value2. Видна в логах и истории — не место для секретов (глава 2).
Тело — у POST/PUT/PATCH. Частые типы: application/json, application/x-www-form-urlencoded, multipart/form-data (загрузка файлов, глава 9).
JSON — основной формат API. REST — архитектурный стиль над HTTP; GraphQL — единый эндпоинт с языком запросов; WebSocket — полнодуплексный канал. Все три разбираются в главе 11.
3.5. Cookies и сессии
Поскольку HTTP без состояния, сервер выдаёт cookie заголовком Set-Cookie, а браузер возвращает её в Cookie:

Атрибуты cookie — это механизмы безопасности:
HttpOnly — недоступна из JavaScript (смягчает кражу сессии при XSS, глава 8).
Secure — отправляется только по HTTPS.
SameSite (Lax/Strict/None) — ограничивает отправку в межсайтовых запросах (ключ к защите от CSRF, глава 8).
Path/Domain — область действия; слишком широкий Domain — риск.
Сессии и токены. Идентификатор сессии хранят в cookie (серверная сессия) или в виде токена в Authorization (как в HunterMart). Учебная модель HunterMart упрощена (без срока жизни и ротации) — её ограничения разбираются в главе 10.
3.5.1. Worked-пример: полный цикл аутентифицированной сессии
Разберём на HunterMart цикл «вход → аутентифицированный запрос» целиком, по трафику. Шаг 1 — вход:

Сервер проверил учётные данные (аутентификация) и выдал токен сессии. HunterMart передаёт токен в теле ответа, и клиент предъявляет его в заголовке Authorization (другие приложения кладут сессию в Set-Cookie — тогда браузер возвращал бы её автоматически, см. 3.5). Шаг 2 — аутентифицированный запрос:

Что здесь важно исследователю: (1) токен — это и есть «состояние», надстроенное над HTTP без состояния; (2) предъявление токена подтверждает личность (аутентификация), но не гарантирует право на объект 1001 — это отдельная проверка (авторизация, глава 6); (3) если убрать Authorization, сервер должен вернуть 401 — проверьте это, чтобы понять, где граница аутентификации. Воспроизвести цикл в терминале:

3.6. Редиректы
Ответ 3xx с Location перенаправляет браузер. 301/308 — постоянный, 302/307 — временный; 307/308 сохраняют метод и тело, 302 исторически часто меняет метод на GET. Редиректы — источник Open Redirect (если цель берётся из управляемого параметра без проверки). В HunterMart это эндпоинт /go (разобран как лаборатория L-OPENREDIR; подробности класса — в части про уязвимости):

3.7. Версии протокола
HTTP/1.1 — текстовый, один активный обмен на соединение (с keep-alive). Обязателен Host. Расхождения в разборе 1.1 между прокси и сервером порождают request smuggling.
HTTP/2 — бинарный, мультиплексирование потоков, сжатие заголовков (HPACK). Семантика та же.
HTTP/3 — поверх QUIC (на UDP), TLS 1.3 встроенно, устраняет head-of-line blocking на транспорте.
Для большинства находок уровня приложения версия транспорта вторична (семантика сохраняется), но на стыках версий и реализаций возникают smuggling и рассинхрон кэша.
3.7.1. Worked-пример: почему стыки версий опасны
Проблема рождается, когда два компонента на пути (например, фронтенд-прокси/CDN и бэкенд-сервер) по-разному интерпретируют одно и то же сообщение. Классический пример — HTTP Request Smuggling: прокси и сервер расходятся в том, где заканчивается один запрос и начинается следующий (из-за разной трактовки Content-Length и Transfer-Encoding в HTTP/1.1, или при трансляции HTTP/2→HTTP/1.1). В результате «протащенный» фрагмент одного запроса влияет на другой — например, на запрос другого пользователя.
Для исследователя практический смысл в том, что такие классы живут не в коде приложения, а в расхождениях реализаций на границе компонентов. Поэтому важно знать, что перед приложением стоит (CDN, обратный прокси) и как устроена трансляция версий. Это продвинутая тема; здесь достаточно понимать принцип: единая семантика HTTP не гарантирует единую интерпретацию байтов разными реализациями, и именно расхождение интерпретаций — источник уязвимости.
3.9.1. Worked-пример: ключ кэша и его рассинхрон
Кэш (браузер, прокси, CDN) хранит ответ под ключом, обычно складывающимся из метода, хоста и пути (иногда части заголовков через Vary). Уязвимости возникают, когда ключ не совпадает с тем, что реально влияет на ответ:
Cache Poisoning. Если на ответ влияет заголовок, не входящий в ключ (например, нестандартный заголовок, который сервер отражает в теле), атакующий «отравляет» кэш: кладёт туда вредный ответ, который затем отдаётся другим пользователям под обычным ключом.
Cache Deception. Атакующий заставляет кэш сохранить приватный ответ под ключом, который потом запросит он сам (например, добавив к приватному URL «статичное» расширение, которое кэш считает кэшируемым).

