Комбо для Drupal. Как захватить сайт с Drupal, используя новые уязвимости

Содержание статьи

В этой статье я расскажу о двух уязвимостях в популярной CMS Drupal. Одна из них связана с архивами PHAR, не особенно страшна и работает только с правами админа, но если подключить другую (XSS), то такой дуэт становится уже очень опасным для любого сайта на незапатченном Drupal. Мы подробно разберем, как работают обе и откуда они взялись.

Итак, интересный случай XSS связан с тем, что разработчики не учли отдельные особенности работы некоторых функций PHP с кодировкой UTF-8. Из-за особенностей работы preg_replace атакующий может загрузить файл, содержащий HTML/JS-код, при переходе на который он будет выполнен в контексте браузера пользователя.

INFO

Эта уязвимость получила номер CVE-2019-6341, ее обнаружил Сэм Томас (Sam Thomas). Под угрозой оказались все версии ветки Drupal 8.6 до 8.6.13, Drupal 8.5 до 8.5.14 и Drupal 7 до 7.65.

Вторая уязвимость — unserialize при помощи архива PHAR. Отсутствие проверки пути до временной директории дает возможность использовать враппер phar://. В конце прошлого года я рассказывал об эксплуатации десериализации через архивы PHAR в форуме phpBB. В Drupal тоже есть возможность загрузки файлов и атакующий может загрузить картинку, содержащую полезную нагрузку. Затем указать путь до нее в качестве временной директории, используя поток phar, что приведет к выполнению произвольного кода.

INFO

Речь идет о CVE-2019-6339. Ей подвержены все версии Drupal 8.6 ниже 8.6.6, Drupal 8.5 ниже 8.5.9 и Drupal 7 ниже 7.62. Уязвимость была найдена Грегом Кнаддисоном (Greg Knaddison) из Drupal Security Team и Сэмом Томасом (Sam Thomas).

Стенд

Чтобы воспроизвести уязвимость, нам понадобятся два контейнера Docker. Первый — для сервера базы данных.

$ docker run -d -e MYSQL_USER="drupal" -e MYSQL_PASSWORD="6zbd9Ilfka" -e MYSQL_DATABASE="drupal" --rm --name=mysql --hostname=mysql mysql/mysql-server:5.7

Второй — официальный, от разработчиков Drupal, с последней уязвимой к обоим багам версией — 8.6.5.

$ docker run -d --rm -p80:80 --link=mysql --name=drupalvh --hostname=drupalvh drupal:8.6.5

Теперь нужно пройти несложную процедуру инсталляции.

Установка Drupal 8.6.5Установка Drupal 8.6.5

Если требуется отладка, то я по-прежнему рекомендую использовать PhpStorm и расширение Xdebug helper для браузера. Эта связка работает быстро и стабильно. Чтобы иметь возможность дебага, я дополнительно установлю PHP-расширение Xdebug.

$ docker exec -ti drupalvh /bin/bash
$ pecl install xdebug-2.6.1
$ echo "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/xdebug.so" > /usr/local/etc/php/conf.d/php-xdebug.ini
$ echo "xdebug.remote_enable=1" >> /usr/local/etc/php/conf.d/php-xdebug.ini
$ echo "xdebug.remote_host=192.168.99.1" >> /usr/local/etc/php/conf.d/php-xdebug.ini
$ service apache2 reload

Не забудь поменять IP-адрес 192.168.99.1 на свой и обрати внимание на путь до скомпилированной библиотеки xdebug.so. Далее нужно скачать исходники Drupal, и после перезагрузки конфигов Apache можно запускать отладчик.

После завершения установки CMS необходимо будет создать тестовую страницу или запись.

Создание тестовой записи в DrupalСоздание тестовой записи в Drupal

Помимо этого, для тестирования XSS понадобится любой пользователь, который сможет загружать файлы и оставлять комментарии. В дефолтной инсталляции это можно делать после прохождения регистрации. Как вариант, можешь просто создать юзера в админке.

Путь к XSS

Начнем с межсайтового скриптинга. У пользователей Drupal есть возможность комментировать записи. И, как и в любой современной CMS, в комментариях можно использовать базовую разметку. Функция, которая нам интересна, — это добавление картинок.

Добавление картинок в форме комментирования записи в DrupalДобавление картинок в форме комментирования записи в Drupal

Причем картинка загружается с компьютера пользователя. Имена загружаемых файлов могут представлять опасность, одна из последних уязвимостей в WordPress тому пример.

За сохранение загруженных файлов отвечает функция _file_save_upload_single.

core/modules/file/file.module
function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $validators = [], $destination = FALSE, $replace = FILE_EXISTS_RENAME) { ... $file->destination = file_destination($destination . $file->getFilename(), $replace);

Обрати внимание на аргумент $replace. Он отвечает за ситуацию, когда в директории уже присутствует файл с таким же именем, как у загружаемого. По дефолту новый файл переименовывается.

core/includes/file.inc
function file_destination($destination, $replace) { if (file_exists($destination)) { switch ($replace) { ... case FILE_EXISTS_RENAME: $basename = drupal_basename($destination); $directory = drupal_dirname($destination); $destination = file_create_filename($basename, $directory); ... return $destination;

Функция file_create_filename генерирует новое имя для загружаемого файла. Но перед этим производится санитизация названия. Убираются все нежелательные символы.

core/includes/file.inc
function file_create_filename($basename, $directory) { ... $basename = preg_replace('/[\x00-\x1F]/u', '_', $basename); if (substr(PHP_OS, 0, 3) == 'WIN') { // These characters are not allowed in Windows filenames $basename = str_replace([':', '*', '?', '"', '<', '>', '|'], '_', $basename); }

Функция preg_replace заменяет на символ подчеркивания (_) все символы с ASCII-кодом до 31 (1F). И все бы ничего, если бы не PCRE-модификатор u (PCRE_UTF8). Он интерпретирует входные данные как строку UTF-8. Допустимая длина символа UTF-8 — от одного до четырех байт. UTF-8 спроектирован с учетом обратной совместимости с набором символов ASCII. Поэтому в диапазоне однобайтовых кодов (0x00—0x7F) ASCII и UTF-8 пересекаются.

При работе функций preg_* с этой кодировкой есть небольшая особенность: если переданная строка имеет некорректный формат, то результатом работы будет NULL, а выполнение кода продолжится. Об этом четко написано в документации — см. справку по модификатору u.

Продолжение доступно только подписчикам

Материалы из последних выпусков можно покупать отдельно только через два месяца после публикации. Чтобы продолжить чтение, необходимо купить подписку.

Подпишись на «Хакер» по выгодной цене!

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Читать новость в источнике Xakep

0