Off by one overflow

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

Basic Information

Η πρόσβαση σε μια υπερχείλιση 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.
Off-by-null
c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}

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

Παράδειγμα κώδικα:

Στόχος

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

Απαιτήσεις

  • Off by one overflow για να τροποποιηθεί η πληροφορία μεγέθους των μεταδεδομένων.

Γενική επίθεση off-by-one

  • Δεσμεύστε τρία κομμάτια 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).

Επίθεση off-by-null

  • 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.

Αυτή η εικόνα εξηγεί τέλεια την επίθεση:

https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks

Άλλα Παραδείγματα & Αναφορές

  • https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
  • Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
  • Off-by-one λόγω του strlen που θεωρεί το πεδίο size του επόμενου κομματιού.
  • Χρησιμοποιείται Tcache, οπότε μια γενική επίθεση off-by-one λειτουργεί για να αποκτήσει μια αυθαίρετη εγγραφή με Tcache poisoning.
  • Asis CTF 2016 b00ks
  • Είναι δυνατόν να εκμεταλλευτείτε ένα off by one για να διαρρεύσετε μια διεύθυνση από την heap επειδή το byte 0x00 στο τέλος μιας συμβολοσειράς που επαναγράφεται από το επόμενο πεδίο.
  • Αυθαίρετη εγγραφή αποκτάται εκμεταλλευόμενοι την εγγραφή off by one για να κάνουμε τον δείκτη να δείχνει σε άλλη θέση όπου θα κατασκευαστεί μια ψεύτικη δομή με ψεύτικους δείκτες. Στη συνέχεια, είναι δυνατόν να ακολουθήσουμε τον δείκτη αυτής της δομής για να αποκτήσουμε αυθαίρετη εγγραφή.
  • Η διεύθυνση libc διαρρέει επειδή αν η heap επεκταθεί χρησιμοποιώντας mmap, η μνήμη που δεσμεύεται από το mmap έχει μια σταθερή απόσταση από τη libc.
  • Τέλος, η αυθαίρετη εγγραφή εκμεταλλεύεται για να γράψει στη διεύθυνση του __free_hook με μια διεύθυνση one gadget.
  • plaidctf 2015 plaiddb
  • Υπάρχει μια ευπάθεια 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 ]

- Στη συνέχεια, εκμεταλλευόμενοι το chunk3 (0x1f8) η null off-by-one εκμεταλλεύεται γράφοντας το prev_size σε `0x4e0`.
- Σημειώστε πώς τα μεγέθη των αρχικά δεσμευμένων κομματιών 1, 2, 5 και 3 συν τα headers 4 αυτών των κομματιών ισούνται με `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Στη συνέχεια, το κομμάτι 4 ελευθερώνεται, δημιουργώντας ένα κομμάτι που καταναλώνει όλα τα κομμάτια μέχρι την αρχή:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]

[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]