Уязвимости безопасности, такие как CSRF (подделка межсайтовых запросов), хорошо известны большинству веб-разработчиков, и Symfony обеспечивает автоматическую защиту от них. Связанная, но менее известная уязвимость называется SSRF (подделка запросов на стороне сервера).
SSRF позволяет злоумышленнику заставить серверное приложение отправлять HTTP-запросы в произвольный домен. Эти атаки также могут быть направлены на внутренние хосты и IP-адреса атакованного сервера. Следующий упрощенный пример был извлечен из этой статьи, которая подробно объясняет проблему:
Шаг 1: Ваш бэкэнд админки доступна, но только с внутренних IP-адресов (например, https://192.168.0.68/admin).
Шаг 2: Ваше веб-приложение отправляет API-запросы, подобные следующим, чтобы получить определенную информацию (например, информацию о товареку):
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=https://stock.weliketoshop.net:8080/product/stock/check%3FproductId%3D6%26storeId%3D1
Шаг 3: Злоумышленник может отправить следующий запрос для доступа к администратору бэкэнда:
POST /product/stock HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
stockApi=https://192.168.0.68/admin
Решение, как это происходит со многими уязвимостями безопасности, требует фильтрации пользовательского ввода (в данном случае IP-адрес, запрошенный пользователем). В Symfony 5.1 улучшили компонент HttpClient, добавив новый NoPrivateNetworkHttpClient
, который по умолчанию блокирует все внутренние IP-адреса.
Этот новый клиент украшает HttpClient
по умолчанию, поэтому вы можете использовать его следующим образом:
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\NoPrivateNetworkHttpClient;
$client = new NoPrivateNetworkHttpClient(HttpClient::create());
// nothing changes when requesting public networks
$client->request('GET', 'https://example.com/');
// however, all requests to private networks are now blocked by default
$client->request('GET', 'http://localhost/');
// the second optional argument defines the networks to block
// in this example, requests from 104.26.14.0 to 104.26.15.255 will result in an exception
// but all the other requests, including other internal networks, will be allowed
$client = new NoPrivateNetworkHttpClient(HttpClient::create(), ['104.26.14.0/23']);