# Server-Side Request Forgery (SSRF)

## Что такое SSRF?

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

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

![server-side request forgery.svg](https://2753068357-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7KQ4F0M3A1jSCGxOdZRW%2Fuploads%2Fgit-blob-a8f409079a590f912f7f70c86e0f34a76fa00b11%2Fserver-side%20request%20forgery.svg?alt=media)

{% hint style="success" %}
**Лабораторные работы**

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

* [Посмотреть все лабораторные работы по SSRF](https://portswigger.net/web-security/all-labs#server-side-request-forgery-ssrf)
  {% endhint %}

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

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

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

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

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

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

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

```
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=http://stock.weliketoshop.net:8080/product/stock/check%3FproductId%3D6%26storeId%3D1
```

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

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

```
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=http://localhost/admin
```

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

{% hint style="success" %}
**LAB**

[**Basic SSRF against the local server**](https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-localhost)
{% endhint %}

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

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

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

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

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

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

```
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=http://192.168.0.68/admin
```

{% hint style="success" %}
**LAB**

[**Basic SSRF against another back-end system**](https://portswigger.net/web-security/ssrf/lab-basic-ssrf-against-backend-system)
{% endhint %}

## Обход типичных защит от 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 фильтры.

{% hint style="success" %}
**LAB**

[**SSRF with blacklist-based input filter**](https://portswigger.net/web-security/ssrf/lab-ssrf-with-blacklist-filter)
{% endhint %}

### 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-запрос. Вы также можете попробовать [двойное кодирование](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/essential-skills/obfuskaciya-atak-s-ispolzovaniem-kodirovok#obfuskaciya-s-pomoshyu-dvoinogo-url-kodirovaniya) символов; некоторые серверы рекурсивно URL-декодируют входные данные, что может приводить к дальнейшим расхождениям.
* Вы можете комбинировать эти техники.

{% hint style="success" %}
**LAB**

[**SSRF with whitelist-based input filter**](https://portswigger.net/web-security/ssrf/lab-ssrf-with-whitelist-filter)
{% endhint %}

{% hint style="info" %}
**Подробнее**

* [A new era of SSRF](https://portswigger.net/blog/top-10-web-hacking-techniques-of-2017#1)
  {% endhint %}

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

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

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

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

```
/product/nextProduct?currentProductId=6&path=http://evil-user.net
```

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

```
http://evil-user.net
```

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

```
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=http://weliketoshop.net/product/nextProduct?currentProductId=6&path=http://192.168.0.68/admin
```

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

{% hint style="success" %}
**LAB**

[**SSRF with filter bypass via open redirection vulnerability**](https://portswigger.net/web-security/ssrf/lab-ssrf-filter-bypass-via-open-redirection)
{% endhint %}

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

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

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

{% hint style="info" %}
**Подробнее**

[Blind Server-Side Request Forgery](https://wr3dmast3r.gitbook.io/portswiggerfundamental/server-side/ssrf/blind-ssrf)
{% endhint %}

## Поиск скрытой поверхности атаки для уязвимостей 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](https://wr3dmast3r.gitbook.io/portswiggerfundamental/server-side/ssrf/blind-ssrf) имеет примеры уязвимостей, связанных с заголовком Referer.

{% hint style="info" %}
**Подробнее**

* [Cracking the lens: Targeting auxiliary systems](https://portswigger.net/blog/cracking-the-lens-targeting-https-hidden-attack-surface#aux)
* [URL validation bypass cheat sheet](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet)
  {% endhint %}
