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
7d710767c6
commit
85b82e417d
@ -1,15 +1,27 @@
|
|||||||
|
# Basic Java Deserialization with ObjectInputStream readObject
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
Σε αυτήν την ανάρτηση θα εξηγηθεί ένα παράδειγμα χρησιμοποιώντας `java.io.Serializable`.
|
Σε αυτή την ανάρτηση θα εξηγηθεί ένα παράδειγμα χρησιμοποιώντας `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`) είναι μια διεπαφή σήμανσης που οι κλάσεις σας πρέπει να υλοποιούν αν θέλουν να είναι **serializable** και **deserializable**. Η σειριοποίηση αντικειμένων Java (γραφή) γίνεται με το [`ObjectOutputStream`](http://tutorials.jenkov.com/java-io/objectoutputstream.html) και η αποσειριοποίηση (ανάγνωση) γίνεται με το [`ObjectInputStream`](http://tutorials.jenkov.com/java-io/objectinputstream.html).
|
||||||
|
|
||||||
Ας δούμε ένα παράδειγμα με μια **κλάση Person** η οποία είναι **σειριοποιήσιμη**. Αυτή η κλάση **υπερκαλύπτει τη συνάρτηση readObject**, έτσι όταν **οποιοδήποτε αντικείμενο** αυτής της **κλάσης** είναι **αποσειριοποιημένο**, αυτή η **συνάρτηση** θα **εκτελείται**.\
|
### Υπενθύμιση: Ποιες μέθοδοι καλούνται έμμεσα κατά την αποσειριοποίηση;
|
||||||
|
|
||||||
|
1. `readObject()` – λογική ανάγνωσης συγκεκριμένης κλάσης (αν έχει υλοποιηθεί και είναι *ιδιωτική*).
|
||||||
|
2. `readResolve()` – μπορεί να αντικαταστήσει το αποσειριοποιημένο αντικείμενο με ένα άλλο.
|
||||||
|
3. `validateObject()` – μέσω callbacks `ObjectInputValidation`.
|
||||||
|
4. `readExternal()` – για κλάσεις που υλοποιούν `Externalizable`.
|
||||||
|
5. Οι κατασκευαστές **δεν** εκτελούνται – επομένως οι αλυσίδες gadget βασίζονται αποκλειστικά στους προηγούμενους callbacks.
|
||||||
|
|
||||||
|
Οποιαδήποτε μέθοδος σε αυτή την αλυσίδα που καταλήγει να καλεί δεδομένα ελεγχόμενα από επιτιθέμενο (εκτέλεση εντολών, αναζητήσεις JNDI, ανακλαστικότητα, κ.λπ.) μετατρέπει τη ρουτίνα αποσειριοποίησης σε gadget RCE.
|
||||||
|
|
||||||
|
Ας δούμε ένα παράδειγμα με μια **κλάση Person** που είναι **serializable**. Αυτή η κλάση **υπερκαλύπτει τη συνάρτηση readObject**, έτσι όταν **οποιοδήποτε αντικείμενο** αυτής της **κλάσης** είναι **deserialized** αυτή η **συνάρτηση** θα **εκτελείται**.\
|
||||||
Στο παράδειγμα, η **συνάρτηση 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
|
```java
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -80,8 +92,63 @@ payloadTest("test.ser");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## Συμπέρασμα
|
### Συμπέρασμα (κλασικό σενάριο)
|
||||||
|
|
||||||
Όπως μπορείτε να δείτε σε αυτό το πολύ βασικό παράδειγμα, η "ευπάθεια" εδώ εμφανίζεται επειδή η **readObject** συνάρτηση **καλεί άλλες ευάλωτες συναρτήσεις**.
|
Όπως μπορείτε να δείτε σε αυτό το πολύ βασικό παράδειγμα, η “ευπάθεια” εδώ εμφανίζεται επειδή η μέθοδος **readObject()** **καλεί άλλον κώδικα που ελέγχεται από τον επιτιθέμενο**. Σε πραγματικές αλυσίδες gadget, χιλιάδες κλάσεις που περιέχονται σε εξωτερικές βιβλιοθήκες (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, κ.λπ.) μπορούν να καταχραστούν – ο επιτιθέμενος χρειάζεται μόνο *μία* προσβάσιμη gadget για να αποκτήσει εκτέλεση κώδικα.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2023-2025: Τι νέο υπάρχει στις επιθέσεις αποσυμπίεσης Java;
|
||||||
|
|
||||||
|
* 2023 – CVE-2023-34040: Η αποσυμπίεση κεφαλίδων σφαλμάτων του Spring-Kafka όταν είναι ενεργοποιημένες οι σημαίες `checkDeserExWhen*` επέτρεψε την αυθαίρετη κατασκευή gadget από θέματα που δημοσιεύθηκαν από τον επιτιθέμενο. Διορθώθηκε στην 3.0.10 / 2.9.11. ¹
|
||||||
|
* 2023 – CVE-2023-36480: Η υπόθεση αξιόπιστου διακομιστή του Aerospike Java client παραβιάστηκε – οι κακόβουλες απαντήσεις του διακομιστή περιείχαν σειριακά payloads που αποσυμπιέστηκαν από τον client → RCE. ²
|
||||||
|
* 2023 – CVE-2023-25581: Η ανάλυση του χαρακτηριστικού προφίλ χρήστη του `pac4j-core` αποδέχθηκε blobs Base64 με πρόθεμα `{#sb64}` και τα αποσυμπίεσε παρά την ύπαρξη ενός `RestrictedObjectInputStream`. Αναβάθμιση ≥ 4.0.0.
|
||||||
|
* 2023 – CVE-2023-4528: Η υπηρεσία JSCAPE MFT Manager (θύρα 10880) αποδέχθηκε Java αντικείμενα κωδικοποιημένα σε XML που οδήγησαν σε RCE ως root/SYSTEM.
|
||||||
|
* 2024 – Προστέθηκαν πολλές νέες αλυσίδες gadget στο 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. **Μην εκθέτετε το raw `ObjectInputStream` μέσω του δικτύου** – προτιμήστε κωδικοποιήσεις JSON/Binary χωρίς σημασιολογία εκτέλεσης κώδικα (Jackson μετά την απενεργοποίηση του `DefaultTyping`, Protobuf, Avro, κ.λπ.).
|
||||||
|
4. **Περιορισμοί Άμυνας σε Βάθος** – Ορίστε μέγιστο μήκος πίνακα, βάθος, αναφορές:
|
||||||
|
```bash
|
||||||
|
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
|
||||||
|
```
|
||||||
|
5. **Συνεχής σάρωση gadget** – εκτελέστε εργαλεία όπως `gadget-inspector` ή `serialpwn-cli` στο CI σας για να αποτύχει η κατασκευή αν γίνει προσβάσιμο ένα επικίνδυνο gadget.
|
||||||
|
|
||||||
|
## Ενημερωμένο cheat-sheet εργαλείων (2024)
|
||||||
|
|
||||||
|
* `ysoserial-plus.jar` – κοινότητα fork με > 130 αλυσίδες gadget:
|
||||||
|
```bash
|
||||||
|
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
|
||||||
|
```
|
||||||
|
* `marshalsec` – παραμένει η αναφορά για τη δημιουργία gadget JNDI (LDAP/RMI).
|
||||||
|
* `gadget-probe` – γρήγορη ανακάλυψη gadget black-box κατά των δικτυακών υπηρεσιών.
|
||||||
|
* `SerialSniffer` – JVMTI agent που εκτυπώνει κάθε κλάση που διαβάζεται από το `ObjectInputStream` (χρήσιμο για τη δημιουργία φίλτρων).
|
||||||
|
* **Συμβουλή ανίχνευσης** – ενεργοποιήστε το `-Djdk.serialDebug=true` (JDK 22+) για να καταγράψετε τις αποφάσεις φίλτρου και τις απορριφθείσες κλάσεις.
|
||||||
|
|
||||||
|
## Γρήγορη λίστα ελέγχου για ασφαλείς υλοποιήσεις `readObject()`
|
||||||
|
|
||||||
|
1. Κάντε τη μέθοδο `private` και προσθέστε την αναγνώριση `@Serial` (βοηθά στην στατική ανάλυση).
|
||||||
|
2. Ποτέ μην καλείτε μεθόδους που παρέχονται από τον χρήστη ή μην εκτελείτε I/O στη μέθοδο – μόνο διαβάστε πεδία.
|
||||||
|
3. Εάν απαιτείται επικύρωση, εκτελέστε την **μετά** την αποσυμπίεση, εκτός της `readObject()`.
|
||||||
|
4. Προτιμήστε να υλοποιήσετε το `Externalizable` και να κάνετε ρητές αναγνώσεις πεδίων αντί για προεπιλεγμένη σειριοποίηση.
|
||||||
|
5. Εγγραφείτε σε ένα σκληρυμένο `ObjectInputFilter` ακόμη και για εσωτερικές υπηρεσίες (σχεδίαση ανθεκτική σε παραβιάσεις).
|
||||||
|
|
||||||
|
## Αναφορές
|
||||||
|
|
||||||
|
1. Spring Security Advisory – CVE-2023-34040 Java Deserialization in Spring-Kafka (Αυγ 2023)
|
||||||
|
2. GitHub Security Lab – GHSL-2023-044: Unsafe Deserialization in Aerospike Java Client (Ιουλ 2023)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user