Definición
Server-Side Request Forgery (SSRF) es una vulnerabilidad en la que una aplicación web hace una solicitud HTTP/TCP a una dirección controlada (parcialmente) por el usuario, sin validar si esa dirección es segura. Un atacante puede:
- Forzar conexiones a servicios internos de la infraestructura (metadata cloud, bases de datos, servicios internos)
- Escanear puertos de la red interna
- Exfiltrar datos de hosts accesibles desde el servidor (pero no desde internet)
Riesgo en CreaRack Pro
En el módulo Digital Signage, hay 3 chokepoints donde se abren conexiones a direcciones controladas por el usuario (admin o cliente):
- Deploy WebDAV (
monitoring/api/signage/deploy.py): abre conexión WebDAV adevice.device_ip(IP del reproductor digital) - Control de Display (
signage/services/display_control/): abre socket TCP a la IP del dispositivo (Samsung MDC 1515, LG 9761, PJLink 4352) - Adapters de vendor (
signage/services/adapters/): hacen requests HTTP a URLs/IPs de reproductores o sistemas de terceros
Sin validación, un admin podría (por error o si está comprometido) apuntar un dispositivo a:
169.254.169.254— metadata cloud (AWS, GCP) → fuga de credenciales de infra127.0.0.1:5432— PostgreSQL local → escaneo de puerto10.x.x.x— hosts internos de red — exfiltración de datos
Mitigación: check_scan_ip
CreaRack Pro hereda de network (sa1–sa5) un guard centralizado: check_scan_ip(ip_str) -> bool. Valida:
| Rango | Permitido | Razón |
|---|---|---|
RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) | ✅ | On-prem del cliente (uso legítimo) |
CGNAT (100.64.0.0/10) | ✅ | On-prem del cliente (carrier NAT) |
Loopback (127.0.0.0/8) | ❌ | SSRF al servidor mismo |
Link-local (169.254.0.0/16) | ❌ | Metadata cloud (AWS, GCP) |
Multicast (224.0.0.0/4) | ❌ | Ruido de red |
| Broadcast, reserved | ❌ | No encaminables |
Aplicación en Signage (s121)
Antes:
# Vulnerable
def deploy_content_to_device(device_id, ...):
device = SignagePlayer.objects.get(id=device_id)
webdav_put(device.device_ip, ...) # Sin validación
Después:
# Seguro
from network.services.security import check_scan_ip
def deploy_content_to_device(device_id, ...):
device = SignagePlayer.objects.get(id=device_id)
if not check_scan_ip(device.device_ip):
raise ValidationError(f"IP {device.device_ip} no permitida")
webdav_put(device.device_ip, ...)
Se aplica en:
deploy_content_to_device— antes de WebDAV PUTdisplay_control.controller— antes de abrir socket TCPadapters.registry.get_adapter— antes de hacer request HTTP
Casos de Uso Legítimos
- Un cliente on-prem con dispositivos en
192.168.x.xpuede seguir deployando - Un cliente con red local en
10.x.x.xpuede seguir controlando displays - Un cliente CGNAT con
100.x.x.xpuede seguir comunicándose
El guard preserva la funcionalidad legítima mientras bloquea ataques.
Referencias
- OWASP A10:2021 — Server-Side Request Forgery (SSRF)
- CWE-918 — Server-Side Request Forgery (SSRF)
- PortSwigger: SSRF
Véase también
- [[feature—signage—s121-permisos-rol-y-seguridad]]
- [[entity—network—service—check-scan-ip]]
- [[concept—saas—multi-tenancy]]