Server-Side Request Forgery (SSRF)

Что такое SSRF?

Server-Side Request Forgery (SSRF) — это уязвимость веб-безопасности, позволяющая атакующему заставить серверное приложение выполнять запросы к непредусмотренному месту назначения.

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

server-side request forgery.svg

Каковы последствия атак SSRF?

Успешная атака SSRF часто приводит к несанкционированным действиям или доступу к данным внутри организации. Это может происходить как в уязвимом приложении, так и на других бекэнд-системах, с которыми приложение может взаимодействовать. В некоторых ситуациях уязвимость SSRF может позволить атакующему выполнять RCE.

Распространенные атаки SSRF

SSRF-атаки часто злоупотребляют доверительными отношениями, чтобы эскалировать атаку от уязвимого приложения и выполнить несанкционированные действия. Эти доверительные отношения могут существовать по отношению к самому серверу или к другим бекэнд-системам внутри той же организации.

Атаки SSRF на сервер

В атаке SSRF на сервер атакующий заставляет приложение выполнить HTTP-запрос обратно к серверу, на котором размещено приложение, через его loopback сетевой интерфейс. Обычно это делается путем передачи URL с именем хоста вроде 127.0.0.1 (зарезервированный IP-адрес, указывающий на адаптер loopback) или localhost (распространенное имя для того же адаптера).

Например, представим приложение магазина, которое позволяет пользователю посмотреть, имеется ли товар в наличии в конкретном магазине. Чтобы предоставить сведения о наличии, приложение должно опрашивать различные REST API бекэнда. Оно делает это, передавая URL соответствующего эндпоинта API бекэнда через фронтенд HTTP-запрос. Когда пользователь просматривает статус наличия товара, его браузер выполняет следующий запрос:

Это заставляет сервер выполнить запрос по указанному URL, получить статус наличия и вернуть его пользователю.

В этом примере атакующий может изменить запрос, указав URL, локальный для сервера:

Сервер извлекает содержимое URL /admin и возвращает его пользователю. Атакующий может открыть URL /admin, но административная функциональность обычно доступна только аутентифицированным пользователям. Это означает, что атакующий ничего интересного не увидит. Однако если запрос к URL /admin приходит с локальной машины, обычные механизмы контроля доступа обходятся. Приложение предоставляет полный доступ к административной функциональности, поскольку запрос выглядит как исходящий из доверенного места.

Почему приложения ведут себя таким образом и имплицитно доверяют запросам, приходящим с локальной машины? Это может происходить по разным причинам:

  • Проверка контроля доступа может быть реализована в другом компоненте, который расположен перед сервером приложения. Когда соединение устанавливается обратно к серверу, эта проверка обходится.

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

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

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

Атаки SSRF на другие бекэнд-системы

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

В предыдущем примере представим, что существует административный интерфейс по бекэнд-URL https://192.168.0.68/admin. Атакующий может отправить следующий запрос, чтобы эксплуатировать уязвимость SSRF и получить доступ к административному интерфейсу:

Обход типичных защит от SSRF

Часто встречаются приложения, содержащие поведение SSRF вместе с защитами, направленными на предотвращение эксплуатации уязвимостей. Нередко эти защиты можно обойти.

SSRF с фильтрами ввода на основе черного списка

Некоторые приложения блокируют ввод, содержащий имена хостов вроде 127.0.0.1 и localhost, или чувствительные URL, такие как /admin. В этой ситуации фильтр часто можно обойти следующими техниками:

  • Используйте альтернативное представление IP-адреса 127.0.0.1, например 2130706433, 017700000001 или 127.1.

  • Зарегистрируйте собственное доменное имя, которое резолвится в 127.0.0.1. Для этой цели вы можете использовать spoofed.burpcollaborator.net.

  • Обфусцируйте блокируемые строки с помощью URL-кодирования или вариаций регистра.

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

SSRF с фильтрами ввода на основе белого списка

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

Спецификация URL содержит ряд особенностей, которые, вероятно, будут упущены из виду при реализации разборов и проверок URL «на коленке» таким способом:

  • Вы можете встроить учетные данные в URL перед именем хоста, используя символ @. Например: https://expected-host:fakepassword@evil-host

  • Вы можете использовать символ # для указания фрагмента URL. Например: https://evil-host#expected-host

  • Вы можете использовать иерархию DNS, чтобы разместить требуемый ввод внутри полностью квалифицированного DNS-имени, которым вы управляете. Например: https://expected-host.evil-host

  • Вы можете применять URL-кодирование символов, чтобы запутать код разбора URL. Это особенно полезно, если код, реализующий фильтр, обрабатывает URL-кодированные символы иначе, чем код, выполняющий бекэнд HTTP-запрос. Вы также можете попробовать двойное кодирование символов; некоторые серверы рекурсивно URL-декодируют входные данные, что может приводить к дальнейшим расхождениям.

  • Вы можете комбинировать эти техники.

Подробнее

Обход фильтров SSRF через Open Redirect

Иногда можно обойти защиты на основе фильтров, эксплуатируя уязвимость Open Redirect.

В предыдущем примере представим, что отправляемый пользователем URL строго валидируется, чтобы предотвратить опасную эксплуатацию поведения SSRF. Однако в приложении, чьи URL разрешены, присутствует уязвимость Open Redirect. Если API, используемый для выполнения бекэнд HTTP-запроса, поддерживает переадресации, вы можете сформировать URL, который удовлетворяет фильтру и приводит к перенаправленному запросу к желаемой бекэнд-цели.

Например, в приложении есть уязвимость Open Redirect, при которой следующий URL:

Возвращает на:

Вы можете использовать уязвимость Open Redirect, чтобы обойти фильтр URL и эксплуатировать уязвимость SSRF следующим образом:

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

Уязвимости Blind SSRF

Уязвимости слепого SSRF возникают, если вы можете заставить приложение выполнить бекэнд HTTP-запрос по переданному URL, но ответ на бекэнд-запрос не возвращается во фронтенд-ответе приложения.

Blind SSRF сложнее эксплуатировать, но иногда приводит к RCE на сервере или других бекэнд-компонентах.

Поиск скрытой поверхности атаки для уязвимостей SSRF

Многие уязвимости Server-Side Request Forgery легко обнаружить, потому что в обычном трафике приложения встречаются параметры запросов, содержащие полные URL. Другие примеры SSRF сложнее найти.

Частичные URL в запросах

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

URL внутри форматов данных

Некоторые приложения передают данные в форматах, спецификация которых допускает включение URL, которые парсер формата может запрашивать. Очевидный пример — формат данных XML, который широко использовался в веб-приложениях для передачи структурированных данных от клиента к серверу. Когда приложение принимает данные в формате XML и парсит их, оно может быть уязвимо к XXE-инъекциям. Оно также может быть уязвимо к SSRF через XXE.

SSRF через заголовок Referer

Некоторые приложения используют серверные системы аналитики для отслеживания посетителей. Это программное обеспечение часто логирует заголовок Referer в запросах, чтобы отслеживать входящие ссылки. Часто аналитическое ПО посещает любые сторонние URL, которые встречаются в заголовке Referer. Обычно это делается для анализа содержимого ссылающихся сайтов, включая анкорный текст, используемый во входящих ссылках. В результате заголовок Referer часто является полезной атакуемой поверхностью для уязвимостей SSRF.

Blind Server-Side Request Forgery имеет примеры уязвимостей, связанных с заголовком Referer.

Last updated