Nuevo en Symfony 5.1: Protección frente a ataques SSRF

Las vulnerabilidades de seguridad tipo CSRF ("Cross-site request forgery") son bastante conocidas en el ámbito del desarrollo web y Symfony ofrece protección automática frente a ellas desde hace muchos años. Sin embargo, existe otra vulnerabilidad relacionada pero mucho menos conocida llamada SSRF (Server-side request forgery).

Gracias al SSRF un atacante puede obligar a un sitio web a realizar cualquier petición HTTP arbitraria, incluyendo los hosts y dirección IP privadas. El siguiente ejemplo simplificado ha sido extraído de este artículo que lo explica el problema en detalle:

Paso 1: El admin de tu backend se puede acceder libremente pero solo desde IPs internas (ej. https://192.168.0.68/admin).

Paso 2: Tu aplicación web realiza peticiones a APIs para obtener cierta información (ej. las existencias de tu producto):

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

Paso 3: El atacante puede enviar la siguiente petición para acceder a tu admin:

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

La solución, como suele ser habitual en muchas vulnerabilidades de seguridad, consiste en filtrar los datos de entrada (en este caso, la dirección IP solicitada por el usuario). En Symfony 5.1 hemos mejorado el componente HttpClient para añadir un nuevo NoPrivateNetworkHttpClient que por defecto bloquea todas las direcciones IP internas.

Este nuevo cliente decora al cliente HTTP por defecto, así que puedes usarlo de la siguiente manera:

use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\NoPrivateNetworkHttpClient;
 
$client = new NoPrivateNetworkHttpClient(HttpClient::create());
// las peticiones a redes públicas no cambian
$client->request('GET', 'https://example.com/');
 
// pero las peticiones a redes privadas ahora están bloqueadas por defecto
$client->request('GET', 'http://localhost/');
 
// el segundo argumento opcional define las redes que se van a bloquear
// en este ejemplo, las peticiones desde 104.26.14.0 a 104.26.15.255 lanzan una
// excepción, pero el resto de peticiones (incluso a otras redes privadas), se permiten
$client = new NoPrivateNetworkHttpClient(HttpClient::create(), ['104.26.14.0/23']);

Esta funcionalidad fue contribuida por Hallison Boaventura en el pull request #35566.


Fuente: New in Symfony 5.1: Server-side request forgery protection

Comentarios

Publicada el

7 de mayo de 2020

Proyectos Symfony destacados

La plataforma de eCommerce 100% Symfony que rivaliza con Magento y PrestaShop. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.