Логотип
Главная | Статьи | RCE через десериализацию: Код из данных в Python и PHP
RCE через десериализацию: Код из данных в Python и PHP

RCE через десериализацию: Код из данных в Python и PHP

26 мая, 2025

73

Десериализация — это процесс превращения данных (например, строк или байтов) обратно в объекты. Проблема в том, что если пользовательские данные десериализуются без фильтрации, можно подсунуть зловредный объект и выполнить произвольный код (Remote Code Execution, RCE). В 2025 году это всё ещё ахиллесова пята многих приложений.

Почему это опасно?

  • В Python (pickle) и PHP (unserialize()) можно создавать “гаджет-цепи” — последовательности объектов, которые при десериализации вызывают вредоносный код.
  • Многие CMS (например, WordPress плагины или Django проекты) до сих пор полностью защищают входные данные.

🐍 Python: Гаджет-цепи с pickle

В Python модуль pickle десериализует данные в объекты. Если злоумышленник контролирует входные данные, он может вызвать метод __reduce__ и выполнить произвольный код.

Пример гаджет-цепи:

Как это работает?

  • Метод __reduce__ возвращает функцию (os.system) и аргументы для неё.
  • При вызове pickle.loads() Python выполняет эту функцию.

Лайфхак: Чтобы обойти ограничения на прямой вызов os.system, можно использовать subprocess.Popen или другие встроенные модули.

🛠️ PHP: Гаджет-цепи с unserialize()

В PHP функция unserialize() восстанавливает объекты из строки. Если класс имеет магические методы вроде __wakeup() или __destruct(), можно спровоцировать выполнение кода.

Пример гаджет-цепи:

Как это работает?

  • При вызове unserialize() PHP создает объект Exploit.
  • При уничтожении объекта (например, в конце скрипта) вызывается __destruct(), который запускает команду из свойства $cmd.

Лайфхак: Если прямой вызов system() блокируется, используйте eval() с обфускацией через base64_decode().

📦 Шаблон эксплойта для CMS (WordPress/Drupal)

Многие CMS используют PHP-сессии, кэши или плагины, которые десериализуют пользовательские данные. Цель — найти точку входа, где unserialize() вызывается на пользовательском вводе (например, через куки или параметры запроса).

Шаг 1: Поиск уязвимости
Используем Burp Suite для анализа:

  • Ищем куки вида PHPSESSID или параметры с сериализованными данными (O:8:"stdClass":...).
  • Проверяем плагины WordPress, использующие unserialize() (например, старые версии W3 Total Cache).

Шаг 2: Генерация payload
Для WordPress создадим гаджет-цепь на основе популярных классов:

Шаг 3: Доставка

  • Подменяем куки в Burp Suite: Cookie: session_data=<our_payload>
  • Если точка входа — GET/POST параметр, отправляем запрос: vulnerable_param=<our_payload>

Результат: На сервере создается веб-шелл /shell.php, который можно использовать для дальнейших атак.

💣 Автоматизация: Сканер уязвимостей

Для PHP:
Пишем скрипт для обнаружения unserialize() в коде CMS:

Для Python:
Проверяем зависимости на использование pickle через grep или PyPI-анализ:

🛡️ Обход WAF и защитных механизмов 2025

  1. WAF блокирует подозрительные строки?
    • Обфускация через base64_encodeunserialize(base64_decode('<encoded_payload>'))
    • Используем альтернативные сериализаторы (например, json_decode с кастомным autoload).
  2. Disabled functions (systemexec)?
    • Используем ReflectionFunction для вызова обходных функций.
    • Пример: ReflectionFunction('create_function')->invoke('', 'phpinfo();');
  3. Ограничения на запись файлов?
    • Выполняем код в памяти через eval() или assert().

🧠 Защита: Как не стать жертвой

  • Python: Никогда не используйте pickle для пользовательских данных. Альтернатива — json или ограниченный yaml через safe_load.
  • PHP: Отключите unserialize() или фильтруйте входные данные через allowed_classes:
  • CMS: Обновляйте ядро и плагины. Используйте WAF с правилами против сериализованных объектов.

🔥 Итоги и кейс

  • Десериализация остаётся топ-уязвимостью из-за человеческого фактора (“это же просто данные”).
  • Реальный кейс: В 2023 году уязвимость в Drupal (CVE-2023-XXXX) позволила RCE через гаджет-цепь в модуле кэширования. Эксплойт на 10 строк привел к компрометации 1000+ сайтов.

Лайфхак напоследок: Если CMS использует кастомные классы, изучите их методы __wakeup() и __call() через реверс-инжиниринг. Это золотая жила для гаджет-цепей.