ТестированиеТестирование безопасностиИнженер по тестированию безопасности

Сервис принимает от пользователя URL для загрузки превью. Как проверить, не превращается ли эта функция в S...

Сервис принимает от пользователя URL для загрузки превью. Как проверить, не превращается ли эта функция в SSRF?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Проверка должна установить, может ли сервер по управляемому пользователем URL отправлять запросы во внутренние сети, к локальному хосту или к облачным служебным адресам. Для этого используют контролируемый внешний endpoint, проверяют сетевые обращения сервера и отдельно исследуют обходы фильтрации адресов.

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

Исторический контекст

Функции предварительного просмотра, импорта по ссылке, проверки вебхуков и загрузки удалённых ресурсов появились как способ переложить сетевую работу с клиента на сервер. Серверу это удобно: он имеет стабильный доступ к внешним ресурсам и может обработать результат единообразно.

Проблема возникает, когда такой серверный запрос получает доступ к сетевому окружению приложения. Внутренние панели, базы данных, служебные API и метаданные облачной инфраструктуры обычно не рассчитаны на обращения из недоверенного пользовательского контекста.

Постановка проблемы

Тестировщик передаёт URL на контролируемый домен и проверяет, действительно ли запрос выполняется сервером, а не браузером. Затем исследуются попытки обращения к локальному хосту, частным сетям, loopback-адресам, адресам привязки всех интерфейсов и служебным адресам среды размещения.

Опасность состоит не только в чтении ответа. Уязвимый сервер может отправить запрос во внутреннюю систему, вызвать действие с его сетевыми полномочиями или раскрыть содержимое ответа пользователю. Даже если тело ответа скрыто, факт успешного соединения иногда позволяет проводить сканирование внутренней сети по различиям во времени ожидания и кодах ошибок.

Подробное решение

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

Затем проверяют, как приложение обрабатывает адреса из запрещённых диапазонов. Важно учитывать не только строковое значение URL, но и результат разрешения DNS, последующие перенаправления, альтернативные представления адреса, IPv4 и IPv6, а также повторное разрешение имени во время соединения.

Надёжная защита строится по принципу разрешённого списка: приложение принимает только необходимые схемы, домены и порты, а сетевой слой дополнительно запрещает исходящие соединения к внутренним диапазонам. Одной проверки текста URL недостаточно: домен может разрешиться во внутренний адрес, а внешний ресурс — перенаправить запрос внутрь сети.

Нужно ограничить число перенаправлений, таймаут, размер ответа, допустимые порты и объём ресурсов. Полезны изоляция компонента загрузки, отдельные сетевые права и отсутствие доступа к служебным учётным данным. При этом блокировка всех исходящих соединений безопаснее, но может сломать требуемую бизнес-функцию; разрешённый список сложнее сопровождать, зато точнее соответствует необходимости.

Проверка считается неполной, если тестируется только HTTP и только один формат адреса. Следует также определить, поддерживаются ли другие схемы, как обрабатываются ошибки DNS и TLS, сохраняются ли загруженные ответы и может ли пользователь влиять на заголовки или метод запроса.

Ситуация из практики

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

Первый вариант был проще, но не учитывал DNS-перенаправления, IPv6 и последующие перенаправления. Второй требовал изменений инфраструктуры и согласования списка поставщиков, зато ограничивал не только ввод, но и фактические сетевые возможности процесса.

Выбрали изолированный загрузчик: он принимал только нужные домены и схемы, не имел доступа к внутренним сетям, ограничивал размер и время загрузки, а перенаправления проверялись на каждом шаге. В результате внешний функционал сохранился, а попытки обратиться к внутренним адресам блокировались независимо от их текстового представления.

Что кандидаты часто упускают

  1. Достаточно ли запретить внутренние IP-адреса в URL?

Нет. Имя домена может сначала разрешиться во внешний адрес, а затем при повторном разрешении — во внутренний, либо внешний сервер может вернуть перенаправление на запрещённый адрес. Проверять нужно конечный адрес каждого соединения и повторять проверку после перенаправления; ещё надёжнее — дополнить это сетевым запретом исходящих соединений.

  1. Считается ли SSRF уязвимостью, если пользователь не видит тело ответа?

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

  1. Почему разрешённый список доменов не всегда полностью решает проблему?

Разрешённый домен может быть скомпрометирован, перенаправлять запросы или разрешаться в неожиданные адреса. Поэтому нужно контролировать схему, порт, результат DNS-разрешения, каждый переход по перенаправлению и фактическое сетевое соединение. Дополнительная изоляция загрузчика и запрет доступа к внутренним сетям уменьшают последствия ошибки в логике фильтрации.