Seguridad PHP explicada · defensivo
SSRF en PHP: qué es y cómo corregirla
Las vistas previas de enlaces, webhooks, importación de imágenes y generadores de PDF hacen que el servidor descargue una URL. Si el visitante controla esa URL, puede dirigir su servidor a lugares que él no alcanza.
Última actualización
Qué es
Su servidor suele estar dentro de una red de confianza. Sus peticiones alcanzan bases de datos, paneles de administración, otros microservicios y servicios de metadatos de la nube que entregan credenciales. La SSRF convierte cualquier función de descarga de URL en un proxy hacia esa red. MITRE la clasifica como CWE-918 y OWASP mantiene una hoja de prevención específica.
Cómo detectarlo
- Busque
curl_setopt(... CURLOPT_URL ...),file_get_contents($var),fopen($var),get_headers()y clientes HTTP como Guzzle que tomen una URL de la entrada. - Enumere todas las funciones que descargan contenido remoto: webhooks, importación de avatar o imagen, vistas previas de enlaces, lectores de feeds, renderizado de PDF o capturas, XML con entidades externas.
- Revise el tráfico saliente del servidor web; peticiones inesperadas a
169.254.169.254,localhosto rangos privados son una señal de alarma.
Cómo corregirlo
- Permita solo los hosts y esquemas que la función realmente necesita (normalmente solo
https) y rechace el resto. - Resuelva usted el host, rechace direcciones privadas, de loopback y link-local, y conéctese a esa IP resuelta para que el DNS no cambie entre la comprobación y el uso.
- Desactive el seguimiento de redirecciones (
CURLOPT_FOLLOWLOCATIONen false) y limite los protocolos conCURLOPT_PROTOCOLS. - En la nube, exija tokens de sesión para los metadatos de instancia (por ejemplo AWS IMDSv2) y limite el tráfico saliente con un firewall.
Comprobaciones de solo lectura y patrones seguros
# Find server-side fetches that may take a user-supplied URL (read-only)
grep -rnE "(curl_setopt.*CURLOPT_URL|file_get_contents\s*\(\s*\$|fopen\s*\(\s*\$)" --include=*.php . | grep -v /vendor/
// Allowlist hosts and schemes before fetching
$u = parse_url($url);
$allowed = ['api.example.com'];
if (($u['scheme'] ?? '') !== 'https' || !in_array($u['host'] ?? '', $allowed, true)) {
throw new RuntimeException('URL not allowed');
}
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);¿Basta con bloquear 127.0.0.1?
No. Las notaciones alternativas de IP, IPv6, nombres DNS que resuelven a direcciones privadas y las redirecciones evitan las listas de bloqueo simples. OWASP recomienda listas de permitidos.
¿Un WAF detiene la SSRF?
Puede detectar algunos patrones, pero no sabe qué hosts internos le importan. Corríjalo en el código.
Otras clases de vulnerabilidades PHP
- Inyección de objetos PHP: qué es y cómo corregirlaLa inyección de objetos PHP ocurre cuando una entrada controlada por el usuario llega a unserialize(), que puede instanciar objetos cuyos métodos mágicos ejecutan la lógica que elige el atacante.
- Inclusión de archivos en PHP (LFI/RFI): qué es y cómo corregirlaLa inclusión de archivos ocurre cuando la entrada del usuario controla la ruta que recibe include o require, lo que permite leer archivos locales (LFI) o, con allow_url_include activado, ejecutar código remoto (RFI).
- XSS en PHP: qué es y cómo prevenirloEl cross-site scripting (XSS) ocurre cuando una página PHP imprime en HTML datos controlados por el usuario sin escapar, de modo que el script de un atacante se ejecuta en el navegador de otros visitantes.
- Exposición de phpinfo(): por qué importa y cómo corregirlaUna página phpinfo() pública revela la versión exacta de PHP, los módulos cargados, las rutas y a menudo variables de entorno o secretos, lo que ayuda a los atacantes a apuntar a fallos como PHP2Shell.
Fuentes
Los enlaces externos salen de este sitio. No alojamos código de explotación.
- CWE-918: Server-Side Request Forgery (SSRF) — MITRE CWE
- Server-Side Request Forgery Prevention Cheat Sheet — OWASP Cheat Sheet Series