Содержание статьи
vBulletin — это продвинутый форумный движок, который позволяет множеству пользователей общаться между собой. Из-за стремительного роста популярности мессенджеров форумы в 2020 году уже не так актуальны, но если и попадаются во время тестирования, то в двух случаях из трех это будет именно vBulletin.
Вкратце баг заключается в следующем: виджет tabbedcontainer_tab_panel разрешает загружать дочерние виджеты и передавать им произвольные параметры. С помощью специально сформированного запроса злоумышленник может вызвать widget_php
и удаленно выполнить произвольный код на PHP.
Уязвимость получила статус критической и была срочно исправлена разработчиками.
INFO
Баг обнаружил Амир Этемадие (Amir Etemadieh), более известный как @Zenofex. Уязвимости присвоен номер CVE-2020-17496. Проблема существует в vBulletin с версии 5.5.4 до 5.6.2. Эксплуатация возможна из-за неполного исправления уязвимости CVE-2019-16759.
Сегодня я рассмотрю, как vBulletin работает с роутингом запросов, как работают виджеты и их шаблоны, и, конечно же, разберем детали уязвимости и проэксплуатируем систему.
Стенд
Для тестового окружения, как всегда, будем использовать Docker. Сначала создадим контейнер для базы данных. Я воспользуюсь MySQL.
docker run -d -e MYSQL_USER="vb" -e MYSQL_PASSWORD="JS7G5yUmaV" -e MYSQL_DATABASE="vb" --rm --name=mysql --hostname=mysql mysql/mysql-server:5.7
Затем запустим контейнер, на котором будет располагаться веб-сервер и сам форум. Не забываем слинковать его с БД.
docker run --rm -ti --link=mysql --name=vbweb --hostname=vbweb -p80:80 debian /bin/bash
В качестве сервера я буду использовать Apache. Поэтому установим его и PHP с необходимыми модулями.
apt update && apt install -y apache2 php nano unzip netcat php-mysqli php-xml php-gd
Включаем модуль mod-rewrite и запускаем Apache.
a2enmod rewrite
service apache2 start
Теперь нужно установить vBulletin. Продукт коммерческий, и я здесь не стану рассматривать, как его получить. Все тесты будем проводить на последней уязвимой версии — 5.5.6. Распаковываем ее в директорию /var/www/html
и устанавливаем.
Если ты хочешь вместе со мной более подробно рассмотреть уязвимость и покопаться в сорцах, то неплохо бы настроить отладку. Я буду использовать связку Xdebug + PhpStorm.
Устанавливаем и активируем Xdebug. Делать это лучше после того, как vBulletin будет установлен, у меня были проблемы во время инсталляции, пришлось отключить.
apt update && apt install -y php-xdebug
phpenmod xdebug
Включаем удаленную отладку и указываем IP-адрес сервера. Обрати на него внимание, а также на пути к файлам — у тебя это все может быть другим.
echo "xdebug.remote_enable=1" >> /etc/php/7.3/apache2/conf.d/20-xdebug.ini
echo "xdebug.remote_host=192.168.99.1" >> /etc/php/7.3/apache2/conf.d/20-xdebug.ini
Теперь перезагружаем веб-сервер.
service apache2 restart
В PhpStorm включаем ожидание коннекта от отладчика. Добавляем параметр XDEBUG_SESSION_START=phpstorm
к запросу, если хотим, чтобы дебаггер сработал.
Стенд готов, и можно переходить к разбору уязвимости.
Обработка URI
Сначала посмотрим, как vBulletin обрабатывает запросы пользователя, а конкретно роуты.
.htaccess
01: <IfModule mod_rewrite.c>
02: RewriteEngine On
...
39: RewriteCond %{REQUEST_FILENAME} !-f
40: RewriteCond %{REQUEST_FILENAME} !-d
41: RewriteRule ^(.*)$ index.php?routestring=$1 [L,QSA]
Проверяется, существует ли файл, и если нет, то указанный URI передается в качестве параметра routestring
.
Как и большинство современных фреймворков, форум поддерживает автозагрузку классов через spl_autoload_register
.
index.php
33: require_once('includes/vb5/autoloader.php');
34: vB5_Autoloader::register(dirname(__FILE__));
includes/vb5/autoloader.php
13: abstract class vB5_Autoloader
14: {
15: protected static $_paths = array();
16: protected static $_autoloadInfo = array();
17:
18: public static function register($path)
19: {
20: self::$_paths[] = (string) $path . '/includes/'; // includes
21:
22: spl_autoload_register(array(__CLASS__, '_autoload'));
23: }
Затем начинается проверка переданного роута. Вызывается метод isQuickRoute
.
index.php
37: if (vB5_Frontend_ApplicationLight::isQuickRoute())
includes/vb5/frontend/applicationlight.php
079: public static function isQuickRoute()
080: {
...
091: foreach (self::$quickRoutePrefixMatch AS $prefix => $route)
092: {
093: if (substr($_REQUEST['routestring'], 0, strlen($prefix)) == $prefix)
094: {
095: return true;
096: }
097: }
098:
099: return false;
100: }
В переменной $quickRoutePrefixMatch
хранятся префиксы роутов, которые должны обрабатываться при помощи quickRoute
.
ajax/apidetach
ajax/api
ajax/render
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»