Stack Canaries
Reading time: 6 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.
StackGuard και StackShield
StackGuard εισάγει μια ειδική τιμή γνωστή ως canary πριν από το EIP (Extended Instruction Pointer), συγκεκριμένα 0x000aff0d
(που αντιπροσωπεύει null, newline, EOF, carriage return) για να προστατεύσει από buffer overflows. Ωστόσο, συναρτήσεις όπως recv()
, memcpy()
, read()
, και bcopy()
παραμένουν ευάλωτες, και δεν προστατεύει το EBP (Base Pointer).
StackShield ακολουθεί μια πιο εξελιγμένη προσέγγιση από το StackGuard διατηρώντας μια Global Return Stack, η οποία αποθηκεύει όλες τις διευθύνσεις επιστροφής (EIPs). Αυτή η ρύθμιση διασφαλίζει ότι οποιαδήποτε υπερχείλιση δεν προκαλεί ζημιά, καθώς επιτρέπει τη σύγκριση μεταξύ των αποθηκευμένων και των πραγματικών διευθύνσεων επιστροφής για την ανίχνευση περιστατικών υπερχείλισης. Επιπλέον, το StackShield μπορεί να ελέγξει τη διεύθυνση επιστροφής σε σχέση με μια τιμή ορίου για να ανιχνεύσει αν το EIP δείχνει εκτός του αναμενόμενου χώρου δεδομένων. Ωστόσο, αυτή η προστασία μπορεί να παρακαμφθεί μέσω τεχνικών όπως Return-to-libc, ROP (Return-Oriented Programming), ή ret2ret, υποδεικνύοντας ότι το StackShield δεν προστατεύει επίσης τις τοπικές μεταβλητές.
Stack Smash Protector (ProPolice) -fstack-protector
:
Αυτή η μηχανισμός τοποθετεί ένα canary πριν από το EBP, και αναδιοργανώνει τις τοπικές μεταβλητές για να τοποθετήσει τα buffers σε υψηλότερες διευθύνσεις μνήμης, αποτρέποντας την επικάλυψη άλλων μεταβλητών. Επίσης, αντιγράφει με ασφάλεια τα επιχειρήματα που περνούν στο stack πάνω από τις τοπικές μεταβλητές και χρησιμοποιεί αυτά τα αντίγραφα ως επιχειρήματα. Ωστόσο, δεν προστατεύει πίνακες με λιγότερα από 8 στοιχεία ή buffers εντός της δομής ενός χρήστη.
Το canary είναι ένας τυχαίος αριθμός που προέρχεται από το /dev/urandom
ή μια προεπιλεγμένη τιμή 0xff0a0000
. Αποθηκεύεται στο TLS (Thread Local Storage), επιτρέποντας στους κοινόχρηστους χώρους μνήμης μεταξύ νημάτων να έχουν παγκόσμιες ή στατικές μεταβλητές συγκεκριμένες για το νήμα. Αυτές οι μεταβλητές αντιγράφονται αρχικά από τη γονική διαδικασία, και οι παιδικές διαδικασίες μπορούν να τροποποιήσουν τα δεδομένα τους χωρίς να επηρεάσουν τη γονική ή τις αδελφές διαδικασίες. Παρ' όλα αυτά, αν χρησιμοποιηθεί fork()
χωρίς να δημιουργηθεί ένα νέο canary, όλες οι διαδικασίες (γονικές και παιδικές) μοιράζονται το ίδιο canary, καθιστώντας το ευάλωτο. Στην αρχιτεκτονική i386, το canary αποθηκεύεται στο gs:0x14
, και στην x86_64, στο fs:0x28
.
Αυτή η τοπική προστασία εντοπίζει συναρτήσεις με buffers ευάλωτα σε επιθέσεις και εισάγει κώδικα στην αρχή αυτών των συναρτήσεων για να τοποθετήσει το canary, και στο τέλος για να επαληθεύσει την ακεραιότητά του.
Όταν ένας web server χρησιμοποιεί fork()
, επιτρέπει μια επίθεση brute-force για να μαντέψει το canary byte by byte. Ωστόσο, η χρήση του execve()
μετά το fork()
επαναγράφει τον χώρο μνήμης, αναιρώντας την επίθεση. Το vfork()
επιτρέπει στην παιδική διαδικασία να εκτελείται χωρίς αναπαραγωγή μέχρι να προσπαθήσει να γράψει, οπότε δημιουργείται μια αναπαραγωγή, προσφέροντας μια διαφορετική προσέγγιση στη δημιουργία διαδικασιών και τη διαχείριση μνήμης.
Μήκη
Στα x64
binaries, το canary cookie είναι ένα 0x8
byte qword. Τα πρώτα επτά bytes είναι τυχαία και το τελευταίο byte είναι ένα null byte.
Στα x86
binaries, το canary cookie είναι ένα 0x4
byte dword. Τα πρώτα τρία bytes είναι τυχαία και το τελευταίο byte είναι ένα null byte.
caution
Το λιγότερο σημαντικό byte και των δύο canaries είναι ένα null byte επειδή θα είναι το πρώτο στο stack που προέρχεται από χαμηλότερες διευθύνσεις και επομένως οι συναρτήσεις που διαβάζουν συμβολοσειρές θα σταματήσουν πριν το διαβάσουν.
Παράκαμψη
Διαρροή του canary και στη συνέχεια επικάλυψη του (π.χ. buffer overflow) με την δική του τιμή.
- Αν το canary είναι forked σε παιδικές διαδικασίες μπορεί να είναι δυνατό να brute-force αυτό byte by byte:
BF Forked & Threaded Stack Canaries
- Αν υπάρχει κάποια ενδιαφέρουσα διαρροή ή ευπάθεια αυθαίρετης ανάγνωσης στο binary μπορεί να είναι δυνατό να διαρρεύσει:
- Επικάλυψη των αποθηκευμένων pointers στο stack
Το stack που είναι ευάλωτο σε υπερχείλιση stack μπορεί να περιέχει διευθύνσεις σε συμβολοσειρές ή συναρτήσεις που μπορούν να επαναγραφούν προκειμένου να εκμεταλλευτούν την ευπάθεια χωρίς να χρειαστεί να φτάσουν στο canary του stack. Ελέγξτε:
- Τροποποίηση και των δύο canary master και thread
Μια υπερχείλιση buffer σε μια συναρτήση με νήμα που προστατεύεται με canary μπορεί να χρησιμοποιηθεί για τροποποίηση του master canary του νήματος. Ως αποτέλεσμα, η μείωση είναι άχρηστη επειδή ο έλεγχος χρησιμοποιείται με δύο canaries που είναι τα ίδια (αν και τροποποιημένα).
Επιπλέον, μια υπερχείλιση buffer σε μια συναρτήση με νήμα που προστατεύεται με canary θα μπορούσε να χρησιμοποιηθεί για τροποποίηση του master canary που αποθηκεύεται στο TLS. Αυτό συμβαίνει επειδή, μπορεί να είναι δυνατό να φτάσει στη θέση μνήμης όπου αποθηκεύεται το TLS (και επομένως, το canary) μέσω ενός bof στο stack ενός νήματος.
Ως αποτέλεσμα, η μείωση είναι άχρηστη επειδή ο έλεγχος χρησιμοποιείται με δύο canaries που είναι τα ίδια (αν και τροποποιημένα).
Αυτή η επίθεση εκτελείται στην αναφορά: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads
Ελέγξτε επίσης την παρουσίαση του https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015 που αναφέρει ότι συνήθως το TLS αποθηκεύεται με mmap
και όταν δημιουργείται ένα stack ενός νήματος δημιουργείται επίσης με mmap
σύμφωνα με αυτό, το οποίο μπορεί να επιτρέπει την υπερχείλιση όπως φαίνεται στην προηγούμενη αναφορά.
- Τροποποίηση της εγγραφής GOT του
__stack_chk_fail
Αν το binary έχει Partial RELRO, τότε μπορείτε να χρησιμοποιήσετε μια αυθαίρετη εγγραφή για να τροποποιήσετε την εγγραφή GOT του __stack_chk_fail
ώστε να είναι μια ψεύτικη συνάρτηση που δεν μπλοκάρει το πρόγραμμα αν το canary τροποποιηθεί.
Αυτή η επίθεση εκτελείται στην αναφορά: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
Αναφορές
- https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html
- http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads
- https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
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.