Off by one overflow
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)
Η πρόσβαση σε μια υπερχείλιση 1B επιτρέπει σε έναν επιτιθέμενο να τροποποιήσει το πεδίο size
από το επόμενο κομμάτι. Αυτό επιτρέπει την παραποίηση των κομματιών που είναι πραγματικά ελεύθερα, ενδεχομένως δημιουργώντας ένα κομμάτι που περιέχει ένα άλλο νόμιμο κομμάτι. Η εκμετάλλευση είναι παρόμοια με την double free ή τα επικαλυπτόμενα κομμάτια.
Υπάρχουν 2 τύποι ευπαθειών off by one:
Arbitrary byte: Αυτός ο τύπος επιτρέπει την επαναγραφή αυτού του byte με οποιαδήποτε τιμή
Null byte (off-by-null): Αυτός ο τύπος επιτρέπει την επαναγραφή αυτού του byte μόνο με 0x00
Ένα κοινό παράδειγμα αυτής της ευπάθειας μπορεί να παρατηρηθεί στον παρακάτω κώδικα όπου η συμπεριφορά των strlen
και strcpy
είναι ασυνεπής, γεγονός που επιτρέπει την τοποθέτηση ενός byte 0x00 στην αρχή του επόμενου κομματιού.
Αυτό μπορεί να εκμεταλλευτεί με το House of Einherjar.
Εάν χρησιμοποιείται Tcache, αυτό μπορεί να αξιοποιηθεί σε μια κατάσταση double free.
Μεταξύ άλλων ελέγχων, τώρα κάθε φορά που ένα κομμάτι είναι ελεύθερο, το προηγούμενο μέγεθος συγκρίνεται με το μέγεθος που έχει ρυθμιστεί στα μεταδεδομένα του κομματιού, καθιστώντας αυτή την επίθεση αρκετά περίπλοκη από την έκδοση 2.28.
Αυτή η επίθεση δεν λειτουργεί πλέον λόγω της χρήσης Tcaches.
Επιπλέον, αν προσπαθήσετε να την εκμεταλλευτείτε χρησιμοποιώντας μεγαλύτερα κομμάτια (έτσι ώστε να μην εμπλέκονται τα tcaches), θα λάβετε το σφάλμα: malloc(): invalid next size (unsorted)
Να περιέχεται ένα κομμάτι μέσα σε ένα άλλο κομμάτι, έτσι ώστε η πρόσβαση εγγραφής σε αυτό το δεύτερο κομμάτι να επιτρέπει την επαναγραφή του περιεχόμενου.
Off by one overflow για να τροποποιηθεί η πληροφορία μεγέθους στα μεταδεδομένα.
Δεσμεύστε τρία κομμάτια A
, B
και C
(ας πούμε μεγέθη 0x20), και ένα άλλο για να αποτραπεί η συγχώνευση με το top-chunk.
Ελευθερώστε το C
(εισαγμένο στη λίστα ελεύθερων κομματιών 0x20 Tcache).
Χρησιμοποιήστε το κομμάτι A
για να υπερχειλίσετε το B
. Εκμεταλλευτείτε το off-by-one για να τροποποιήσετε το πεδίο size
του B
από 0x21 σε 0x41.
Τώρα έχουμε το B
που περιέχει το ελεύθερο κομμάτι C
.
Ελευθερώστε το B
και δεσμεύστε ένα κομμάτι 0x40 (θα τοποθετηθεί ξανά εδώ).
Μπορούμε να τροποποιήσουμε τον δείκτη fd
από το C
, το οποίο είναι ακόμα ελεύθερο (Tcache poisoning).
3 κομμάτια μνήμης (a, b, c) δεσμεύονται το ένα μετά το άλλο. Στη συνέχεια, το μεσαίο ελευθερώνεται. Το πρώτο περιέχει μια ευπάθεια off by one overflow και ο επιτιθέμενος την εκμεταλλεύεται με ένα 0x00 (αν το προηγούμενο byte ήταν 0x10 θα έκανε το μεσαίο κομμάτι να υποδεικνύει ότι είναι 0x10 μικρότερο από ό,τι πραγματικά είναι).
Στη συνέχεια, 2 ακόμη μικρότερα κομμάτια δεσμεύονται στο μεσαίο ελεύθερο κομμάτι (b), ωστόσο, καθώς το b + b->size
δεν ενημερώνει ποτέ το κομμάτι c επειδή η διεύθυνση που δείχνει είναι μικρότερη από ό,τι θα έπρεπε.
Στη συνέχεια, τα b1 και c ελευθερώνονται. Καθώς το c - c->prev_size
δείχνει ακόμα στο b (b1 τώρα), και τα δύο συγχωνεύονται σε ένα κομμάτι. Ωστόσο, το b2 είναι ακόμα μέσα ανάμεσα στο b1 και c.
Τέλος, εκτελείται μια νέα malloc που ανακτά αυτή την περιοχή μνήμης που στην πραγματικότητα θα περιέχει το b2, επιτρέποντας στον κάτοχο της νέας malloc να ελέγξει το περιεχόμενο του b2.
Αυτή η εικόνα εξηγεί τέλεια την επίθεση:
Off-by-one λόγω του strlen
που εξετάζει το πεδίο size
του επόμενου κομματιού.
Χρησιμοποιείται Tcache, οπότε μια γενική επίθεση off-by-one λειτουργεί για να αποκτήσει μια αυθαίρετη εγγραφή με Tcache poisoning.
Είναι δυνατόν να εκμεταλλευτείτε ένα off by one για να διαρρεύσετε μια διεύθυνση από την heap επειδή το byte 0x00 στο τέλος μιας συμβολοσειράς επαναγράφεται από το επόμενο πεδίο.
Αυθαίρετη εγγραφή αποκτάται εκμεταλλευόμενοι την εγγραφή off by one για να κάνουμε τον δείκτη να δείχνει σε άλλη θέση όπου θα κατασκευαστεί μια ψεύτικη δομή με ψεύτικους δείκτες. Στη συνέχεια, είναι δυνατόν να ακολουθήσουμε τον δείκτη αυτής της δομής για να αποκτήσουμε αυθαίρετη εγγραφή.
Η διεύθυνση libc διαρρέει επειδή αν η heap επεκταθεί χρησιμοποιώντας mmap, η μνήμη που δεσμεύεται από το mmap έχει μια σταθερή απόσταση από τη libc.
Τέλος, η αυθαίρετη εγγραφή εκμεταλλεύεται για να γράψει στη διεύθυνση του __free_hook με μια διεύθυνση one gadget.
Υπάρχει μια ευπάθεια NULL off by one στη λειτουργία getline
που διαβάζει γραμμές εισόδου χρήστη. Αυτή η λειτουργία χρησιμοποιείται για να διαβάσει το "κλειδί" του περιεχομένου και όχι το περιεχόμενο.
Στη συγγραφή, δημιουργούνται 5 αρχικά κομμάτια:
chunk1 (0x200)
chunk2 (0x50)
chunk5 (0x68)
chunk3 (0x1f8)
chunk4 (0xf0)
chunk defense (0x400) για να αποφευχθεί η συγχώνευση με το top chunk
Στη συνέχεια, τα κομμάτια 1, 5 και 3 ελευθερώνονται, οπότε:
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]