mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/deserialization/basic-java-deserializati
This commit is contained in:
parent
7d8a9504c1
commit
7c267dfe3e
@ -1,15 +1,27 @@
|
||||
# Basic Java Deserialization with ObjectInputStream readObject
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
У цьому POST буде пояснено приклад використання `java.io.Serializable`.
|
||||
У цьому POST буде пояснено приклад використання `java.io.Serializable` **і чому перевизначення `readObject()` може бути надзвичайно небезпечним, якщо вхідний потік контролюється атакуючим**.
|
||||
|
||||
# Serializable
|
||||
## Serializable
|
||||
|
||||
Java `Serializable` інтерфейс (`java.io.Serializable` є маркерним інтерфейсом, який ваші класи повинні реалізувати, якщо вони повинні бути **серіалізовані** та **десеріалізовані**. Серіалізація об'єктів Java (запис) виконується за допомогою [ObjectOutputStream](http://tutorials.jenkov.com/java-io/objectoutputstream.html), а десеріалізація (читання) виконується за допомогою [ObjectInputStream](http://tutorials.jenkov.com/java-io/objectinputstream.html).
|
||||
Java `Serializable` інтерфейс (`java.io.Serializable`) є маркерним інтерфейсом, який ваші класи повинні реалізувати, якщо вони мають бути **серіалізовані** та **десеріалізовані**. Серіалізація об'єктів Java (запис) виконується за допомогою [`ObjectOutputStream`](http://tutorials.jenkov.com/java-io/objectoutputstream.html), а десеріалізація (читання) виконується за допомогою [`ObjectInputStream`](http://tutorials.jenkov.com/java-io/objectinputstream.html).
|
||||
|
||||
### Нагадування: Які методи імпліцитно викликаються під час десеріалізації?
|
||||
|
||||
1. `readObject()` – специфічна для класу логіка читання (якщо реалізована та *приватна*).
|
||||
2. `readResolve()` – може замінити десеріалізований об'єкт на інший.
|
||||
3. `validateObject()` – через зворотні виклики `ObjectInputValidation`.
|
||||
4. `readExternal()` – для класів, що реалізують `Externalizable`.
|
||||
5. Конструктори **не** виконуються – тому ланцюги гаджетів покладаються виключно на попередні зворотні виклики.
|
||||
|
||||
Будь-який метод у цьому ланцюзі, який в кінцевому підсумку викликає дані, контрольовані атакуючим (виконання команд, запити JNDI, рефлексія тощо), перетворює рутину десеріалізації на гаджет RCE.
|
||||
|
||||
Давайте розглянемо приклад з **класом Person**, який є **серіалізованим**. Цей клас **перезаписує функцію readObject**, тому коли **будь-який об'єкт** цього **класу** буде **десеріалізований**, ця **функція** буде **виконана**.\
|
||||
У прикладі **функція readObject** класу Person викликає функцію `eat()` його домашньої тварини, а функція `eat()` собаки (з якоїсь причини) викликає **calc.exe**. **Ми побачимо, як серіалізувати та десеріалізувати об'єкт Person, щоб виконати цей калькулятор:**
|
||||
У прикладі функція **readObject** класу Person викликає функцію `eat()` його домашньої тварини, а функція `eat()` собаки (з якоїсь причини) викликає **calc.exe**. **Ми побачимо, як серіалізувати та десеріалізувати об'єкт Person, щоб виконати цей калькулятор:**
|
||||
|
||||
**Наступний приклад з [https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649](https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649)**
|
||||
**Наступний приклад взято з <https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649>**
|
||||
```java
|
||||
import java.io.Serializable;
|
||||
import java.io.*;
|
||||
@ -80,8 +92,63 @@ payloadTest("test.ser");
|
||||
}
|
||||
}
|
||||
```
|
||||
## Висновок
|
||||
### Висновок (класичний сценарій)
|
||||
|
||||
Як ви можете побачити в цьому дуже простому прикладі, "вразливість" тут виникає тому, що функція **readObject** **викликає інші вразливі функції**.
|
||||
Як ви можете бачити в цьому дуже базовому прикладі, "вразливість" тут виникає через те, що метод **readObject()** **викликає інший код, контрольований атакуючим**. У реальних ланцюгах гаджетів тисячі класів, що містяться в зовнішніх бібліотеках (Commons-Collections, Spring, Groovy, Rome, SnakeYAML тощо), можуть бути зловживані – атакуючому потрібен лише *один* досяжний гаджет для отримання виконання коду.
|
||||
|
||||
---
|
||||
|
||||
## 2023-2025: Що нового в атаках десеріалізації Java?
|
||||
|
||||
* 2023 – CVE-2023-34040: десеріалізація заголовків записів помилок Spring-Kafka, коли увімкнені прапорці `checkDeserExWhen*`, дозволила довільне створення гаджетів з тем, опублікованих атакуючими. Виправлено в 3.0.10 / 2.9.11. ¹
|
||||
* 2023 – CVE-2023-36480: порушено припущення про довірений сервер Java-клієнта Aerospike – зловмисні відповіді сервера містили серіалізовані корисні навантаження, які були десеріалізовані клієнтом → RCE. ²
|
||||
* 2023 – CVE-2023-25581: парсинг атрибутів профілю користувача `pac4j-core` приймав Base64 блохи з префіксом `{#sb64}` і десеріалізував їх, незважаючи на `RestrictedObjectInputStream`. Оновлення ≥ 4.0.0.
|
||||
* 2023 – CVE-2023-4528: JSCAPE MFT Manager Service (порт 10880) приймав XML-кодовані Java-об'єкти, що призводило до RCE як root/SYSTEM.
|
||||
* 2024 – до ysoserial-plus(mod) додано кілька нових ланцюгів гаджетів, включаючи класи Hibernate5, TomcatEmbed і SnakeYAML 2.x, які обходять деякі старі фільтри.
|
||||
|
||||
## Сучасні заходи, які ви повинні впровадити
|
||||
|
||||
1. **JEP 290 / Фільтрація серіалізації (Java 9+)**
|
||||
*Додайте список дозволених або заборонених класів:*
|
||||
```bash
|
||||
# Приймати лише ваші DTO та java.base, відхиляти все інше
|
||||
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
|
||||
```
|
||||
Приклад програмного коду:
|
||||
```java
|
||||
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
|
||||
ObjectInputFilter.Config.setSerialFilter(filter);
|
||||
```
|
||||
2. **JEP 415 (Java 17+) Фабрики фільтрів, специфічні для контексту** – використовуйте `BinaryOperator<ObjectInputFilter>`, щоб застосовувати різні фільтри для кожного контексту виконання (наприклад, для кожного виклику RMI, для кожного споживача черги повідомлень).
|
||||
3. **Не піддавайте сирий `ObjectInputStream` через мережу** – надавайте перевагу JSON/бінарним кодуванням без семантики виконання коду (Jackson після відключення `DefaultTyping`, Protobuf, Avro тощо).
|
||||
4. **Обмеження захисту в глибині** – встановіть максимальну довжину масиву, глибину, посилання:
|
||||
```bash
|
||||
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
|
||||
```
|
||||
5. **Безперервне сканування гаджетів** – запускайте інструменти, такі як `gadget-inspector` або `serialpwn-cli` у вашій CI, щоб зупинити збірку, якщо небезпечний гаджет стає досяжним.
|
||||
|
||||
## Оновлений чек-лист інструментів (2024)
|
||||
|
||||
* `ysoserial-plus.jar` – спільний форк з > 130 ланцюгами гаджетів:
|
||||
```bash
|
||||
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
|
||||
```
|
||||
* `marshalsec` – все ще еталон для генерації гаджетів JNDI (LDAP/RMI).
|
||||
* `gadget-probe` – швидке виявлення гаджетів чорного ящика проти мережевих сервісів.
|
||||
* `SerialSniffer` – агент JVMTI, який друкує кожен клас, прочитаний `ObjectInputStream` (корисно для створення фільтрів).
|
||||
* **Порада з виявлення** – увімкніть `-Djdk.serialDebug=true` (JDK 22+), щоб записувати рішення фільтра та відхилені класи.
|
||||
|
||||
## Швидкий чек-лист для безпечних реалізацій `readObject()`
|
||||
|
||||
1. Зробіть метод `private` і додайте анотацію `@Serial` (допомагає статичному аналізу).
|
||||
2. Ніколи не викликайте методи, надані користувачем, або не виконуйте I/O у методі – лише читайте поля.
|
||||
3. Якщо потрібна валідація, виконуйте її **після** десеріалізації, поза `readObject()`.
|
||||
4. Віддавайте перевагу реалізації `Externalizable` і виконуйте явні читання полів замість стандартної серіалізації.
|
||||
5. Зареєструйте посилений `ObjectInputFilter` навіть для внутрішніх сервісів (дизайн, стійкий до компрометацій).
|
||||
|
||||
## Посилання
|
||||
|
||||
1. Консультація з безпеки Spring – CVE-2023-34040 Десеріалізація Java в Spring-Kafka (серпень 2023)
|
||||
2. GitHub Security Lab – GHSL-2023-044: Небезпечна десеріалізація в Java-клієнті Aerospike (липень 2023)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user