Сборщик - gradle 5.6.4. Имеется wrapper этой версии в каждом из модулей. Можно открыть всю папку mai-sec как новый проект и затем выполнить gradle-таск mai-sec:build/build, что соберет всё вложенные приложения.
Простейшее веб-приложение, которое было создано злоумышленником. Он оставляет ссылки на страницу этого приложения kittens.html, которая содержит якобы легитимные ссылки для просмотра контента. На самом деле при переходе по этим ссылкам осуществляется атака CSRF: если пользователь был залогинен в банке, то с его счета спишутся деньги в пользу хакера.
В текущей реализации существует баг из-за того, что все веб-приложения запускаются на одном домене localhost
: если залогиниться в банке, затем залогиниться на форуме, затем перейти на kittens.html
и нажать на ссылку, отправляющую в приложение банка, банк просит авторизоваться еще раз, т.к. его авторизационные куки были перетерты куками форума. Поэтому надо авторизоваться в банке, затем нажать два раза "Назад" в браузере и снова нажать на кнопку на странице злоумышленника. В реальных условиях такого бага происходить не будет по понятным причинам.
Создать docker image, сделать контейнер, запустить. Рабочий порт приложения - 1337, сделать маппинг этого порта при запуске контейнера (--publish 1337:1337
).
Уязвимая версия вспомогательного приложения "банк". POST-эндпоинт /transfer
подвержен атаке CSRF. Для удобства ведется логирование транзакций.
Данные для входа: alice / 1; bob / 1; hacker / hack0r
Защита от CSRF включена в Spring по умолчанию, пришлось выключить ее (см. класс SecurityConfiguration
).
Создать docker image, сделать контейнер, запустить. Рабочий порт приложения - 6080, сделать маппинг этого порта при запуске контейнера (--publish 6080:6080
).
Патченная версия приложения "банк". Во все POST-запросы добавлен токен CSRF (защита с помощью токена синхронизации). POST-эндпоинт /transfer
выкидывает ошибку 403, если токен отсутствует или не соответствует ожидаемому токену.
Данные для входа: alice / 1; bob / 1; hacker / hack0r
Создать docker image, сделать контейнер, запустить. Рабочий порт приложения - 6080, сделать маппинг этого порта при запуске контейнера (--publish 6080:6080
).
Уязвимая версия основного приложения "форум".
Уязвимости:
-
SQL-инъекция в поле "Поиск" - используется "сырой" SQL-запрос с конкантенацией пользовательского ввода без проверок
-
Хранимая XSS в поле добавления сообщений в темах - можно писать любые тэги, сообщение с тэгами будет сохранено в СУБД и выгружено в таком же виде при просмотре темы, фильтрация отсутствует
-
IDOR, позволяющая смотреть темы, к которым у пользователя нет доступа
-
Missing Function Level Access Control: страница администрирования и функции, представленные на ней, доступны любому, кто узнает "секретную ссылку" на эту страницу (считается, что она неизвестна никому, кроме администраторов)
Данные для входа:
alice / 1 (читатель)
bob / 1 (редактор)
manager / mngr (менеджер)
admin1 / superpa$$word1 (админ)
admin2 / superpa$$word2 (админ)
admin3 / superpa$$word3 (админ)
hacker / Imhack0r (читатель)
Бизнес-правила (те, которые важны для воспроизведения уязвимостей):
-
Права в порядке возрастания привилегий: читатель - 0, редактор - 1, менеджер - 2, админ - 4
-
Пользователь может читать только те темы, которые были начаты пользователем с правами на единицу большими, чем у пользователя, или меньшими (т.е. например, читатель может читать темы читателей и редакторов; менеджер - темы читателей, редакторов и менеджеров (но не администраторов)). Темы менеджеров могут читать и комментировать все.
Воспроизведение уязвимостей:
-
SQL-инъекция: залогиниться за hacker, сделать поиск по слову "не". Поиск выдаст 3-4 сообщения - только те, которые должны быть доступны этому пользователю для чтения. Вернуться и сделать поиск по
' OR '' = '
, что превратит запрос SQL в коде... WHERE ... LIKE '%" + input + "%' ...
в... WHERE ... LIKE '%' OR '' = '%' ...
и приведет к выводу всех записей таблицы. -
XSS: залогиниться за hacker, зайти в тему "Обратная связь (здесь могут писать даже потребители)" и оставить пробное сообщение
<script>alert("text");</script>
. При возвращении в тему будет выведено предупреждение с нашим текстом. -
IDOR: залогиниться за hacker. На домашней странице есть список тем, видно их ссылки. У тем номера 1001, 1002, 1003, 1006. Видимо, есть и темы 1004 и 1005, т.е. у тем форума очень очевидные id. Попробовать перейти на страницу
http://localhost:8080/threads/1005
- успех, тему видно. В теме обсуждаются пароли администраторов и оставлена секретная ссылка на страницу администрирования, т.к. админы считают, что эта тема видна только им (согласно бизнес-логике, это действительно должно быть так). -
Missing Function Level Access Control: используем ссылку, которую получили при эксплуатации IDOR и беспрепятственно переходим на
http://localhost:8080/secret_admin_page.html
. Действие "удалить пользователя" также можно успешно выполнить. -
CSRF: Залогиниться за hacker, оставить в теме "Обратная связь (здесь могут писать даже потребители)" сообщение
<a href="http://localhost:1337/kittens.html">Visit my newest coolest website!!!</a>
. Теперь залогиниться за alice в банке. История транзакций пуста. Затем пойти на форум, залогиниться там и перейти по ссылке хакера. На открывшейся странице нажать кнопку. (Здесь см. примечание "Известные проблемы" для task-attacker-site). Итог действий: в истории транзакций банка в аккаунте alice - перевод хакеру, который она, фактически, не делала.
Создать docker image, сделать контейнер, запустить. Рабочий порт приложения - 8080, сделать маппинг этого порта при запуске контейнера (--publish 8080:8080
). Запускать в паре с уязвимым банком и приложением хакера.
Версия основного приложения "форум" без уязвимостей.
Исправления:
-
SQL-инъекция в поле "Поиск" - запрос переделан так, чтобы использовать возможности параметризованных запросов JPA; также дополнительно приведена реализация с использованием методов Spring Data. Параметризация работает так, что инъекция станет аргументом критерия отбора, а не частью запроса.
-
Хранимая XSS в поле добавления сообщений в темах - добавлена фильтрация
org.springframework.web.util.HtmlUtils.htmlEscape()
при сохранении текста сообщения в СУБД и загрузке его оттуда при отрисовке страницы темы и домашней страницы. -
IDOR, позволяющая смотреть темы, к которым у пользователя нет доступа - добавлена проверка, есть ли у пользователя права для просмотра темы, при переходе в нее.
Также хороший метод защиты заключается в рандомизации id темы (например, использовать не числа, а UUID), это также поможет защитить от несанкционированного добавления сообщений в недоступные темы из программ вроде Postman, т.к. там требуется указывать id темы. -
Missing Function Level Access Control: добавлена проверка при переходе на страницу, является ли пользователь администратором.
-
CSRF: включена проверка токена, так же, как и для банка.
Повторное воспроизведение уязвимостей:
-
SQL-инъекция: залогиниться за hacker, сделать поиск по слову "не". Поиск выдаст 3-4 сообщения - только те, которые должны быть доступны этому пользователю для чтения. Вернуться и сделать поиск по
' OR '' = '
. Выведено 0 записей. -
XSS: залогиниться за hacker, зайти в тему "Обратная связь (здесь могут писать даже потребители)" и оставить пробное сообщение
<script>alert("text");</script>
. При возвращении в тему будет выведено сообщение с нашим текстом просто в виде текста. -
IDOR: залогиниться за hacker. На домашней странице есть список тем, видно их ссылки. У тем номера 1001, 1002, 1003, 1006. Видимо, есть и темы 1004 и 1005, т.е. у тем форума очень очевидные id. Попробовать перейти на страницу
http://localhost:8080/threads/1005
- выводится сообщение "У Вас недостаточно прав для просмотра этой темы". -
Missing Function Level Access Control: используем ссылку
http://localhost:8080/secret_admin_page
. Получаем ошибку "404 NOT FOUND". При использовании ссылки администратором страница открывается. -
CSRF: Залогиниться за hacker, оставить в теме "Обратная связь (здесь могут писать даже потребители)" сообщение
<a href="http://localhost:1337/kittens.html">Visit my newest coolest website!!!</a>
.
Теперь залогиниться за alice в банке. История транзакций пуста. Затем пойти на форум, залогиниться там и перейти по ссылке хакера. На открывшейся странице нажать кнопку. (Здесь см. примечание Известные проблемы).
Итог действий: в истории транзакций банка в аккаунте alice - всё еще пусто, после нажатия кнопки на странице хакера произошла ошибка 403 Forbidden (стандартная реакция Spring при отсутствии или несоответствии токена CSRF).
Создать docker image, сделать контейнер, запустить. Рабочий порт приложения - 8080, сделать маппинг этого порта при запуске контейнера (--publish 8080:8080
).
Запускать в паре с патченным банком и приложением хакера.