Статья SSRF против внутреннего админского API: от разведки до эксплуатации и defense in depth

SSRF-атака на внутренний admin API через уязвимый параметр URL

Постановка задачи и архитектура приложения

Всего один некорректно настроенный параметр URL может позволить злоумышленнику использовать запросы на стороне сервера для получения потенциального доступа к внутренним сервисам, конечным точкам облачных метаданных или скрытым ресурсам, которые изначально не предназначались для внешнего доступа. В этой статье, мы рассмотрим процесс постановки задачи и разработки архитектуры приложения, которое использует уязвимость SSRF (Server-Side Request Forgery) для атаки на внутренний админский API.


Discovery: поиск SSRF-вектора

1780064590686.webp

Ключевая деталь заключается в том, кто именно отправляет запрос: сервер, а не браузер пользователя. Это имеет важное значение, потому что сервер, как правило, находится внутри доверенного сетевого контура. Он имеет доступ к внутренним API, панелям администрирования, конечным точкам облачных метаданных и бэкенд-сервисам, которые остаются невидимыми для внешних злоумышленников. Внедряя вредоносный URL-адрес, вы фактически «заимствуете» эту привилегированную позицию.

Анализ функции URL preview/fetch

Начните с тех, которые явно управляются через URL, потому что быстрое их исключение позволяет понять, есть ли у цели вообще какая-либо защита от SSRF.

Параметры URL, выглядящие как идентификаторы. Параметры с именами являются классическими кандидатами для эксплуатации SSRF:
  1. callback
  2. return_url
  3. redirect_uri
  4. next
  5. image_url
  6. avatar
  7. url
  8. uri
  9. dest
  10. source
  11. path
  12. target
  13. reference
  14. site
  15. feed
Также следует обращать внимание на значения, закодированные в Base64 или URL-кодировке, которые после декодирования представляют собой URL-адреса. Поля ввода URL в настройках профиля (URL аватара, пользовательское фоновое изображение), функции импорта, кнопки «загрузить по URL» или любые формы, принимающие ссылки.

Проверка обработки внешних ресурсов

Места, где уязвимости SSRF сохраняются в production-среде. Поля, заголовки или параметры, которые косвенно определяют целевой ресурс; поскольку разработчики редко распознают их как «приемники URL» (URL sinks), они практически никогда не подвергаются столь же тщательной защитной обработке, как более очевидные элементы.
HTTP-заголовки, влияющие на маршрутизацию или выборку. Такие заголовки, как:
  1. X-Forwarded-For
  2. X-Forwarded-Host
  3. X-Original-URL
  4. X-Rewrite-URL
  5. Referer
  6. Forwarded
иногда могут влиять на то, куда приложение отправляет последующие запросы - особенно в приложениях, работающих за обратными прокси-серверами или использующих промежуточное ПО для перезаписи URL:
  • URL-адреса, внедренные в загруженные файлы
  • Внешние сущности XML
  • Теги SVG <image href>
  • Ссылки на изображения в формате Markdown
  • Содержащиеся в загруженном контенте
  • HTML-шаблоны в генераторах PDF
  • А также файлы DOCX/XLSX с внешними ссылками
Все они при парсинге инициируют запросы к внешним ресурсам на стороне сервера.
Функции импорта и предварительного просмотра файлов. Такие инструменты, как:
  • «Импорт по URL»
  • RSS-ридеры
  • Сервисы создания скриншотов
  • Генераторы PDF и конвертеры URL в изображения
Все они осуществляют загрузку внешнего контента. Особую ценность представляют генераторы PDF: зачастую они используют безголовые браузеры или HTML-рендереры, поддерживающие схему file://, а также выполнение внутренних HTTP-запросов.


Fingerprinting внутренней сети через SSRF

Это техника разведки, при которой атакующий использует уязвимый веб-сервер в качестве «прокси» для сканирования, маппинга и определения сервисов, находящихся внутри периметра безопасности компании (в локальной сети или в приватном облаке), к которым нет прямого доступа из интернета.

Port scanning через SSRF

SSRF позволяет выполнять сканирование внутренних портов, что дает злоумышленникам возможность составить карту внутренних сервисов и выявить уязвимости.

В уязвимое URL поле (как правило, от сервиса который что-то импортирует из файлов или ссылок), вводится уязвимый адрес – локальный.
http://127.0.0.1:22
Сервер возвращает интересный ответ «Failed to download from (http:127.0.0.1:22): wrong status line: “SSH-2.0-OpenSSH_7.4”», таким образом, мы понимаем что на 22 порту крутиться SSH.

Enumeration internal services (127.0.0.1, 10.0.0.0/8)

Злоумышленники часто начинают эксплуатацию уязвимостей SSRF с перечисления внутренних сервисов. Они систематически сканируют распространенные порты и конечные точки на localhost, а также в диапазонах адресов внутренней сети.

Такой «Bruteforce» можно реализовать либо через Burp Suite в разделе Intruder (при наличии pro версии) с регулярным выражением "^((?!Connection refused).)$*", либо через python-скрипт и библиотеку requests.


Обход защитных фильтров

1780064623896.webp

Большинство целевых систем, с которыми вы столкнетесь, тем или иным образом будут проверять ваши входные данные и пытаться воспрепятствовать доступу к внутренним сервисам или запросу ресурсов, на получение которых у вас нет разрешения. Один из способов, к которому прибегают разработчики, заключается в проверке имени хоста в предоставленном URL-адресе путем его сопоставления со списком разрешенных или запрещённых хостов.

IP blacklist bypass (decimal/hex encoding, DNS rebinding)

Приложение будет блокировать запросы к 127.0.0.1 или 192.168.0.1, оно обычно проверяет только строковое значение ввода.

ОС и сетевые библиотеки на самом деле понимают IP-адреса не только в привычном формате. Они принимают числа в 16ричных и 8ричных системах или в виде одного огромного числа.

Шестнадцатеричный формат:

127 = 7F, 0 = 00, 1 = 01

http://0x7F00001 или http://0x7F.0x00.0x00.0x01

Некоторые из ваших целей пойдут еще дальше и выполнят DNS-запрос для проверки хоста по списку разрешенных адресов. Однако, если уязвимый компонент подвержен уязвимости типа TOCTOU («время проверки — время использования»), мы можем обойти эту проверку посредством DNS-ребиндинга.
  1. Хакер покупает свой домен и настраивает свой DNS-сервер для него.
  2. Этот DNS-сервер настроен так, чтобы отдавать ответы с очень коротким временем жизни (TTL=0 или 1 секунда).
  3. При первом запросе DNS-сервер атакующего возвращает легитимный публичный IP. Валидатор видит, что это не локальный адрес и пропускает его.
  4. При втором запросе TTL уже истёк. Приложению снова приходится справивать DNS. В этот второй раз DNS-сервер хакера возвращает 127.0.0.1 .
  5. Приложение думает что направляет запрос на внешний сайт, но отправляет запрос в свой локальный интерфейс.

Protocol smuggling (gopher://, file://)

Методика, при которой хакер использует альтернативные системные или сетевые протоколы, чтобы заставить сервер взаимодействовать с внутренними сервисами или локальной файловой системой.

Gopher — это протокол прикладного уровня, предназначенный для распространения, поиска и получения документов через Интернет. Хотя HTTP быстро превзошел его по популярности благодаря появлению HTML и веб-браузеров, Gopher по-прежнему находит применение в определенных нишах - в частности, в сфере исследований безопасности и тестирования на проникновение. Gopher работает на 70 порту TCP и использует простую модель запрос-ответ. Он может возвращать: Файл, Директорию, Поисковой запрос.

Вы можете формировать «сырые» TCP-запросы с помощью Gopher и обходить определенные WAF или SSRF-фильтры.
gopher://127.0.0.1:11211/_%0d%0aset%20x%200%20900%205%0d%0ahello%0d%0a
file – это протокол, для чтения локальных файлов. Если бэкенд-движок, выполняющий запросы, поддерживает схему file://, уязвимость SSRF мгновенно превращается в LFI.

Базовый payload для Linux: file:///etc/passwd
Базовый payload для Windows: file:///C:/Windows/win.ini

Различные атаки на парсеры

Когда у вас есть доступ к исходному коду, задача не ограничивается поиском небезопасных функций. Более эффективный подход заключается в поиске десинхронизации логики. Подобные уязвимости называются parser differentials.

Суть атаки заключается в том, что в современном веб-приложении обработкой одного URL-адреса обычно занимаются минимум два разных компонента.

  1. Валидатор: Код, который проверяет, безопасен ли URL
  2. Бизнес-логика: Библиотека или утилита, которая делает фактический запрос (cURL, urllib, requests)
Если эти два компонента по-разному интерпретируют один и тот же сложный или нестандартный URL, атакующий может составить такую строку, которую валидатор посчитает безопасным внешним сайтом, а HTTP-клиент прочитает как внутренний IP.

Например, манипуляция с символом @:
http://example.com:80@localhost:8080/

Манипуляция с символами-разделителями:
http://example.com\localhost или http://example.com#@localhost

Пространство имён и инъекция порта:
http://localhost:80#@example.com:80


Эксплуатация: доступ к admin API

1780064689508.webp

Если уязвимость типа SSRF позволяет обойти сетевые фильтры, конечной целью хакера становится проникновение во внутреннюю инфраструктуру. Одной из наиболее ценных целей при этом является внутренний API администрирования.

Рассмотрим конечную точку API, которая извлекает контент по URL-адресу, указанному пользователем:
NGINX:
POST /api/fetch-content
{
    "url": "http://example.com/data"
}
Хакер может воспользоваться этим, предоставив URL-адрес, указывающий на внутренний сервис:
NGINX:
{
    "url": "http://localhost:8000/admin"
}

Извлечение sensitive endpoints

Поскольку разработчики часто считают, что внутренняя сеть находится в безопасности, административные интерфейсы (Admin API) внутри периметра часто лишены авторизации, но при этом детально документированы или имеют предсказуемую структуру.

Современные разработчики редко пишут документацию вручную — за них это делают фреймворки. Если через SSRF удается дотянуться до внутреннего порта приложения, первым делом проверяется наличие автоматически сгенерированных схем API.

Если автоматической документации нет, эндпоинты приходится искать перебором. Для этого используются специализированные словари (api-endpoints.txt или common-api-endpoints).

Получение admin credentials из metadata service

Если приложение выполняется в облачной среде, уязвимость SSRF приобретает значительно более серьезные последствия. Облачные провайдеры предоставляют доступ к конечной точке метаданных, доступной исключительно изнутри самого инстанса. Эта точка содержит учетные данные IAM, SSH-ключи, конфигурацию инстанса, а также скрипты пользовательских данных, в которых зачастую хранятся секреты; именно поэтому облачные метаданные представляют собой наиболее высокооплачиваемый вектор эскалации привилегий через SSRF - и именно на эту угрозу команды реагирования реагируют быстрее всего. (AWS EC2 metadata service (IMDSv1))
http://111.111.111.111/latest/meta-data/
http://111.111.111.111/latest/meta-data/iam/security-credentials/

Сначала перечислите доступные роли IAM, получив список учетных данных.
http://111.111.111.111/latest/meta-data/iam/security-credentials/{ROLE}

В ответе возвращаются временные значения AccessKeyId, SecretAccessKey и Token - действительные учетные данные AWS, которые можно немедленно использовать в AWS CLI для дальнейшей эксплуатации.

Escalation до RCE

Поскольку тип атаки SSRF не достаточно гибок для RCE, то мы используем службы. Протокол gopher:// представляет собой одну из наиболее мощных доступных техник эскалации SSRF. В отличие от http://, который ограничен структурой HTTP-запросов, Gopher позволяет серверу отправлять произвольные «сырые» байты на любой TCP-порт. Именно такая техника служит мостом между SSRF и RCE при атаках на реальные цели. Вы можете взаимодействовать с Redis, MySQL, SMTP, FastCGI или любым другим протоколом.

Экземпляры Redis, доступные на localhost без аутентификации, - частое явление в устаревших развертываниях и некорректно настроенных средах Docker. Redis позволяет записывать файлы в файловую систему с помощью команды CONFIG SET; если корневой каталог веб-сервера или директория crontab доступны для записи, это открывает возможность для удаленного выполнения кода (RCE).

При использовании инструмента Gopherus генерация полезной нагрузки выполняется одной командой:
gopherus --exploit redis
После URL-кодирования в формат Gopher URL и передачи через параметр SSRF сервер устанавливает соединение с Redis на порту 6379.

PHP-FPM, прослушивающий порт 9000, представляет собой еще одну весьма ценную цель для Gopher. FastCGI позволяет задавать произвольные значения в конфигурации PHP (.ini), а также выполнять любой файл, присутствующий в файловой системе. Опция --exploit fastcgi инструмента Gopherus генерирует полезную нагрузку на основе указанного пути к любому .php-файлу на сервере.

Defense in depth для микросервисов

1780064748547.webp

Если хакер взломает один контейнер, при отсутствии внутренней защиты он мгновенно захватит всю сеть («soft belly» эффект).

Network policies и segmentation

Главный принцип — микросервисы не должны видеть те сервисы, с которыми им не нужно общаться по бизнес-логике.
  1. Внедрение инструментов вроде Istio, Linkerd или Consul первично. Они создают выделенный слой для управления трафиком.
  2. Шифрование всего трафика между микросервисами с проверкой сертификатов в режиме «каждый с каждым».
  3. Настройка сетевых плагинов (Calico, Cilium) для изоляции подов.
Даже если сеть пропустила запрос, микросервис должен проверить права на уровне приложения.
  1. Нельзя верить запросу только потому, что он пришел от соседнего сервиса.
  2. Каждый эндпоинт внутри периметра должен проверять права, а не просто доверять локальному IP.

SSRF-защита в коде (allow-list domains, схем)

Очевидно, что первый этап - ограничение выбора протокола – только http или https.

Для NodeJS например, используется библиотека axios для такой реализации:
JavaScript:
const axios = require('axios');
const URL = require('url');


function safeFetch(userUrl) {
const parsedUrl = URL.parse(userUrl);
    const allowedProtocols = ['http:', 'https:'];
    if (!allowedProtocols.includes(parsedUrl.protocol)) {
    throw new Error("Only HTTP or HTTPS.");
    }
}

Если приложение должно отправлять запросы только на доверенные сторонние ресурсы, необходимо проверять хост по строгому списку разрешенных доменов.

Важно использовать следующий алгоритм проверки:
  1. Распарсить URL с помощью надёжного встроенного парсера языка программирования
  2. Извлечь чистый хост
  3. Проверить полное совпадение с элементами белого списка
Реализация на Python:
Python:
from urllib.parse import urlparse
import requests

ALLOWED_DOMAINS = ["api.example.com", "api.github.com", "images.pictures.com"]

def safe_get_request(user_input_url):
    try:
        parsed_url = urlparse(user_input_url)
        if parsed_url.scheme not in ["http", "https"]:
            raise ValueError("Invalid protocol")
        target_host = parsed_url.hostname
        if target_host not in ALLOWED_DOMAIN
            raise ValueError("Access Denied: Domain not allowed")
        response = requests.get(user_input_url, timeout=5)
        return response.text
    except Exception as e:
        return f"Error: {str(e)}"

Если приложение должно разрешать пользователям вводить любые внешние домены, обычный Allow-list доменов не поможет. Хакер может использовать свой домен, настроенный на DNS Rebinding.

Безопасный алгоритм для произвольных URL:
  1. Выделяем хост из URL.
  2. Программно преобразуем домен в IP-адрес до отправки HTTP-запроса.
  3. Убеждаемся, что полученный IP-адрес не является приватным.
  4. Делаем HTTP-запрос напрямую на проверенный IP-адрес, а исходный домен передаём исключительно в заголовке Host. Это лишает DNS Rebinding всякого смысла, так как повторного DNS-запроса уже не будет.

Runtime protection (WAF rules, egress monitoring)

Когда безопасность на уровне исходного кода невозможна, защита от SSRF переносится на уровень Runtime Protection.

WAF работает на входном (Ingress) направлении. Его задача — проанализировать входящий HTTP-запрос от пользователя и заблокировать его до того, как он попадет в приложение, если в параметрах обнаружены признаки SSRF. Поскольку WAF видит только строку запроса, его правила (Signatures) в основном нацелены на блокировку альтернативных кодировок IP-адресов и опасных протоколов.
  1. Блокировка схем file:// и gopher://
  2. Блокировка обращений к локальной сети и метаданным.
  3. Блокировка шестнадцатеричных и десятичных IP.
Если WAF защищает «вход», то Egress Monitoring - это самое эффективное средство защиты от SSRF на уровне инфраструктуры, поскольку оно контролирует «выход». Даже если приложение уязвимо, а хакер обошел WAF, атака становится бесполезна, если серверу физически запрещено отправлять пакеты во внутреннюю сеть.

В современных микросервисных средах (Kubernetes + Istio/Envoy) по умолчанию применяется подход Deny-All для исходящего трафика. Контейнерам запрещено инициировать соединения с внешним миром и другими сервисами, если это явно не разрешено.

Cloud-специфика (IMDSv2, VPC endpoints)

IMDS решает важную задачу безопасности для облачных пользователей, предоставляя доступ к временным и часто обновляемым учетным данным, а также устраняя необходимость жестко прописывать (hardcode) или вручную (либо программно) распространять конфиденциальные учетные данные непосредственно на экземпляры. Вторая версия Службы метаданных экземпляров (IMDSv2) добавляет дополнительные механизмы защиты; в частности, IMDSv2 использует сеансовую аутентификацию со следующими усовершенствованиями.

  1. Для начала сеанса IMDSv2 требуется создание секретного токена посредством простого HTTP-запроса типа PUT; этот токен должен использоваться для получения информации при выполнении вызовов к IMDSv2.
  2. Токен сеанса IMDSv2 должен передаваться в качестве заголовка в последующих запросах к IMDSv2 для получения информации из службы метаданных. В отличие от статического токена или фиксированного заголовка, сеанс и соответствующий ему токен уничтожаются, как только завершается процесс, использующий этот токен. Сеансы IMDSv2 могут длиться до шести часов.
  3. Токен сеанса может быть использован только непосредственно с того экземпляра EC2, на котором был инициирован данный сеанс.
  4. Вы можете либо повторно использовать уже существующий токен, либо создавать новый токен для каждого отдельного запроса.
  5. Запросы PUT для создания токена сеанса блокируются, если они содержат заголовок X-forwarded-for.
VPC Endpoints (Внутренние шлюзы до сервисов) позволяют виртуальным машинам внутри изолированной приватной сети общаться с глобальными сервисами облака (например, с хранилищем AWS S3, базами данных DynamoDB или KMS-клиентами) напрямую через внутреннюю сеть AWS, не выходя в публичный интернет.

Если хакер заперт внутри сети и не может вызвать внешний адрес 169.254.169.254, он начинает сканировать внутренний диапазон сети на предмет живых веб-интерфейсов.

Если в компании настроен S3 VPC Endpoint, атакующий через SSRF может обратиться к внутреннему DNS-имени этого эндпоинта. Если у роли, под которой запущено приложение, есть доступ к бакетам (чтение/запись), хакер сможет скачивать конфиденциальные файлы компании прямо из S3, используя SSRF как прокси, даже если сам бакет закрыт от всего интернета.


Литература

https://infosecwriteups.com/ssrf-in-apis-how-a-single-url-parameter-can-expose-internal-systems-63128bff63a4

https://kariiem.medium.com/0dssrf-automate-finding-ssrf-external-service-interactions-open-redirects-944be6770a02

https://www.yeswehack.com/learn-bug-bounty/server-side-request-forgery-ssrf

https://medium.com/@zoningxtr/gopher-protocol-a-forgotten-protocol-with-modern-security-implications-932188d5c65e

https://www.intigriti.com/researchers/blog/hacking-tools/ssrf-a-complete-guide-to-exploiting-advanced-ssrf-vulnerabilities#2-bypassing-host-whitelists

https://blogs.jsmon.sh/source-code-analysis-exploiting-parser-differentials-in-ssrf-unicode/

https://iaraoz.medium.com/hacking-apis-attackers-exploiting-ssrf-57624d575987

https://bitpanic.medium.com/beginners-introduction-to-server-side-request-forgery-85c3a35eb726

https://aws.amazon.com/blogs/security/get-the-full-benefits-of-imdsv2-and-disable-imdsv1-across-your-aws-infrastructure/
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab