![]() |
https://forum.antichat.xyz/attachmen...213381cd71.png
Когда я впервые столкнулся с десериализацией на пентесте, это выглядело как магия: непонятный blob в cookie, утилита ysoserial, и через полминуты - reverse shell на WebLogic. Потом я потратил три вечера, чтобы понять, почему это сработало и как подобрать правильную gadget chain для нестандартного стека. Три вечера - потому что документация по gadget chain разбросана по десяткам issue на GitHub, а половина примеров устарела. Эта статья - результат того пути: от обнаружения сериализованных объектов в трафике до эксплуатации десериализации в Java, PHP и Python с разбором конкретных CVE. OWASP включал небезопасную десериализацию веб-приложений в Top 10 как отдельную категорию (A8:2017), а в редакции 2021 года объединил её с «Software and Data Integrity Failures» (A8:2021). В черновике OWASP Top 10 2025 CWE-502 по-прежнему входит в категорию A08. Но то, что категорию «укрупнили», не значит, что проблема стала менее опасной - уязвимости десериализации стабильно приводят к Remote Code Execution на корпоративных Java-серверах, PHP-фреймворках и Python-сервисах. По MITRE ATT&CK эксплуатация десериализации - это Exploit Public-Facing Application (T1190, Initial Access), а результат - Command and Scripting Interpreter (T1059, Execution). Ниже - практическое руководство: от идентификации формата до доставки payload - полный цикл от анализа CVE до рабочего шелла разобран в гайде по разработке эксплойтов. Как распознать сериализованные данные в трафике Прежде чем искать десериализацию RCE уязвимость, нужно найти точку входа. Сериализованные объекты передаются в cookie, POST-параметрах, заголовках и WebSocket-фреймах. Каждый язык оставляет характерный «отпечаток» - и если научиться его читать, полдела сделано. Сигнатуры Java, PHP и Python в HTTP-запросах Java. Сериализованные Java-объекты всегда начинаются с байтов Код:
ac ed 00 05Код:
rO0ABКод:
java.io.SerializableКод:
Content-Type: application/x-java-serialized-objectКод:
rO0ABPHP. Формат сериализации PHP текстовый - читается глазами. Строка начинается с маркеров типов: Код:
O:Код:
a:Код:
s:Код:
i:Код:
b:Код:
datasКод:
a:2:{s:4:"call";s:11:"trackOption";s:6:"status";b:0;}Код:
unserialize()Python. Модуль Код:
pickleКод:
\x80Код:
\x02Код:
\x05Код:
cbuiltinsКод:
cbuiltinКод:
cosКод:
!!python/object/apply:Код:
yaml.load()Код:
Loader=SafeLoaderМой рабочий процесс простой: перехват трафика в Burp, Base64-декод параметров, проверка первых байтов. Код:
ac edКод:
O:Код:
a:Код:
\x80\x0Xhttps://forum.antichat.xyz/attachmen...6808149835.png Эксплуатация десериализации Java через ysoserial Java - исторически главная площадка для десериализационных атак. Корпоративные стеки на WebLogic, JBoss, Spring Framework и Apache Struts годами содержали gadget chain, превращающие вызов Код:
ObjectInputStream.readObject()Требования к окружению: Java 1.7+ для запуска ysoserial, JAR-файл из GitHub releases ( Код:
frohoff/ysoserialПринцип работы: указываете тип gadget chain и команду ОС, ysoserial генерирует сериализованный Java-объект на stdout. Когда приложение с нужными библиотеками в classpath десериализует данные, цепочка срабатывает и выполняет команду. Часто упускаемый момент (я сам сначала на него не обратил внимания): уязвимость не в библиотеке, а в приложении, которое передаёт недоверенные данные в Код:
readObject()Код:
readObject()https://forum.antichat.xyz/attachmen...6808206538.png Подбор ysoserial gadget chain и CVE десериализации Java Ysoserial содержит более 30 gadget chain: CommonsCollections1–7, Spring1–2, Groovy1, Hibernate1–2, JSON1, Jdk7u21, ROME и другие. Не все ведут к RCE напрямую - некоторые пишут файлы или делают JNDI-lookup. Каждый требует конкретных библиотек конкретных версий. Код:
CommonsCollections1Код:
commons-collections:3.1Код:
CommonsCollections2Код:
commons-collections4:4.0Если classpath цели неизвестен (black-box), работает перебор: генерация payload для каждого chain с OOB-callback (DNS-запрос на Burp Collaborator) и анализ, какой вызвал обращение. Ещё есть GadgetProbe (расширение Burp Suite из BApp Store) - он определяет загруженные на сервере классы через DNS-взаимодействие при десериализации. Сужает перебор с десятков chain до единиц - экономит кучу времени. Bash: Код:
# Генерация payload для WebLogic (CommonsCollections1)Код:
AV:N/AC:L/PR:N/UI:NКод:
com.bea.core.apache.commons.collections.jarhttps://forum.antichat.xyz/attachmen...6808271336.png CVE-2017-9805: Apache Struts REST без фильтрации типов REST Plugin в Apache Struts 2.1.1–2.3.x (до 2.3.34) и 2.5.x (до 2.5.13) использовал Код:
XStreamHandlerКод:
AC:HОба CVE - классика T1190 (Exploit Public-Facing Application): атакующий обращается к торчащему в интернет endpoint, отправляет сериализованный payload, получает выполнение кода, а дальше - Web Shell (T1505.003, Persistence) или Reflective Code Loading (T1620, Defense Evasion) для загрузки вредоносных модулей в память. PHP десериализация: phpggc и black-box перебор цепочек PHP-приложения на Laravel, Symfony, Magento и Drupal регулярно содержат гаджеты для эксплуатации. Если в Java-мире всё крутится вокруг бинарного Код:
ObjectInputStreamКод:
unserialize()Инструмент phpggc (PHP Generic Gadget Chains) - PHP-аналог ysoserial. Содержит готовые gadget chain для десятков фреймворков и библиотек. Код:
phpggc -lКод:
phpggc -l | grep RCEBrute-force цепочек при black-box phpggc эксплуатации В идеале у пентестера есть доступ к исходному коду, чтобы определить доступные классы. На bug bounty или при black-box аудите кода нет. Исследователи Vaadata описали методику, которую я неоднократно применял: генерация payload для всех RCE-совместимых chain из phpggc и перебор через Burp Intruder. Bash: Код:
#!/bin/bashКод:
-aКод:
-bКод:
-uКод:
-fКод:
destruct()срабатывает немедленно после Код:
unserialize()Код:
Код:
destruct()Код:
__wakeup()Код:
-fВ кейсе Vaadata из нескольких сотен сгенерированных payload сработал Код:
Monolog/RCE8Код:
system('whoami /all')Магические методы и объектная инъекция в PHP Эксплуатация insecure deserialization в PHP базируется на магических методах. При вызове Код:
unserialize()Код:
wakeup()на восстановленном объекте. При уничтожении - Код:
Код:
destruct()Код:
__toString()Цепочка строится по принципу POP (Property-Oriented Programming): объект A в Код:
__destruct()Код:
system()Код:
exec()Код:
file_put_contents()Код:
eval()Если phpggc не содержит chain для целевого фреймворка, цепочку строят руками. Нужен доступ к коду (например, после эксплуатации отдельной уязвимости чтения файлов). Поиск входных точек: Код:
grep -rn 'destruct\|wakeup\|__toString' vendor/Десериализация Python pickle exploit: RCE без gadget chain Python-десериализация через Код:
pickleКод:
reduce()Код:
pickle.loads()Python: Код:
importКод:
pickle.loads()Где искать pickle:
Код:
.pklКод:
eval()Детект и митигация Для Java: замена Код:
ObjectInputStreamКод:
unserialize()Код:
json_decode()Код:
allowed_classesКод:
unserialize()Код:
pickle.loads()Код:
jsonКод:
msgpackКод:
safetensorsКод:
ac ed 00 05Код:
rO0ABПопробуйте прогнать свои сервисы через описанные сигнатуры - перехватите трафик в Burp, поищите Код:
rO0ABВопрос к читателям Кто работал с black-box phpggc-перебором на Laravel или Symfony - как вы обходите ситуацию, когда флаг Код:
-fКод:
Monolog/RCE8Код:
-a -b -u -fКод:
-fКод:
__wakeup()Код:
datas |
| Время: 15:26 |