ASLR
Βασικές Πληροφορίες
Η Τυχαία Διάταξη Χώρου Διεύθυνσης (ASLR) είναι μια τεχνική ασφαλείας που χρησιμοποιείται σε λειτουργικά συστήματα για να τυχαιοποιήσει τις διευθύνσεις μνήμης που χρησιμοποιούνται από τις διεργασίες του συστήματος και τις εφαρμογές. Με αυτόν τον τρόπο, κάνει σημαντικά πιο δύσκολο για έναν εισβολέα να προβλέψει τη θέση συγκεκριμένων διεργασιών και δεδομένων, όπως το stack, το heap και οι βιβλιοθήκες, με αποτέλεσμα τη μείωση ορισμένων τύπων εκμετάλλευσης, ιδιαίτερα των buffer overflows.
Έλεγχος Κατάστασης ASLR
Για να ελέγξετε την κατάσταση του ASLR σε ένα σύστημα Linux, μπορείτε να διαβάσετε την τιμή από το αρχείο /proc/sys/kernel/randomize_va_space
. Η τιμή που αποθηκεύεται σε αυτό το αρχείο καθορίζει τον τύπο του ASLR που εφαρμόζεται:
0: Χωρίς τυχαιοποίηση. Όλα είναι στατικά.
1: Συντηρητική τυχαιοποίηση. Οι κοινόχρηστες βιβλιοθήκες, το stack, το mmap(), η σελίδα VDSO τυχαιοποιούνται.
2: Πλήρης τυχαιοποίηση. Εκτός από τα στοιχεία που τυχαιοποιούνται από τη συντηρητική τυχαιοποίηση, η μνήμη που διαχειρίζεται μέσω του
brk()
τυχαιοποιείται.
Μπορείτε να ελέγξετε την κατάσταση του ASLR με την ακόλουθη εντολή:
Απενεργοποίηση του ASLR
Για να απενεργοποιήσετε το ASLR, ορίζετε την τιμή του /proc/sys/kernel/randomize_va_space
σε 0. Η απενεργοποίηση του ASLR συνήθως δεν συνιστάται εκτός από περιπτώσεις ελέγχου ή αποσφαλμάτωσης. Ακολουθεί πως μπορείτε να το απενεργοποιήσετε:
Μπορείτε επίσης να απενεργοποιήσετε το ASLR για μια εκτέλεση με:
Ενεργοποίηση του ASLR
Για να ενεργοποιήσετε το ASLR, μπορείτε να γράψετε μια τιμή 2 στο αρχείο /proc/sys/kernel/randomize_va_space
. Αυτό απαιτεί συνήθως δικαιώματα ρίζας. Η ενεργοποίηση πλήρους τυχαίοποίησης μπορεί να γίνει με την ακόλουθη εντολή:
Μόνιμη Διατήρηση Μετά την Επανεκκίνηση
Οι αλλαγές που γίνονται με τις εντολές echo
είναι προσωρινές και θα επαναφερθούν κατά την επανεκκίνηση. Για να κάνετε την αλλαγή μόνιμη, πρέπει να επεξεργαστείτε το αρχείο /etc/sysctl.conf
και να προσθέσετε ή να τροποποιήσετε την παρακάτω γραμμή:
Μετά την επεξεργασία του /etc/sysctl.conf
, εφαρμόστε τις αλλαγές με:
Αυτό θα εξασφαλίσει ότι οι ρυθμίσεις του ASLR παραμένουν μετά από επανεκκίνηση.
Παρακάμψεις
Βίαιη εξαναγκαστική επίθεση 32bit
Το PaX διαιρεί τον χώρο διεύθυνσης της διεργασίας σε 3 ομάδες:
Κώδικας και δεδομένα (αρχικοποιημένα και μη αρχικοποιημένα):
.text
,.data
, και.bss
—> 16 bits εντροπία στη μεταβλητήdelta_exec
. Αυτή η μεταβλητή αρχικοποιείται τυχαία με κάθε διεργασία και προστίθεται στις αρχικές διευθύνσεις.Μνήμη που εκχωρείται από την
mmap()
και κοινές βιβλιοθήκες —> 16 bits, με το όνομαdelta_mmap
.Η στοίβα —> 24 bits, αναφέρεται ως
delta_stack
. Ωστόσο, χρησιμοποιεί πραγματικά 11 bits (από τον 10ο έως τον 20ο byte συμπεριλαμβανομένου), ευθυγραμμισμένα σε 16 bytes —> Αυτό οδηγεί σε 524,288 πιθανές πραγματικές διευθύνσεις στοίβας.
Τα προηγούμενα δεδομένα αφορούν συστήματα 32-bit και η μειωμένη τελική εντροπία καθιστά δυνατή την παράκαμψη του ASLR επαναλαμβάνοντας την εκτέλεση μέχρι η εκμετάλλευση να ολοκληρωθεί με επιτυχία.
Ιδέες για βίαιη εξαναγκαστική επίθεση:
Αν έχετε ένα αρκετά μεγάλο υπερχείλισμα για να φιλοξενήσετε ένα μεγάλο NOP sled πριν το shellcode, μπορείτε απλά να εξαναγκάσετε διευθύνσεις στη στοίβα μέχρι η ροή να περάσει πάνω από κάποιο τμήμα του NOP sled.
Μια άλλη επιλογή γι' αυτό στην περίπτωση που το υπερχείλισμα δεν είναι τόσο μεγάλο και η εκμετάλλευση μπορεί να εκτελεστεί τοπικά είναι να προστεθεί το NOP sled και το shellcode σε μεταβλητή περιβάλλοντος.
Αν η εκμετάλλευση είναι τοπική, μπορείτε να δοκιμάσετε να εξαναγκάσετε τη βασική διεύθυνση της libc (χρήσιμο για συστήματα 32bit):
Εάν επιτεθείτε σε ένα απομακρυσμένο διακομιστή, μπορείτε να δοκιμάσετε να δοκιμάσετε με βία τη διεύθυνση της συνάρτησης
usleep
τηςlibc
, περνώντας ως όρισμα τον αριθμό 10 (για παράδειγμα). Εάν σε κάποιο σημείο ο διακομιστής καθυστερεί 10 δευτερόλεπτα περισσότερο για να ανταποκριθεί, τότε βρήκατε τη διεύθυνση αυτής της συνάρτησης.
Στα 64bit συστήματα η εντροπία είναι πολύ υψηλότερη και αυτό δεν θα έπρεπε να είναι δυνατό.
Επίθεση brute-forcing στο stack 64 bits
Είναι δυνατό να καταλάβετε ένα μεγάλο μέρος του stack με μεταβλητές περιβάλλοντος και στη συνέχεια να προσπαθήσετε να εκμεταλλευτείτε το δυαδικό αρχείο εκατοντάδες/χιλιάδες φορές τοπικά. Ο παρακάτω κώδικας δείχνει πώς είναι δυνατό να επιλέξετε απλώς μια διεύθυνση στο stack και κάθε λίγες εκατοντάδες εκτελέσεις αυτή η διεύθυνση θα περιέχει την NOP εντολή:
Τοπικές Πληροφορίες (/proc/[pid]/stat
)
/proc/[pid]/stat
)Το αρχείο /proc/[pid]/stat
ενός διεργασίας είναι πάντα προσβάσιμο από όλους και περιέχει ενδιαφέρουσες πληροφορίες όπως:
startcode & endcode: Διευθύνσεις πάνω και κάτω από το TEXT του δυαδικού
startstack: Η διεύθυνση της αρχής του stack
start_data & end_data: Διευθύνσεις πάνω και κάτω από όπου βρίσκεται το BSS
kstkesp & kstkeip: Τρέχουσες διευθύνσεις ESP και EIP
arg_start & arg_end: Διευθύνσεις πάνω και κάτω από όπου βρίσκονται οι παράμετροι της γραμμής εντολών
env_start & env_end: Διευθύνσεις πάνω και κάτω από όπου βρίσκονται οι μεταβλητές περιβάλλοντος
Επομένως, αν ο επιτιθέμενος βρίσκεται στον ίδιο υπολογιστή με το δυαδικό που εκμεταλλεύεται και αυτό το δυαδικό δεν περιμένει την υπερχείλιση από ωμές παραμέτρους, αλλά από μια διαφορετική είσοδο που μπορεί να δημιουργηθεί μετά την ανάγνωση αυτού του αρχείου. Είναι δυνατό για έναν επιτιθέμενο να αποκτήσει μερικές διευθύνσεις από αυτό το αρχείο και να κατασκευάσει μετατοπίσεις από αυτές για την εκμετάλλευση.
Για περισσότερες πληροφορίες σχετικά με αυτό το αρχείο ελέγξτε το https://man7.org/linux/man-pages/man5/proc.5.html αναζητώντας το /proc/pid/stat
Έχοντας μια διαρροή
Η πρόκληση είναι να δοθεί μια διαρροή
Αν σας δίνεται μια διαρροή (εύκολες προκλήσεις CTF), μπορείτε να υπολογίσετε μετατοπίσεις από αυτήν (υποθέτοντας για παράδειγμα ότι γνωρίζετε την ακριβή έκδοση της βιβλιοθήκης libc που χρησιμοποιείται στο σύστημα που εκμεταλλεύεστε). Αυτό το παράδειγμα εκμετάλλευσης εξάγεται από το παράδειγμα από εδώ (ελέγξτε αυτήν τη σελίδα για περισσότερες λεπτομέρειες):
ret2plt
Καταχρώντας ένα buffer overflow θα ήταν δυνατό να εκμεταλλευτείτε ένα ret2plt για να εξαγάγετε μια διεύθυνση μιας συνάρτησης από την libc. Ελέγξτε:
pageRet2pltFormat Strings Arbitrary Read
Όπως και στο ret2plt, αν έχετε ένα αυθαίρετο διάβασμα μέσω μιας ευπάθειας format strings είναι δυνατό να εξάγετε τη διεύθυνση μιας συνάρτησης της libc από το GOT. Το ακόλουθο παράδειγμα είναι από εδώ:
Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με την ανάγνωση τυχαίων δεδομένων με Format Strings στο:
pageFormat StringsRet2ret & Ret2pop
Προσπαθήστε να παρακάμψετε το ASLR καταχρώμενοι διευθύνσεις μέσα στη στοίβα:
pageRet2ret & Reo2popvsyscall
Ο μηχανισμός vsyscall
χρησιμεύει για τη βελτίωση της απόδοσης επιτρέποντας σε συγκεκριμένες κλήσεις συστήματος να εκτελούνται στον χώρο χρήστη, αν και ουσιαστικά ανήκουν στον πυρήνα. Το κρίσιμο πλεονέκτημα των vsyscalls βρίσκεται στις σταθερές διευθύνσεις τους, οι οποίες δεν υπόκεινται σε ASLR (Τυχαία Διάταξη Χώρου Διεύθυνσης). Αυτή η σταθερή φύση σημαίνει ότι οι επιτιθέμενοι δεν χρειάζεται να έχουν μια ευπάθεια διαρροής πληροφοριών για να καθορίσουν τις διευθύνσεις τους και να τις χρησιμοποιήσουν σε μια εκμετάλλευση.
Ωστόσο, δεν θα βρεθούν πολύ ενδιαφέροντα gadgets εδώ (αν και, για παράδειγμα, είναι δυνατόν να πάρετε ένα ret;
ισοδύναμο)
(Το παρακάτω παράδειγμα και κώδικας είναι από αυτό το άρθρο)
Για παράδειγμα, ένας επιτιθέμενος μπορεί να χρησιμοποιήσει τη διεύθυνση 0xffffffffff600800
μέσα σε μια εκμετάλλευση. Ενώ η προσπάθεια να πηδήξετε απευθείας σε μια εντολή ret
μπορεί να οδηγήσει σε αστάθεια ή κολλήματα μετά την εκτέλεση μερικών gadgets, το να πηδήξετε στην αρχή ενός syscall
που παρέχεται από την ενότητα vsyscall μπορεί να αποδειχθεί επιτυχημένο. Τοποθετώντας προσεκτικά ένα ROP gadget που οδηγεί την εκτέλεση σε αυτήν τη διεύθυνση vsyscall, ένας επιτιθέμενος μπορεί να επιτύχει την εκτέλεση κώδικα χωρίς την ανάγκη να παρακάμψει το ASLR για αυτό το τμήμα της εκμετάλλευσης.
vDSO
Σημειώστε λοιπόν πώς είναι δυνατόν να παρακάμψετε το ASLR καταχρώμενοι το vdso εάν το πυρήνας έχει μεταγλωττιστεί με το CONFIG_COMPAT_VDSO καθώς η διεύθυνση vdso δεν θα τυχαιοποιηθεί. Για περισσότερες πληροφορίες ελέγξτε:
pageRet2vDSOLast updated