Deserialization
Basic Information
Серіалізація розуміється як метод перетворення об'єкта в формат, який може бути збережений, з наміром або зберегти об'єкт, або передати його як частину процесу комунікації. Ця техніка зазвичай використовується для забезпечення можливості відтворення об'єкта в майбутньому, зберігаючи його структуру та стан.
Десеріалізація, навпаки, є процесом, який протидіє серіалізації. Він включає в себе взяття даних, які були структуровані в певному форматі, і відновлення їх назад в об'єкт.
Десеріалізація може бути небезпечною, оскільки вона потенційно дозволяє зловмисникам маніпулювати серіалізованими даними для виконання шкідливого коду або викликати непередбачувану поведінку в додатку під час процесу відновлення об'єкта.
PHP
В PHP під час процесів серіалізації та десеріалізації використовуються специфічні магічні методи:
__sleep
: Викликається, коли об'єкт серіалізується. Цей метод повинен повертати масив імен усіх властивостей об'єкта, які повинні бути серіалізовані. Він зазвичай використовується для фіксації очікуючих даних або виконання подібних завдань очищення.__wakeup
: Викликається, коли об'єкт десеріалізується. Він використовується для відновлення будь-яких з'єднань з базою даних, які могли бути втрачені під час серіалізації, та виконання інших завдань повторної ініціалізації.__unserialize
: Цей метод викликається замість__wakeup
(якщо він існує) під час десеріалізації об'єкта. Він надає більше контролю над процесом десеріалізації в порівнянні з__wakeup
.__destruct
: Цей метод викликається, коли об'єкт збирається бути знищеним або коли скрипт закінчується. Він зазвичай використовується для завдань очищення, таких як закриття файлових дескрипторів або з'єднань з базою даних.__toString
: Цей метод дозволяє об'єкту розглядатися як рядок. Він може використовуватися для читання файлу або інших завдань на основі викликів функцій всередині нього, ефективно надаючи текстове представлення об'єкта.
Якщо ви подивитеся на результати, ви можете побачити, що функції __wakeup
та __destruct
викликаються, коли об'єкт десеріалізується. Зверніть увагу, що в кількох підручниках ви знайдете, що функція __toString
викликається, коли намагаються надрукувати деякий атрибут, але, очевидно, це більше не відбувається.
Метод __unserialize(array $data)
викликається замість __wakeup()
, якщо він реалізований у класі. Це дозволяє вам десеріалізувати об'єкт, надаючи серіалізовані дані у вигляді масиву. Ви можете використовувати цей метод для десеріалізації властивостей і виконання будь-яких необхідних завдань під час десеріалізації.
Ви можете прочитати пояснений PHP приклад тут: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, тут https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf або тут https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHP Deserial + Autoload Classes
Ви можете зловживати функціональністю автозавантаження PHP для завантаження довільних php файлів та більше:
PHP - Deserialization + Autoload ClassesСеріалізація посилальних значень
Якщо з якоїсь причини ви хочете серіалізувати значення як посилання на інше серіалізоване значення, ви можете:
PHPGGC (ysoserial для PHP)
PHPGGC може допомогти вам генерувати payload'и для зловживання десеріалізаціями PHP.
Зверніть увагу, що в кількох випадках ви не зможете знайти спосіб зловживати десеріалізацією в вихідному коді програми, але ви можете зловживати кодом зовнішніх PHP розширень.
Отже, якщо можете, перевірте phpinfo()
сервера та пошукайте в інтернеті (навіть на gadgets PHPGGC) можливі gadgets, якими ви могли б зловживати.
phar:// метадані десеріалізації
Якщо ви знайшли LFI, який просто читає файл і не виконує php код всередині нього, наприклад, використовуючи функції, такі як file_get_contents(), fopen(), file() або file_exists(), md5_file(), filemtime() або filesize(). Ви можете спробувати зловживати десеріалізацією, що відбувається при читанні файлу за допомогою протоколу phar. Для отримання додаткової інформації прочитайте наступний пост:
phar:// deserializationPython
Pickle
Коли об'єкт буде розпакований, функція __reduce__ буде виконана. При експлуатації сервер може повернути помилку.
Перед перевіркою техніки обходу спробуйте використати print(base64.b64encode(pickle.dumps(P(),2)))
, щоб згенерувати об'єкт, який сумісний з python2, якщо ви використовуєте python3.
Для отримання додаткової інформації про втечу з pickle jails дивіться:
Bypass Python sandboxesYaml & jsonpickle
Наступна сторінка представляє техніку зловживання небезпечним десеріалізацією в yamls бібліотеках python і завершується інструментом, який можна використовувати для генерації RCE десеріалізаційного payload для Pickle, PyYAML, jsonpickle та ruamel.yaml:
Python Yaml DeserializationClass Pollution (Python Prototype Pollution)
Class Pollution (Python's Prototype Pollution)NodeJS
JS Magic Functions
JS не має "магічних" функцій як PHP або Python, які виконуються лише для створення об'єкта. Але має деякі функції, які часто використовуються навіть без прямого виклику, такі як toString
, valueOf
, toJSON
.
Якщо зловживати десеріалізацією, ви можете компрометувати ці функції для виконання іншого коду (потенційно зловживаючи забрудненням прототипу), ви могли б виконати довільний код, коли їх викликають.
Ще один "магічний" спосіб викликати функцію без прямого виклику - це компрометація об'єкта, який повертається асинхронною функцією (promise). Тому, якщо ви перетворите цей об'єкт повернення в інший promise з властивістю під назвою "then" типу функція, він буде виконаний лише тому, що його повертає інший promise. Слідкуйте за цим посиланням для отримання додаткової інформації.
__proto__
та забруднення prototype
__proto__
та забруднення prototype
Якщо ви хочете дізнатися про цю техніку ознайомтеся з наступним посібником:
NodeJS - __proto__ & prototype PollutionЦя бібліотека дозволяє серіалізувати функції. Приклад:
Серіалізований об'єкт виглядатиме так:
Ви можете побачити в прикладі, що коли функція серіалізується, до серіалізованого об'єкта додається прапорець _$$ND_FUNC$$_
.
Всередині файлу node-serialize/lib/serialize.js
ви можете знайти той же прапорець і як код його використовує.
Як ви можете бачити в останньому фрагменті коду, якщо прапорець знайдено, використовується eval
для десеріалізації функції, тому в основному вхідні дані користувача використовуються всередині функції eval
.
Однак, просто серіалізувати функцію не виконає її, оскільки необхідно, щоб якась частина коду викликала y.rce
в нашому прикладі, і це вкрай малоймовірно.
У будь-якому випадку, ви могли б просто модифікувати серіалізований об'єкт, додавши деякі дужки, щоб автоматично виконати серіалізовану функцію, коли об'єкт буде десеріалізовано.
У наступному фрагменті коду зверніть увагу на останню дужку і як функція unserialize
автоматично виконає код:
Як було зазначено раніше, ця бібліотека отримає код після _$$ND_FUNC$$_
і виконає його за допомогою eval
. Тому, щоб автоматично виконати код, ви можете видалити частину створення функції та останню дужку і просто виконати JS однолінійник як у наступному прикладі:
Ви можете знайти тут додаткову інформацію про те, як експлуатувати цю вразливість.
Помітним аспектом funcster є недоступність стандартних вбудованих об'єктів; вони виходять за межі доступної області. Це обмеження запобігає виконанню коду, який намагається викликати методи на вбудованих об'єктах, що призводить до виключень, таких як "ReferenceError: console is not defined"
при використанні команд, таких як console.log()
або require(something)
.
Незважаючи на це обмеження, відновлення повного доступу до глобального контексту, включаючи всі стандартні вбудовані об'єкти, можливе через специфічний підхід. Використовуючи глобальний контекст безпосередньо, можна обійти це обмеження. Наприклад, доступ можна відновити, використовуючи наступний фрагмент:
Для додаткової інформації прочитайте це джерело.
Пакет serialize-javascript призначений виключно для цілей серіалізації, не маючи жодних вбудованих можливостей десеріалізації. Користувачі несуть відповідальність за реалізацію власного методу для десеріалізації. Пряме використання eval
пропонується офіційним прикладом для десеріалізації серіалізованих даних:
Якщо ця функція використовується для десеріалізації об'єктів, ви можете легко її експлуатувати:
Для додаткової інформації прочитайте це джерело.
Cryo бібліотека
На наступних сторінках ви можете знайти інформацію про те, як зловживати цією бібліотекою для виконання довільних команд:
Java - HTTP
У Java, зворотні виклики десеріалізації виконуються під час процесу десеріалізації. Це виконання може бути використано зловмисниками, які створюють шкідливі корисні навантаження, що викликають ці зворотні виклики, що призводить до потенційного виконання шкідливих дій.
Відбитки
Білий ящик
Щоб виявити потенційні вразливості серіалізації в кодовій базі, шукайте:
Класи, які реалізують інтерфейс
Serializable
.Використання функцій
java.io.ObjectInputStream
,readObject
,readUnshared
.
Зверніть особливу увагу на:
XMLDecoder
, що використовується з параметрами, визначеними зовнішніми користувачами.Метод
fromXML
бібліотекиXStream
, особливо якщо версія XStream менша або дорівнює 1.46, оскільки вона підлягає проблемам серіалізації.ObjectInputStream
у поєднанні з методомreadObject
.Реалізацію методів, таких як
readObject
,readObjectNodData
,readResolve
абоreadExternal
.ObjectInputStream.readUnshared
.Загальне використання
Serializable
.
Чорний ящик
Для тестування чорного ящика шукайте специфічні підписи або "Magic Bytes", які позначають java серіалізовані об'єкти (походять з ObjectInputStream
):
Шістнадцятковий шаблон:
AC ED 00 05
.Base64 шаблон:
rO0
.HTTP заголовки відповіді з
Content-type
, встановленим наapplication/x-java-serialized-object
.Шістнадцятковий шаблон, що вказує на попереднє стиснення:
1F 8B 08 00
.Base64 шаблон, що вказує на попереднє стиснення:
H4sIA
.Веб-файли з розширенням
.faces
та параметромfaces.ViewState
. Виявлення цих шаблонів у веб-додатку повинно спонукати до перевірки, як зазначено в пості про десеріалізацію Java JSF ViewState.
Перевірте, чи вразливий
Якщо ви хочете дізнатися, як працює експлойт Java Deserialized, вам слід ознайомитися з Основною десеріалізацією Java, Десеріалізацією DNS Java та Payload CommonsCollection1.
Тестування в білому ящику
Ви можете перевірити, чи встановлено будь-який додаток з відомими вразливостями.
Ви можете спробувати перевірити всі бібліотеки, які відомі як вразливі і для яких Ysoserial може надати експлойт. Або ви можете перевірити бібліотеки, вказані на Java-Deserialization-Cheat-Sheet. Ви також можете використовувати gadgetinspector для пошуку можливих ланцюгів гаджетів, які можна експлуатувати. При запуску gadgetinspector (після його збірки) не звертайте уваги на безліч попереджень/помилок, які він проходить, і дайте йому закінчити. Він запише всі знахідки під gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Будь ласка, зверніть увагу, що gadgetinspector не створить експлойт і може вказувати на хибнопозитивні результати.
Чорний ящик
Використовуючи розширення Burp gadgetprobe, ви можете ідентифікувати які бібліотеки доступні (і навіть версії). З цією інформацією може бути легше вибрати payload для експлуатації вразливості.
Прочитайте це, щоб дізнатися більше про GadgetProbe.
GadgetProbe зосереджений на ObjectInputStream
десеріалізаціях.
Використовуючи розширення Burp Java Deserialization Scanner, ви можете ідентифікувати вразливі бібліотеки, які можна експлуатувати за допомогою ysoserial, і експлуатувати їх.
Прочитайте це, щоб дізнатися більше про Java Deserialization Scanner.
Java Deserialization Scanner зосереджений на ObjectInputStream
десеріалізаціях.
Ви також можете використовувати Freddy для виявлення вразливостей десеріалізації в Burp. Цей плагін виявить не тільки вразливості, пов'язані з ObjectInputStream
, але також вразливості з бібліотек десеріалізації Json та Yml. В активному режимі він спробує підтвердити їх, використовуючи payload'и на основі затримки або DNS.
Ви можете знайти більше інформації про Freddy тут.
Тест на серіалізацію
Не все зводиться до перевірки, чи використовується якась вразлива бібліотека сервером. Іноді ви можете змінити дані всередині серіалізованого об'єкта і обійти деякі перевірки (можливо, надати вам адміністративні привілеї в веб-додатку). Якщо ви знайдете серіалізований об'єкт java, що надсилається до веб-додатку, ви можете використовувати SerializationDumper для виведення в більш зрозумілому форматі серіалізованого об'єкта, що надсилається. Знаючи, які дані ви надсилаєте, буде легше їх змінити і обійти деякі перевірки.
Експлойт
ysoserial
Основний інструмент для експлуатації Java десеріалізацій - це ysoserial (скачати тут). Ви також можете розглянути можливість використання ysoseral-modified, що дозволить вам використовувати складні команди (наприклад, з конвеєрами).
Зверніть увагу, що цей інструмент зосереджений на експлуатації ObjectInputStream
.
Я б почав використовувати payload "URLDNS" перед RCE payload, щоб перевірити, чи можлива ін'єкція. У будь-якому випадку, зверніть увагу, що, можливо, payload "URLDNS" не працює, але інший RCE payload працює.
Коли ви створюєте payload для java.lang.Runtime.exec(), ви не можете використовувати спеціальні символи такі як ">" або "|" для перенаправлення виходу виконання, "$()" для виконання команд або навіть передавати аргументи команді, розділені пробілами (ви можете зробити echo -n "hello world"
, але не можете зробити python2 -c 'print "Hello world"'
). Щоб правильно закодувати payload, ви можете використати цю веб-сторінку.
Не соромтеся використовувати наступний скрипт для створення всіх можливих payload для виконання коду для Windows і Linux, а потім протестуйте їх на вразливій веб-сторінці:
serialkillerbypassgadgets
Ви можете використовувати https://github.com/pwntester/SerialKillerBypassGadgetCollection разом з ysoserial для створення більше експлойтів. Більше інформації про цей інструмент у слайдах виступу, де був представлений інструмент: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec може бути використаний для генерації пейлоадів для експлуатації різних Json та Yml бібліотек серіалізації в Java.
Щоб скомпілювати проект, мені потрібно було додати ці залежності до pom.xml
:
Встановіть maven, і скомпілюйте проект:
FastJSON
Дізнайтеся більше про цю бібліотеку Java JSON: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Labs
Якщо ви хочете протестувати деякі ysoserial payloads, ви можете запустити цей веб-додаток: https://github.com/hvqzao/java-deserialize-webapp
Why
Java використовує багато серіалізації для різних цілей, таких як:
HTTP запити: Серіалізація широко використовується в управлінні параметрами, ViewState, куками тощо.
RMI (Віддалений виклик методів): Протокол Java RMI, який повністю покладається на серіалізацію, є основою для віддаленого зв'язку в Java-додатках.
RMI через HTTP: Цей метод зазвичай використовується Java-додатками з товстим клієнтом, використовуючи серіалізацію для всіх об'єктних комунікацій.
JMX (Розширення управління Java): JMX використовує серіалізацію для передачі об'єктів через мережу.
Користувацькі протоколи: У Java стандартною практикою є передача сирих Java-об'єктів, що буде продемонстровано в наступних прикладах експлуатації.
Prevention
Transient objects
Клас, який реалізує Serializable
, може реалізувати як transient
будь-який об'єкт всередині класу, який не повинен бути серіалізованим. Наприклад:
Уникайте серіалізації класу, який повинен реалізовувати Serializable
У сценаріях, де певні об'єкти повинні реалізовувати інтерфейс Serializable
через ієрархію класів, існує ризик ненавмисної десеріалізації. Щоб запобігти цьому, переконайтеся, що ці об'єкти не підлягають десеріалізації, визначивши final
метод readObject()
, який постійно викидає виключення, як показано нижче:
Покращення безпеки десеріалізації в Java
Налаштування java.io.ObjectInputStream
є практичним підходом для забезпечення безпеки процесів десеріалізації. Цей метод підходить, коли:
Код десеріалізації під вашим контролем.
Відомі класи, які очікуються для десеріалізації.
Перевизначте resolveClass()
метод, щоб обмежити десеріалізацію лише дозволеними класами. Це запобігає десеріалізації будь-якого класу, крім тих, що явно дозволені, як у наступному прикладі, який обмежує десеріалізацію лише класом Bicycle
:
Використання Java Agent для підвищення безпеки пропонує резервне рішення, коли модифікація коду неможлива. Цей метод застосовується в основному для чорного списку шкідливих класів, використовуючи параметр JVM:
Це забезпечує спосіб динамічно захистити десеріалізацію, ідеально підходить для середовищ, де негайні зміни коду є непрактичними.
Перегляньте приклад у rO0 by Contrast Security
Реалізація фільтрів серіалізації: Java 9 представила фільтри серіалізації через інтерфейс ObjectInputFilter
, що забезпечує потужний механізм для визначення критеріїв, яким повинні відповідати серіалізовані об'єкти перед десеріалізацією. Ці фільтри можуть бути застосовані глобально або для кожного потоку, пропонуючи детальний контроль над процесом десеріалізації.
Щоб використовувати фільтри серіалізації, ви можете встановити глобальний фільтр, який застосовується до всіх операцій десеріалізації, або налаштувати його динамічно для конкретних потоків. Наприклад:
Використання зовнішніх бібліотек для підвищення безпеки: Бібліотеки, такі як NotSoSerial, jdeserialize та Kryo, пропонують розширені можливості для контролю та моніторингу десеріалізації Java. Ці бібліотеки можуть забезпечити додаткові рівні безпеки, такі як білий або чорний списки класів, аналіз серіалізованих об'єктів перед десеріалізацією та реалізацію власних стратегій серіалізації.
NotSoSerial перехоплює процеси десеріалізації, щоб запобігти виконанню ненадійного коду.
jdeserialize дозволяє аналізувати серіалізовані Java-об'єкти без їх десеріалізації, що допомагає виявити потенційно шкідливий вміст.
Kryo є альтернативною рамкою серіалізації, яка підкреслює швидкість і ефективність, пропонуючи налаштовувані стратегії серіалізації, які можуть підвищити безпеку.
Посилання
Десеріалізація та доповідь ysoserial: http://frohoff.github.io/appseccali-marshalling-pickles/
Доповідь про gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 та слайди: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
Дослідження десеріалізації Java та .Net JSON документ: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, доповідь: https://www.youtube.com/watch?v=oUAeWhW5b8c та слайди: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
CVE десеріалізацій: https://paper.seebug.org/123/
JNDI Injection & log4Shell
Дізнайтеся, що таке JNDI Injection, як його зловживати через RMI, CORBA & LDAP та як експлуатувати log4shell (і приклад цієї уразливості) на наступній сторінці:
JNDI - Java Naming and Directory Interface & Log4ShellJMS - Java Message Service
API Java Message Service (JMS) є Java API для обміну повідомленнями, орієнтованим на послуги, для надсилання повідомлень між двома або більше клієнтами. Це реалізація для вирішення проблеми виробника-споживача. JMS є частиною Java Platform, Enterprise Edition (Java EE) і була визначена специфікацією, розробленою в Sun Microsystems, але з тих пір керується Java Community Process. Це стандарт обміну повідомленнями,