Deserialization
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Η σειριοποίηση κατανοείται ως η μέθοδος μετατροπής ενός αντικειμένου σε μια μορφή που μπορεί να διατηρηθεί, με σκοπό είτε την αποθήκευση του αντικειμένου είτε τη μετάδοσή του ως μέρος μιας διαδικασίας επικοινωνίας. Αυτή η τεχνική χρησιμοποιείται συνήθως για να διασφαλιστεί ότι το αντικείμενο μπορεί να αναδημιουργηθεί αργότερα, διατηρώντας τη δομή και την κατάσταση του.
Η αποσειριοποίηση, αντιθέτως, είναι η διαδικασία που αντενδρά στη σειριοποίηση. Περιλαμβάνει τη λήψη δεδομένων που έχουν δομηθεί σε μια συγκεκριμένη μορφή και την ανακατασκευή τους πίσω σε ένα αντικείμενο.
Η αποσειριοποίηση μπορεί να είναι επικίνδυνη επειδή επιτρέπει στους επιτιθέμενους να χειρίζονται τα σειριοποιημένα δεδομένα για να εκτελέσουν επιβλαβή κώδικα ή να προκαλέσουν απροσδόκητη συμπεριφορά στην εφαρμογή κατά τη διάρκεια της διαδικασίας ανακατασκευής του αντικειμένου.
Στην PHP, συγκεκριμένες μαγικές μέθοδοι χρησιμοποιούνται κατά τη διάρκεια των διαδικασιών σειριοποίησης και αποσειριοποίησης:
__sleep
: Καλείται όταν ένα αντικείμενο σειριοποιείται. Αυτή η μέθοδος θα πρέπει να επιστρέφει έναν πίνακα με τα ονόματα όλων των ιδιοτήτων του αντικειμένου που θα πρέπει να σειριοποιηθούν. Χρησιμοποιείται συνήθως για να δεσμεύσει εκκρεμή δεδομένα ή να εκτελέσει παρόμοιες εργασίες καθαρισμού.
__wakeup
: Καλείται όταν ένα αντικείμενο αποσειριοποιείται. Χρησιμοποιείται για να αποκαταστήσει οποιεσδήποτε συνδέσεις βάσης δεδομένων μπορεί να έχουν χαθεί κατά τη διάρκεια της σειριοποίησης και να εκτελέσει άλλες εργασίες επαναρχικοποίησης.
__unserialize
: Αυτή η μέθοδος καλείται αντί για __wakeup
(αν υπάρχει) όταν ένα αντικείμενο αποσειριοποιείται. Παρέχει περισσότερη έλεγχο στη διαδικασία αποσειριοποίησης σε σύγκριση με το __wakeup
.
__destruct
: Αυτή η μέθοδος καλείται όταν ένα αντικείμενο πρόκειται να καταστραφεί ή όταν το σενάριο τελειώνει. Χρησιμοποιείται συνήθως για εργασίες καθαρισμού, όπως το κλείσιμο χειριστών αρχείων ή συνδέσεων βάσης δεδομένων.
__toString
: Αυτή η μέθοδος επιτρέπει σε ένα αντικείμενο να αντιμετωπίζεται ως συμβολοσειρά. Μπορεί να χρησιμοποιηθεί για την ανάγνωση ενός αρχείου ή άλλων εργασιών με βάση τις κλήσεις συναρτήσεων εντός του, παρέχοντας αποτελεσματικά μια κειμενική αναπαράσταση του αντικειμένου.
Αν κοιτάξετε τα αποτελέσματα, μπορείτε να δείτε ότι οι συναρτήσεις __wakeup
και __destruct
καλούνται όταν το αντικείμενο αποδομηθεί. Σημειώστε ότι σε πολλές οδηγίες θα βρείτε ότι η συνάρτηση __toString
καλείται όταν προσπαθείτε να εκτυπώσετε κάποια ιδιότητα, αλλά προφανώς αυτό δεν συμβαίνει πια.
Η μέθοδος __unserialize(array $data)
καλείται αντί για __wakeup()
αν έχει υλοποιηθεί στην κλάση. Σας επιτρέπει να αποδομήσετε το αντικείμενο παρέχοντας τα σειριασμένα δεδομένα ως πίνακα. Μπορείτε να χρησιμοποιήσετε αυτή τη μέθοδο για να αποδομήσετε ιδιότητες και να εκτελέσετε οποιεσδήποτε απαραίτητες εργασίες κατά την αποδόμηση.
Μπορείτε να διαβάσετε ένα εξηγημένο παράδειγμα PHP εδώ: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, εδώ https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf ή εδώ https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
Μπορείτε να εκμεταλλευτείτε τη λειτουργία autoload του PHP για να φορτώσετε αυθαίρετα αρχεία php και περισσότερα:
PHP - Deserialization + Autoload ClassesΑν για κάποιο λόγο θέλετε να σειριοποιήσετε μια τιμή ως αναφορά σε άλλη τιμή που έχει σειριοποιηθεί μπορείτε:
PHPGGC μπορεί να σας βοηθήσει να δημιουργήσετε payloads για να εκμεταλλευτείτε τις PHP deserializations.
Σημειώστε ότι σε πολλές περιπτώσεις δεν θα μπορείτε να βρείτε τρόπο να εκμεταλλευτείτε μια deserialization στον πηγαίο κώδικα της εφαρμογής, αλλά μπορεί να μπορείτε να εκμεταλλευτείτε τον κώδικα εξωτερικών PHP επεκτάσεων.
Έτσι, αν μπορείτε, ελέγξτε το phpinfo()
του διακομιστή και αναζητήστε στο διαδίκτυο (ακόμα και στα gadgets του PHPGGC) κάποια πιθανά gadgets που θα μπορούσατε να εκμεταλλευτείτε.
Αν έχετε βρει ένα LFI που απλώς διαβάζει το αρχείο και δεν εκτελεί τον php κώδικα μέσα σε αυτό, για παράδειγμα χρησιμοποιώντας συναρτήσεις όπως file_get_contents(), fopen(), file() ή file_exists(), md5_file(), filemtime() ή filesize(). Μπορείτε να προσπαθήσετε να εκμεταλλευτείτε μια deserialization που συμβαίνει όταν διαβάζετε ένα αρχείο χρησιμοποιώντας το phar πρωτόκολλο. Για περισσότερες πληροφορίες διαβάστε την παρακάτω ανάρτηση:
phar:// deserializationΌταν το αντικείμενο αποσυμπιέζεται, η συνάρτηση __reduce__ θα εκτελεστεί. Όταν εκμεταλλευτεί, ο διακομιστής μπορεί να επιστρέψει ένα σφάλμα.
Πριν ελέγξετε την τεχνική παράκαμψης, δοκιμάστε να χρησιμοποιήσετε print(base64.b64encode(pickle.dumps(P(),2)))
για να δημιουργήσετε ένα αντικείμενο που είναι συμβατό με python2 αν τρέχετε python3.
Για περισσότερες πληροφορίες σχετικά με την αποφυγή από pickle jails ελέγξτε:
Bypass Python sandboxesΗ παρακάτω σελίδα παρουσιάζει την τεχνική για κατάχρηση μιας μη ασφαλούς αποσυμπίεσης σε yamls βιβλιοθήκες python και τελειώνει με ένα εργαλείο που μπορεί να χρησιμοποιηθεί για να δημιουργήσει RCE deserialization payload για Pickle, PyYAML, jsonpickle και ruamel.yaml:
Python Yaml DeserializationJS δεν έχει "μαγικές" συναρτήσεις όπως PHP ή Python που θα εκτελούνται απλώς για τη δημιουργία ενός αντικειμένου. Αλλά έχει κάποιες συναρτήσεις που είναι συχνά χρησιμοποιούμενες ακόμη και χωρίς να τις καλείτε άμεσα όπως toString
, valueOf
, toJSON
.
Αν καταχραστείτε μια αποσυμπίεση μπορείτε να συμβιβάσετε αυτές τις συναρτήσεις για να εκτελέσετε άλλο κώδικα (πιθανώς καταχρώντας τις μολύνσεις πρωτοτύπου) μπορείτε να εκτελέσετε αυθαίρετο κώδικα όταν καλούνται.
Ένας άλλος "μαγικός" τρόπος για να καλέσετε μια συνάρτηση χωρίς να την καλέσετε άμεσα είναι με το να συμβιβάσετε ένα αντικείμενο που επιστρέφεται από μια async συνάρτηση (υπόσχεση). Διότι, αν μετατρέψετε αυτό το επιστρεφόμενο αντικείμενο σε άλλη υπόσχεση με μια ιδιότητα που ονομάζεται "then" τύπου συνάρτησης, θα εκτελείται απλώς επειδή επιστρέφεται από άλλη υπόσχεση. Ακολουθήστε αυτόν τον σύνδεσμο για περισσότερες πληροφορίες.
__proto__
και prototype
ρύπανσηΑν θέλετε να μάθετε για αυτή την τεχνική ρίξτε μια ματιά στο παρακάτω σεμινάριο:
NodeJS - __proto__ & prototype PollutionΑυτή η βιβλιοθήκη επιτρέπει την σειριοποίηση συναρτήσεων. Παράδειγμα:
Το σειριοποιημένο αντικείμενο θα φαίνεται όπως:
Μπορείτε να δείτε στο παράδειγμα ότι όταν μια συνάρτηση είναι σειριοποιημένη, η σημαία _$$ND_FUNC$$_
προστίθεται στο σειριοποιημένο αντικείμενο.
Μέσα στο αρχείο node-serialize/lib/serialize.js
μπορείτε να βρείτε την ίδια σημαία και πώς ο κώδικας τη χρησιμοποιεί.
Όπως μπορείτε να δείτε στο τελευταίο κομμάτι κώδικα, αν βρεθεί η σημαία χρησιμοποιείται το eval
για να αποσειριοποιήσει τη συνάρτηση, οπότε βασικά η είσοδος του χρήστη χρησιμοποιείται μέσα στη συνάρτηση eval
.
Ωστόσο, απλά σειριοποιώντας μια συνάρτηση δεν θα την εκτελέσει καθώς θα ήταν απαραίτητο κάποιο μέρος του κώδικα να καλεί το y.rce
στο παράδειγμά μας και αυτό είναι πολύ απίθανο.
Ούτως ή άλλως, θα μπορούσατε απλά να τροποποιήσετε το σειριοποιημένο αντικείμενο προσθέτοντας μερικές παρενθέσεις ώστε να εκτελείται αυτόματα η σειριοποιημένη συνάρτηση όταν το αντικείμενο αποσειριοποιείται.
Στο επόμενο κομμάτι κώδικα προσέξτε την τελευταία παρένθεση και πώς η συνάρτηση unserialize
θα εκτελέσει αυτόματα τον κώδικα:
Όπως αναφέρθηκε προηγουμένως, αυτή η βιβλιοθήκη θα πάρει τον κώδικα μετά το _$$ND_FUNC$$_
και θα εκτελέσει αυτόν χρησιμοποιώντας το eval
. Επομένως, για να αυτοεκτελέσετε κώδικα μπορείτε να διαγράψετε το μέρος δημιουργίας της συνάρτησης και την τελευταία παρένθεση και να εκτελέσετε απλά μια JS oneliner όπως στο παρακάτω παράδειγμα:
Μπορείτε να βρείτε εδώ περισσότερες πληροφορίες σχετικά με το πώς να εκμεταλλευτείτε αυτήν την ευπάθεια.
Ένα αξιοσημείωτο χαρακτηριστικό του funcster είναι η μη προσβασιμότητα των τυπικών ενσωματωμένων αντικειμένων; βρίσκονται εκτός του προσβάσιμου πεδίου. Αυτή η περιοριστική πολιτική αποτρέπει την εκτέλεση κώδικα που προσπαθεί να καλέσει μεθόδους σε ενσωματωμένα αντικείμενα, οδηγώντας σε εξαιρέσεις όπως το "ReferenceError: console is not defined"
όταν χρησιμοποιούνται εντολές όπως console.log()
ή require(something)
.
Παρά αυτόν τον περιορισμό, η αποκατάσταση πλήρους πρόσβασης στο παγκόσμιο πλαίσιο, συμπεριλαμβανομένων όλων των τυπικών ενσωματωμένων αντικειμένων, είναι δυνατή μέσω μιας συγκεκριμένης προσέγγισης. Εκμεταλλευόμενοι άμεσα το παγκόσμιο πλαίσιο, μπορεί κανείς να παρακάμψει αυτόν τον περιορισμό. Για παράδειγμα, η πρόσβαση μπορεί να αποκατασταθεί χρησιμοποιώντας το παρακάτω απόσπασμα:
Για περισσότερες πληροφορίες διαβάστε αυτή την πηγή.
Το πακέτο serialize-javascript έχει σχεδιαστεί αποκλειστικά για σκοπούς σειριοποίησης, χωρίς καμία ενσωματωμένη δυνατότητα αποσειριοποίησης. Οι χρήστες είναι υπεύθυνοι για την υλοποίηση της δικής τους μεθόδου αποσειριοποίησης. Μια άμεση χρήση του eval
προτείνεται από το επίσημο παράδειγμα για την αποσειριοποίηση σειριοποιημένων δεδομένων:
Αν αυτή η συνάρτηση χρησιμοποιείται για να αποδομήσει αντικείμενα, μπορείτε εύκολα να την εκμεταλλευτείτε:
Για περισσότερες πληροφορίες διαβάστε αυτή την πηγή.
Στις επόμενες σελίδες μπορείτε να βρείτε πληροφορίες σχετικά με το πώς να εκμεταλλευτείτε αυτή τη βιβλιοθήκη για να εκτελέσετε αυθαίρετες εντολές:
Στην Java, οι κλήσεις ανασυγκρότησης εκτελούνται κατά τη διάρκεια της διαδικασίας ανασυγκρότησης. Αυτή η εκτέλεση μπορεί να εκμεταλλευτεί από επιτιθέμενους που κατασκευάζουν κακόβουλα payloads που ενεργοποιούν αυτές τις κλήσεις, οδηγώντας σε πιθανή εκτέλεση επιβλαβών ενεργειών.
Για να εντοπίσετε πιθανές ευπάθειες ανασυγκρότησης στον κώδικα, αναζητήστε:
Κλάσεις που υλοποιούν τη διεπαφή Serializable
.
Χρήση των συναρτήσεων java.io.ObjectInputStream
, readObject
, readUnshare
.
Δώστε ιδιαίτερη προσοχή σε:
XMLDecoder
που χρησιμοποιείται με παραμέτρους που ορίζονται από εξωτερικούς χρήστες.
Η μέθοδος fromXML
του XStream
, ειδικά αν η έκδοση του XStream είναι μικρότερη ή ίση με 1.46, καθώς είναι επιρρεπής σε προβλήματα ανασυγκρότησης.
ObjectInputStream
σε συνδυασμό με τη μέθοδο readObject
.
Υλοποίηση μεθόδων όπως readObject
, readObjectNodData
, readResolve
, ή readExternal
.
ObjectInputStream.readUnshared
.
Γενική χρήση του Serializable
.
Για δοκιμές μαύρου κουτιού, αναζητήστε συγκεκριμένες υπογραφές ή "Magic Bytes" που δηλώνουν java serialized objects (προερχόμενα από ObjectInputStream
):
Εξαδικό μοτίβο: AC ED 00 05
.
Μοτίβο Base64: rO0
.
HTTP response headers με Content-type
ρυθμισμένο σε application/x-java-serialized-object
.
Εξαδικό μοτίβο που υποδηλώνει προηγούμενη συμπίεση: 1F 8B 08 00
.
Μοτίβο Base64 που υποδηλώνει προηγούμενη συμπίεση: H4sIA
.
Ιστοσελίδες με την επέκταση .faces
και την παράμετρο faces.ViewState
. Η ανακάλυψη αυτών των μοτίβων σε μια διαδικτυακή εφαρμογή θα πρέπει να προκαλέσει μια εξέταση όπως αναφέρεται στην ανάρτηση σχετικά με την ανασυγκρότηση Java JSF ViewState.
Αν θέλετε να μάθετε πώς λειτουργεί μια εκμετάλλευση Java Deserialized θα πρέπει να ρίξετε μια ματιά σε Basic Java Deserialization, Java DNS Deserialization, και CommonsCollection1 Payload.
Μπορείτε να ελέγξετε αν είναι εγκατεστημένη κάποια εφαρμογή με γνωστές ευπάθειες.
Μπορείτε να προσπαθήσετε να ελέγξετε όλες τις βιβλιοθήκες που είναι γνωστό ότι είναι ευάλωτες και ότι Ysoserial μπορεί να παρέχει μια εκμετάλλευση. Ή μπορείτε να ελέγξετε τις βιβλιοθήκες που αναφέρονται στο Java-Deserialization-Cheat-Sheet. Μπορείτε επίσης να χρησιμοποιήσετε gadgetinspector για να αναζητήσετε πιθανές αλυσίδες gadget που μπορούν να εκμεταλλευτούν. Όταν εκτελείτε το gadgetinspector (μετά την κατασκευή του) μην ανησυχείτε για τους τόνους προειδοποιήσεων/σφαλμάτων που περνάει και αφήστε το να ολοκληρωθεί. Θα γράψει όλα τα ευρήματα κάτω από gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Παρακαλώ, σημειώστε ότι το gadgetinspector δεν θα δημιουργήσει μια εκμετάλλευση και μπορεί να υποδείξει ψευδώς θετικά αποτελέσματα.
Χρησιμοποιώντας την επέκταση Burp gadgetprobe μπορείτε να προσδιορίσετε ποια βιβλιοθήκες είναι διαθέσιμες (και ακόμη και τις εκδόσεις τους). Με αυτές τις πληροφορίες θα μπορούσε να είναι ευκολότερο να επιλέξετε ένα payload για να εκμεταλλευτείτε την ευπάθεια.
Διαβάστε αυτό για να μάθετε περισσότερα για το GadgetProbe.
Το GadgetProbe επικεντρώνεται σε ObjectInputStream
deserializations.
Χρησιμοποιώντας την επέκταση Burp Java Deserialization Scanner μπορείτε να εντοπίσετε ευάλωτες βιβλιοθήκες που μπορούν να εκμεταλλευτούν με το ysoserial και να τις εκμεταλλευτείτε.
Διαβάστε αυτό για να μάθετε περισσότερα για το Java Deserialization Scanner.
Ο Java Deserialization Scanner επικεντρώνεται σε ObjectInputStream
deserializations.
Μπορείτε επίσης να χρησιμοποιήσετε Freddy για να εντοπίσετε ευπάθειες deserialization στο Burp. Αυτό το plugin θα ανιχνεύσει όχι μόνο ευπάθειες σχετικές με το ObjectInputStream
αλλά και ευπάθειες από βιβλιοθήκες deserialization Json και Yml. Σε ενεργό λειτουργία, θα προσπαθήσει να τις επιβεβαιώσει χρησιμοποιώντας payloads sleep ή DNS.
Μπορείτε να βρείτε περισσότερες πληροφορίες για το Freddy εδώ.
Serialization Test
Δεν είναι όλα σχετικά με το να ελέγξετε αν χρησιμοποιείται κάποια ευάλωτη βιβλιοθήκη από τον διακομιστή. Μερικές φορές μπορείτε να αλλάξετε τα δεδομένα μέσα στο serialized object και να παρακάμψετε κάποιους ελέγχους (ίσως να σας δώσει δικαιώματα διαχειριστή μέσα σε μια webapp). Αν βρείτε ένα java serialized object που αποστέλλεται σε μια web εφαρμογή, μπορείτε να χρησιμοποιήσετε SerializationDumper για να εκτυπώσετε σε πιο ανθρώπινα αναγνώσιμη μορφή το serialization object που αποστέλλεται. Γνωρίζοντας ποια δεδομένα στέλνετε θα είναι πιο εύκολο να τα τροποποιήσετε και να παρακάμψετε κάποιους ελέγχους.
Το κύριο εργαλείο για την εκμετάλλευση των Java deserializations είναι ysoserial (κατεβάστε εδώ). Μπορείτε επίσης να εξετάσετε τη χρήση του ysoseral-modified που θα σας επιτρέψει να χρησιμοποιήσετε σύνθετες εντολές (με pipes για παράδειγμα).
Σημειώστε ότι αυτό το εργαλείο είναι εστιασμένο στην εκμετάλλευση του ObjectInputStream
.
Θα άρχιζα χρησιμοποιώντας το payload "URLDNS" πριν από ένα RCE payload για να δοκιμάσω αν η ένεση είναι δυνατή. Ούτως ή άλλως, σημειώστε ότι ίσως το payload "URLDNS" να μην λειτουργεί αλλά κάποιο άλλο RCE payload να λειτουργεί.
Όταν δημιουργείτε ένα payload για java.lang.Runtime.exec() δεν μπορείτε να χρησιμοποιήσετε ειδικούς χαρακτήρες όπως ">" ή "|" για να ανακατευθύνετε την έξοδο μιας εκτέλεσης, "$()" για να εκτελέσετε εντολές ή ακόμη και να περάσετε παραμέτρους σε μια εντολή χωρισμένες με κενά (μπορείτε να κάνετε echo -n "hello world"
αλλά δεν μπορείτε να κάνετε python2 -c 'print "Hello world"'
). Για να κωδικοποιήσετε σωστά το payload μπορείτε να χρησιμοποιήσετε αυτή τη σελίδα.
Μη διστάσετε να χρησιμοποιήσετε το επόμενο σενάριο για να δημιουργήσετε όλα τα πιθανά payloads εκτέλεσης κώδικα για Windows και Linux και στη συνέχεια να τα δοκιμάσετε στη ευάλωτη ιστοσελίδα:
Μπορείτε να χρησιμοποιήσετε https://github.com/pwntester/SerialKillerBypassGadgetCollection μαζί με το ysoserial για να δημιουργήσετε περισσότερους εκμεταλλεύσεις. Περισσότερες πληροφορίες σχετικά με αυτό το εργαλείο στις διαφάνειες της ομιλίας όπου παρουσιάστηκε το εργαλείο: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec μπορεί να χρησιμοποιηθεί για να δημιουργήσει payloads για να εκμεταλλευτεί διάφορες Json και Yml βιβλιοθήκες σειριοποίησης στην Java.
Για να κάνω compile το έργο, χρειάστηκε να προσθέσω αυτές τις εξαρτήσεις στο pom.xml
:
Εγκαταστήστε το maven, και συγκεντρώστε το έργο:
Διαβάστε περισσότερα για αυτή τη βιβλιοθήκη Java JSON: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Αν θέλετε να δοκιμάσετε μερικά ysoserial payloads μπορείτε να τρέξετε αυτή την εφαρμογή ιστού: https://github.com/hvqzao/java-deserialize-webapp
Η Java χρησιμοποιεί πολύ serialization για διάφορους σκοπούς όπως:
HTTP requests: Η serialization χρησιμοποιείται ευρέως στη διαχείριση παραμέτρων, ViewState, cookies, κ.λπ.
RMI (Remote Method Invocation): Το πρωτόκολλο Java RMI, το οποίο βασίζεται εξ ολοκλήρου στη serialization, είναι θεμέλιο για την απομακρυσμένη επικοινωνία σε εφαρμογές Java.
RMI over HTTP: Αυτή η μέθοδος χρησιμοποιείται συνήθως από εφαρμογές ιστού Java που βασίζονται σε thick client, χρησιμοποιώντας serialization για όλες τις επικοινωνίες αντικειμένων.
JMX (Java Management Extensions): Το JMX χρησιμοποιεί serialization για τη μετάδοση αντικειμένων μέσω του δικτύου.
Custom Protocols: Στην Java, η τυπική πρακτική περιλαμβάνει τη μετάδοση ακατέργαστων αντικειμένων Java, κάτι που θα αποδειχθεί σε επερχόμενα παραδείγματα εκμετάλλευσης.
Μια κλάση που υλοποιεί το Serializable
μπορεί να υλοποιήσει ως transient
οποιοδήποτε αντικείμενο μέσα στην κλάση που δεν θα πρέπει να είναι serializable. Για παράδειγμα:
Σε σενάρια όπου ορισμένα αντικείμενα πρέπει να υλοποιούν τη διεπαφή Serializable
λόγω ιεραρχίας κλάσεων, υπάρχει κίνδυνος ακούσιας αποσειριοποίησης. Για να το αποτρέψετε, βεβαιωθείτε ότι αυτά τα αντικείμενα είναι μη αποσειριοποιήσιμα ορίζοντας μια final
readObject()
μέθοδο που ρίχνει πάντα μια εξαίρεση, όπως φαίνεται παρακάτω:
Προσαρμόζοντας το java.io.ObjectInputStream
είναι μια πρακτική προσέγγιση για την ασφάλιση των διαδικασιών αποσυμπίεσης. Αυτή η μέθοδος είναι κατάλληλη όταν:
Ο κώδικας αποσυμπίεσης είναι υπό τον έλεγχό σας.
Οι κλάσεις που αναμένονται για αποσυμπίεση είναι γνωστές.
Επικαλύψτε τη μέθοδο resolveClass()
για να περιορίσετε την αποσυμπίεση μόνο σε επιτρεπόμενες κλάσεις. Αυτό αποτρέπει την αποσυμπίεση οποιασδήποτε κλάσης εκτός από αυτές που επιτρέπονται ρητά, όπως στο παρακάτω παράδειγμα που περιορίζει την αποσυμπίεση μόνο στην κλάση Bicycle
:
Χρησιμοποιώντας έναν Java Agent για την Ενίσχυση της Ασφάλειας προσφέρει μια εναλλακτική λύση όταν η τροποποίηση του κώδικα δεν είναι δυνατή. Αυτή η μέθοδος εφαρμόζεται κυρίως για μαύρη λίστα επιβλαβών κλάσεων, χρησιμοποιώντας μια παράμετρο JVM:
Παρέχει έναν τρόπο για να ασφαλίσετε τη διαδικασία αποσυμπίεσης δυναμικά, ιδανικό για περιβάλλοντα όπου οι άμεσες αλλαγές κώδικα είναι μη πρακτικές.
Δείτε ένα παράδειγμα στο rO0 by Contrast Security
Εφαρμογή Φίλτρων Σειριοποίησης: Η Java 9 εισήγαγε φίλτρα σειριοποίησης μέσω της διεπαφής ObjectInputFilter
, παρέχοντας έναν ισχυρό μηχανισμό για τον καθορισμό κριτηρίων που πρέπει να πληρούν τα σειριοποιημένα αντικείμενα πριν αποσυμπιεστούν. Αυτά τα φίλτρα μπορούν να εφαρμοστούν παγκοσμίως ή ανά ροή, προσφέροντας λεπτομερή έλεγχο στη διαδικασία αποσυμπίεσης.
Για να χρησιμοποιήσετε φίλτρα σειριοποίησης, μπορείτε να ορίσετε ένα παγκόσμιο φίλτρο που εφαρμόζεται σε όλες τις λειτουργίες αποσυμπίεσης ή να το ρυθμίσετε δυναμικά για συγκεκριμένες ροές. Για παράδειγμα:
Αξιοποίηση Εξωτερικών Βιβλιοθηκών για Βελτιωμένη Ασφάλεια: Βιβλιοθήκες όπως NotSoSerial, jdeserialize και Kryo προσφέρουν προηγμένα χαρακτηριστικά για τον έλεγχο και την παρακολούθηση της αποσυναρμολόγησης Java. Αυτές οι βιβλιοθήκες μπορούν να παρέχουν επιπλέον επίπεδα ασφάλειας, όπως η λευκή ή μαύρη λίστα κλάσεων, η ανάλυση σειριοποιημένων αντικειμένων πριν από την αποσυναρμολόγηση και η εφαρμογή προσαρμοσμένων στρατηγικών σειριοποίησης.
NotSoSerial παρεμβαίνει στις διαδικασίες αποσυναρμολόγησης για να αποτρέψει την εκτέλεση μη αξιόπιστου κώδικα.
jdeserialize επιτρέπει την ανάλυση σειριοποιημένων αντικειμένων Java χωρίς να τα αποσυναρμολογεί, βοηθώντας στην αναγνώριση δυνητικά κακόβουλου περιεχομένου.
Kryo είναι ένα εναλλακτικό πλαίσιο σειριοποίησης που δίνει έμφαση στην ταχύτητα και την αποδοτικότητα, προσφέροντας ρυθμιζόμενες στρατηγικές σειριοποίησης που μπορούν να ενισχύσουν την ασφάλεια.
Ομιλία για την αποσυναρμολόγηση και το ysoserial: http://frohoff.github.io/appseccali-marshalling-pickles/
Ομιλία για το gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 και διαφάνειες: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
Έγγραφο Marshalsec: https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true
Έγγραφο για την αποσυναρμολόγηση JSON Java και .Net : https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf,** ομιλία: https://www.youtube.com/watch?v=oUAeWhW5b8c και διαφάνειες: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
CVEs αποσυναρμολόγησης: https://paper.seebug.org/123/
Βρείτε τι είναι JNDI Injection, πώς να το εκμεταλλευτείτε μέσω RMI, CORBA & LDAP και πώς να εκμεταλλευτείτε το log4shell (και παράδειγμα αυτής της ευπάθειας) στην παρακάτω σελίδα:
JNDI - Java Naming and Directory Interface & Log4ShellΗ Java Message Service (JMS) API είναι μια Java API προσανατολισμένη σε μηνύματα για την αποστολή μηνυμάτων μεταξύ δύο ή περισσότερων πελατών. Είναι μια υλοποίηση για την αντιμετώπιση του προβλήματος παραγωγού-καταναλωτή. Η JMS είναι μέρος της Java Platform, Enterprise Edition (Java EE) και ορίστηκε από μια προδιαγραφή που αναπτύχθηκε από την Sun Microsystems, αλλά από τότε καθοδηγείται από τη διαδικασία της κοινότητας Java. Είναι ένα πρότυπο μηνυμάτων που επιτρέπει στα συστατικά εφαρμογών που βασίζονται σε Java EE να δημιουργούν, να στέλνουν, να λαμβάνουν και να διαβάζουν μηνύματα. Επιτρέπει την επικοινωνία μεταξύ διαφορετικών συστατικών μιας κατανεμημένης εφαρμογής να είναι χαλαρά συνδεδεμένη, αξιόπιστη και ασύγχρονη. (Από Wikipedia).
Υπάρχουν αρκετά προϊόντα που χρησιμοποιούν αυτό το middleware για την αποστολή μηνυμάτων:
Έτσι, βασικά υπάρχουν πολλές υπηρεσίες που χρησιμοποιούν JMS με επικίνδυνο τρόπο. Επομένως, αν έχετε αρκετά προνόμια για να στείλετε μηνύματα σε αυτές τις υπηρεσίες (συνήθως θα χρειαστείτε έγκυρα διαπιστευτήρια) θα μπορούσατε να στείλετε κακόβουλα αντικείμενα που θα σειριοποιηθούν και θα αποσυναρμολογηθούν από τον καταναλωτή/συνδρομητή. Αυτό σημαίνει ότι σε αυτή την εκμετάλλευση όλοι οι πελάτες που θα χρησιμοποιήσουν αυτό το μήνυμα θα μολυνθούν.
Πρέπει να θυμάστε ότι ακόμη και αν μια υπηρεσία είναι ευάλωτη (επειδή αποσυναρμολογεί ανασφαλώς την είσοδο του χρήστη) θα χρειαστεί να βρείτε έγκυρα gadgets για να εκμεταλλευτείτε την ευπάθεια.
Το εργαλείο JMET δημιουργήθηκε για να συνδεθεί και να επιτεθεί σε αυτές τις υπηρεσίες στέλνοντας αρκετά κακόβουλα αντικείμενα που σειριοποιούνται χρησιμοποιώντας γνωστά gadgets. Αυτές οι εκμεταλλεύσεις θα λειτουργήσουν αν η υπηρεσία είναι ακόμα ευάλωτη και αν κάποιο από τα χρησιμοποιούμενα gadgets είναι μέσα στην ευάλωτη εφαρμογή.
Ομιλία JMET: https://www.youtube.com/watch?v=0h8DWiOWGGA
Στο πλαίσιο του .Net, οι εκμεταλλεύσεις αποσυναρμολόγησης λειτουργούν με τρόπο παρόμοιο με εκείνες που βρίσκονται στην Java, όπου τα gadgets εκμεταλλεύονται για να εκτελέσουν συγκεκριμένο κώδικα κατά την αποσυναρμολόγηση ενός αντικειμένου.
Ο πηγαίος κώδικας θα πρέπει να ελεγχθεί για περιπτώσεις των:
TypeNameHandling
JavaScriptTypeResolver
Η προσοχή θα πρέπει να εστιάζεται σε σειριοποιητές που επιτρέπουν τον προσδιορισμό του τύπου από μια μεταβλητή υπό τον έλεγχο του χρήστη.
Η αναζήτηση θα πρέπει να στοχεύει στη Base64 κωδικοποιημένη συμβολοσειρά AAEAAAD///// ή οποιοδήποτε παρόμοιο μοτίβο που μπορεί να υποστεί αποσυναρμολόγηση στην πλευρά του διακομιστή, παρέχοντας έλεγχο στον τύπο που θα αποσυναρμολογηθεί. Αυτό θα μπορούσε να περιλαμβάνει, αλλά δεν περιορίζεται σε, JSON ή XML δομές που περιλαμβάνουν TypeObject
ή $type
.
Σε αυτή την περίπτωση μπορείτε να χρησιμοποιήσετε το εργαλείο ysoserial.net προκειμένου να δημιουργήσετε τις εκμεταλλεύσεις αποσυναρμολόγησης. Αφού κατεβάσετε το git repository θα πρέπει να συγκεντρώσετε το εργαλείο χρησιμοποιώντας το Visual Studio για παράδειγμα.
Αν θέλετε να μάθετε για πώς δημιουργεί το ysoserial.net την εκμετάλλευσή του μπορείτε να ελέγξετε αυτή τη σελίδα όπου εξηγείται το gadget ObjectDataProvider + ExpandedWrapper + Json.Net formatter.
Οι κύριες επιλογές του ysoserial.net είναι: --gadget
, --formatter
, --output
και --plugin
.
--gadget
χρησιμοποιείται για να υποδείξει το gadget που θα εκμεταλλευτεί (υποδείξτε την κλάση/συνάρτηση που θα εκμεταλλευτεί κατά την αποσυναρμολόγηση για να εκτελέσει εντολές).
--formatter
, χρησιμοποιείται για να υποδείξει τη μέθοδο για τη σειριοποίηση της εκμετάλλευσης (πρέπει να γνωρίζετε ποια βιβλιοθήκη χρησιμοποιεί το back-end για να αποσυναρμολογήσει το payload και να χρησιμοποιήσετε την ίδια για να το σειριοποιήσετε)
--output
χρησιμοποιείται για να υποδείξει αν θέλετε την εκμετάλλευση σε raw ή base64 κωδικοποιημένη. Σημειώστε ότι το ysoserial.net θα κωδικοποιήσει το payload χρησιμοποιώντας UTF-16LE (κωδικοποίηση που χρησιμοποιείται από προεπιλογή στα Windows) οπότε αν πάρετε το raw και το κωδικοποιήσετε απλά από μια κονσόλα linux μπορεί να έχετε κάποια προβλήματα συμβατότητας κωδικοποίησης που θα εμποδίσουν την εκμετάλλευση να λειτουργήσει σωστά (στην HTB JSON box το payload λειτούργησε και σε UTF-16LE και ASCII αλλά αυτό δεν σημαίνει ότι θα λειτουργεί πάντα).
--plugin
το ysoserial.net υποστηρίζει plugins για τη δημιουργία εκμεταλλεύσεων για συγκεκριμένα πλαίσια όπως το ViewState
--minify
θα παρέχει ένα μικρότερο payload (αν είναι δυνατόν)
--raf -f Json.Net -c "anything"
Αυτό θα υποδείξει όλα τα gadgets που μπορούν να χρησιμοποιηθούν με έναν παρεχόμενο formatter (Json.Net
σε αυτή την περίπτωση)
--sf xml
μπορείτε να υποδείξετε ένα gadget (-g
) και το ysoserial.net θα αναζητήσει formatters που περιέχουν "xml" (χωρίς διάκριση πεζών-κεφαλαίων)
Παραδείγματα ysoserial για τη δημιουργία εκμεταλλεύσεων:
ysoserial.net έχει επίσης μια πολύ ενδιαφέρουσα παράμετρο που βοηθά να κατανοήσετε καλύτερα πώς λειτουργεί κάθε εκμετάλλευση: --test
Αν υποδείξετε αυτή την παράμετρο, ysoserial.net θα δοκιμάσει την εκμετάλλευση τοπικά, ώστε να μπορείτε να ελέγξετε αν το payload σας θα λειτουργήσει σωστά.
Αυτή η παράμετρος είναι χρήσιμη γιατί αν αναθεωρήσετε τον κώδικα θα βρείτε κομμάτια κώδικα όπως το παρακάτω (από ObjectDataProviderGenerator.cs):
Αυτό σημαίνει ότι προκειμένου να δοκιμαστεί η εκμετάλλευση, ο κώδικας θα καλέσει serializersHelper.JsonNet_deserialize
In the προηγούμενος κώδικας είναι ευάλωτος στην εκμετάλλευση που δημιουργήθηκε. Έτσι, αν βρείτε κάτι παρόμοιο σε μια εφαρμογή .Net, σημαίνει ότι πιθανώς αυτή η εφαρμογή είναι επίσης ευάλωτη.
Επομένως, η --test
παράμετρος μας επιτρέπει να κατανοήσουμε ποια κομμάτια κώδικα είναι ευάλωτα στην εκμετάλλευση της αποσειριοποίησης που μπορεί να δημιουργήσει το ysoserial.net.
Ρίξτε μια ματιά σε αυτή την ανάρτηση σχετικά με το πώς να προσπαθήσετε να εκμεταλλευτείτε την παράμετρο __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, σε μη αξιόπιστες πηγές δεδομένων.
Java και .Net JSON αποσειριοποίηση έγγραφο: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, ομιλία: https://www.youtube.com/watch?v=oUAeWhW5b8c και διαφάνειες: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
Στη 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 γενική αποσειριοποίηση σε αλυσίδα gadget RCE (περισσότερες πληροφορίες στο https://www.elttam.com/blog/ruby-deserialization/):
Άλλες αλυσίδες RCE για εκμετάλλευση του Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Όπως εξηγείται σε αυτή την αναφορά ευπάθειας, αν κάποια μη φιλτραρισμένη είσοδος χρήστη φτάσει στη μέθοδο .send()
ενός αντικειμένου ruby, αυτή η μέθοδος επιτρέπει να καλέσετε οποιαδήποτε άλλη μέθοδο του αντικειμένου με οποιαδήποτε παραμέτρους.
Για παράδειγμα, η κλήση eval και στη συνέχεια κώδικα ruby ως δεύτερη παράμετρος θα επιτρέψει την εκτέλεση αυθαίρετου κώδικα:
Επιπλέον, αν μόνο μία παράμετρος του .send()
ελέγχεται από έναν επιτιθέμενο, όπως αναφέρθηκε στην προηγούμενη περιγραφή, είναι δυνατόν να κληθεί οποιαδήποτε μέθοδος του αντικειμένου που δεν χρειάζεται παραμέτρους ή των οποίων οι παράμετροι έχουν προεπιλεγμένες τιμές.
Για αυτό, είναι δυνατόν να απαριθμηθούν όλες οι μέθοδοι του αντικειμένου για να βρεθούν κάποιες ενδιαφέρουσες μέθοδοι που πληρούν αυτές τις απαιτήσεις.
Αυτή η τεχνική ελήφθη από αυτήν την ανάρτηση στο blog.
Υπάρχουν άλλες βιβλιοθήκες Ruby που μπορούν να χρησιμοποιηθούν για την σειριοποίηση αντικειμένων και επομένως θα μπορούσαν να καταχραστούν για να αποκτηθεί RCE κατά τη διάρκεια μιας ανασφαλούς αποσειριοποίησης. Ο παρακάτω πίνακας δείχνει μερικές από αυτές τις βιβλιοθήκες και τη μέθοδο που καλούν από τη φορτωμένη βιβλιοθήκη όποτε αποσειριοποιούνται (λειτουργία προς κατάχρηση για να αποκτηθεί RCE βασικά):
Βιβλιοθήκη
Δεδομένα εισόδου
Μέθοδος εκκίνησης μέσα στην κλάση
Marshal (Ruby)
Δυαδικά
_load
Oj
JSON
hash
(η κλάση πρέπει να τοποθετηθεί σε hash(map) ως κλειδί)
Ox
XML
hash
(η κλάση πρέπει να τοποθετηθεί σε hash(map) ως κλειδί)
Psych (Ruby)
YAML
hash
(η κλάση πρέπει να τοποθετηθεί σε hash(map) ως κλειδί)
init_with
JSON (Ruby)
JSON
json_create
([δείτε σημειώσεις σχετικά με το json_create στο τέλος](#table-vulnerable-sinks))
Βασικό παράδειγμα:
Στην περίπτωση που προσπαθήσαμε να εκμεταλλευτούμε το Oj, ήταν δυνατό να βρούμε μια κλάση gadget που μέσα στη συνάρτηση hash
της θα καλούσε το to_s
, το οποίο θα καλούσε το spec, το οποίο θα καλούσε το fetch_path, το οποίο ήταν δυνατό να το κάνουμε να ανακτήσει μια τυχαία διεύθυνση URL, παρέχοντας έναν εξαιρετικό ανιχνευτή αυτού του είδους των μη καθαρισμένων ευπαθειών αποσυμπίεσης.
Επιπλέον, διαπιστώθηκε ότι με την προηγούμενη τεχνική δημιουργείται επίσης ένας φάκελος στο σύστημα, ο οποίος είναι απαραίτητος για την κατάχρηση μιας άλλης συσκευής προκειμένου να μετατραπεί αυτό σε μια πλήρη RCE με κάτι σαν:
Ελέγξτε για περισσότερες λεπτομέρειες στην πρωτότυπη ανάρτηση.
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)