Οι επιθέσεις DDoS (Distributed Denial of Service) λειτουργούν καταφέρνοντας να υπερφορτώσουν έναν στόχο με κίνηση από πολλούς υπολογιστές ή συσκευές, καθιστώντας τον μη διαθέσιμο για τους νόμιμους χρήστες. Ακολουθούν τα βασικά στάδια του πώς λειτουργεί μια επίθεση DDoS:
Επιλογή του Στόχου: Ο επιτιθέμενος επιλέγει μια ιστοσελίδα, έναν διακομιστή ή μια υπηρεσία ως στόχο για την επίθεση DDoS.
Δημιουργία Botnet Δικτύου (Botnet): Ο επιτιθέμενος συγκεντρώνει ένα μεγάλο αριθμό υπολογιστών ή συσκευών που είναι μολυσμένα από κακόβουλο λογισμικό (malware) και έχουν μετατραπεί σε bot. Αυτά τα μέλη του botnet μπορούν να ελεγχθούν από τον επιτιθέμενο.
Εκτέλεση της Επίθεσης: Ο επιτιθέμενος εκτελεί την επίθεση ενεργοποιώντας τους υπολογιστές στο botnet να στείλουν μεγάλο όγκο αιτημάτων στον στόχο (συνήθως στον διακομιστή του στόχου).
Υπερφόρτωση του Διακομιστή Στόχου: Ο διακομιστής στόχος αντιμετωπίζει τον υπερβολικό όγκο κίνησης από το botnet. Οι αιτήσεις από το botnet συχνά είναι ανώνυμες ή περιέχουν πλαστικά δεδομένα, καθιστώντας δύσκολο τον διαχωρισμό μεταξύ νόμιμων και κακόβουλων αιτημάτων.
Αποτυχία της Διαθεσιμότητας: Η διακίνηση των κακόβουλων αιτημάτων καταφέρνει να υπερφορτώσει τον διακομιστή στόχο, καθιστώντας τον μη διαθέσιμο για τους νόμιμους χρήστες. Αυτό είναι γνωστό ως “αποκοπή της υπηρεσίας” (Denial of Service) και συνήθως είναι το αποτέλεσμα της επίθεσης DDoS.
Οι επιθέσεις DDoS μπορούν να έχουν σοβαρές συνέπειες για τους στόχους τους, όπως διακοπή της λειτουργίας της ιστοσελίδας ή της υπηρεσίας, απώλεια επιχειρηματικής δραστηριότητας και οικονομικές απώλειες. Για αυτόν τον λόγο, οι ιδιοκτήτες ιστοσελίδων και οι διαχειριστές δικτύου πρέπει να λάβουν μέτρα προστασίας, όπως τη χρήση WAFs, CDNs, και λοιπών ασφαλιστικών πρακτικών για την αντιμετώπιση των επιθέσεων DDoS.
Η προστασία από επιθέσεις DDoS (Distributed Denial of Service) είναι σημαντική για τη διατήρηση της διαθεσιμότητας της ιστοσελίδας σας και την προστασία της από υπερφορτώσεις του δικτύου. Εδώ είναι μερικά βασικά μέτρα για την προστασία από DDoS:
Χρησιμοποιήστε Content Delivery Network (CDN): Η χρήση ενός CDN μπορεί να βοηθήσει στην κατανομή του φόρτου των επιθέσεων DDoS σε διάφορες τοποθεσίες, μειώνοντας τον αντίκτυπο στον κύριο διακομιστή σας.
Χρησιμοποιήστε Φιλτρά και Εισόδους Web Application Firewall (WAF): Ένα WAF μπορεί να ανιχνεύσει και να αποτρέψει επιθέσεις DDoS. Συνδυάζοντας το με φιλτρά ανάλυσης κίνησης, μπορείτε να αντιμετωπίσετε τις επιθέσεις πριν φτάσουν στον διακομιστή σας.
Παρακολούθηση της Κίνησης Δικτύου: Χρησιμοποιήστε λύσεις παρακολούθησης της κίνησης του δικτύου για να ανιχνεύετε ασυνήθιστη δραστηριότητα που ενδεχομένως να υποδηλώνει DDoS επιθέσεις.
Αντιμετώπιση της Εξελισσόμενης Κίνησης: Ορίστε μηχανισμούς αυτόματης επέκτασης της υποδομής σας για να αντιμετωπίζετε αυξημένη κίνηση κατά την επίδειξη επιθέσεων DDoS.
Απενεργοποίηση Pingbacks και Trackbacks: Στο WordPress, απενεργοποιήστε τις λειτουργίες Pingbacks και Trackbacks, καθώς μπορούν να χρησιμοποιηθούν για επιθέσεις επικάλυψης DDoS.
Χρησιμοποιήστε Υπηρεσίες Ασφαλείας DDoS: Υπάρχουν πολλές εταιρείες που προσφέρουν υπηρεσίες προστασίας DDoS. Αυτές οι υπηρεσίες μπορούν να αναλάβουν την προστασία της ιστοσελίδας σας και να διαχειριστούν την κίνηση DDoS για εσάς.
Σχεδιασμός για Κλιμάκωση: Σχεδιάστε την υποδομή σας και τον κωδικά της ιστοσελίδας σας με τη δυνατότητα κλιμάκωσης, έτσι ώστε να μπορεί να αντιμετωπίσει αυξημένη κίνηση κατά τις επιθέσεις DDoS χωρίς να αποτύχει.
Εφαρμογή Rate Limiting: Εφαρμόστε περιορισμούς στον αριθμό των αιτήσεων που μπορούν να γίνουν από μια διεύθυνση IP σε σύντομο χρονικό διάστημα.
Εφαρμόστε περιορισμούς: Εάν γνωρίζετε τη γεωγραφική περιοχή από την οποία προέρχονται συχνά οι επιθέσεις, μπορείτε να εφαρμόσετε περιορισμούς που θα αποκλείουν την κίνηση από αυτές τις χώρες.
CloudFlare και προστασία απο επιθέσεις DDos
Η Cloudflare παρέχει εξειδικευμένα εργαλεία και υπηρεσίες για την προστασία από DDoS επιθέσεις. Εδώ είναι μερικά από τα βήματα που μπορείτε να ακολουθήσετε για να ενισχύσετε την προστασία σας χρησιμοποιώντας την υπηρεσία Cloudflare:
Ενεργοποίηση του DDoS Protection: Βεβαιωθείτε ότι έχετε ενεργοποιήσει την προστασία DDoS από τον λογαριασμό Cloudflare σας. Αυτό περιλαμβάνει την προστασία από επιθέσεις (Layer 3/4) και επιθέσεις εφαρμογής (Layer 7).
Διαμορφώστε τους κανόνες ασφαλείας: Στον πίνακα ελέγχου της Cloudflare, μπορείτε να διαμορφώσετε κανόνες ασφαλείας για να ανιχνεύουν και να φιλτράρουν κίνηση που φαίνεται ύποπτη ή από επιθετικές διευθύνσεις IP.
Χρησιμοποιήστε τη λειτουργία “I’m Under Attack”: Η Cloudflare έχει μια επιλογή που λέγεται “I’m Under Attack,” η οποία ενεργοποιεί επιπρόσθετα μέτρα προστασίας κατά των DDoS επιθέσεων. Μπορείτε να τη χρησιμοποιήσετε όταν παρατηρείτε υπερβολική κίνηση.
Καταγραφή και ανάλυση: Ενεργοποιήστε την καταγραφή γεγονότων και ανάλυση κίνησης στο Cloudflare για να παρακολουθείτε την εισερχόμενη κίνηση και να ανιχνεύετε επιθέσεις.
Χρησιμοποιήστε την WAF της Cloudflare: Η Web Application Firewall (WAF) της Cloudflare μπορεί να ανιχνεύει και να προστατεύει την εφαρμογή σας από επιθέσεις εφαρμογής. Ρυθμίστε την WAF σύμφωνα με τις ανάγκες σας.
Χρησιμοποιήστε Rate Limiting: Η υπηρεσία Rate Limiting της Cloudflare μπορεί να περιορίσει τον αριθμό των αιτημάτων από μια διεύθυνση IP σε ένα συγκεκριμένο χρονικό διάστημα, βοηθώντας έτσι στην αντιμετώπιση επιθέσεων που βασίζονται στον όγκο.
Συνεχής ενημέρωση και παρακολούθηση: Παρακολουθείτε συνεχώς τις αναφορές ασφαλείας της Cloudflare και ενημερώνετε τις ρυθμίσεις ασφαλείας σας ανάλογα με τις νέες απειλές.
Ο Αλέξανδρος είναι ο ιδρυτής του hacks.gr και η κινητήρια δύναμη πίσω από το όραμά μας.
Με πολυετή εμπειρία στον κόσμο του hacking, έχει διαμορφώσει μια κοινότητα που είναι πηγή έμπνευσης και μάθησης για όλους.
Με τον προσωπικό του χαρακτήρα και την τεχνογνωσία του, έχει δημιουργήσει έναν χώρο όπου οι λάτρεις του hacking μπορούν να συναντιούνται, να μοιράζονται γνώσεις και να εξελίσσονται.
Επίθεση Χάκερ στη MongoDB:Παραβίαση δεδομένων πελατών
Η εταιρεία λογισμικού βάσης δεδομένων MongoDB αποκάλυψε ότι έχει πέσει θύμα κακόβουλης επίθεσης στα εταιρικά της συστήματα, προειδοποιώντας ότι στα κλεμμένα δεδομένα περιλαμβάνονται στοιχεία μεταδεδομένων λογαριασμού πελατών και πληροφορίες επικοινωνίας.
Σε μια σύντομη ανακοίνωση που δημοσιεύτηκε το περασμένο Σαββατοκύριακο, η εταιρεία με έδρα τη Νέα Υόρκη αναφέρει ότι ανιχνεύτηκε “ύποπτη δραστηριότητα” στο δίκτυό της στις 13 Δεκεμβρίου και αργότερα επιβεβαίωσε ότι οι χάκερ κατόρθωσαν να διεισδύσουν στα συστήματά της “πριν από την ανίχνευση για κάποιο χρονικό διάστημα.”
Η εταιρεία δεν παρείχε περαιτέρω λεπτομέρειες σχετικά με την παραβίαση.
Σε ανακοίνωση προς τους πελάτες, η MongoDB, Lena Smart, δήλωσε ότι η εταιρεία δεν έχει ενημερωθεί για εκθέσεις δεδομένων που οι πελάτες αποθηκεύουν στο κορυφαίο προϊόν της, το MongoDB Atlas.
“Παρ’ όλα αυτά, συνιστούμε στους πελάτες να παραμείνουν επιφυλακτικοί έναντι επιθέσεων κοινωνικής μηχανικής και ψαρέματος, να ενεργοποιήσουν την πολυπαραμετρική πιστοποίηση αντιμετώπισης του ψαρέματος και να αλλάζουν τα κωδικούς τους στο MongoDB Atlas τακτικά,” επεσήμανε η Smart.
Ο Αλέξανδρος είναι ο ιδρυτής του hacks.gr και η κινητήρια δύναμη πίσω από το όραμά μας.
Με πολυετή εμπειρία στον κόσμο του hacking, έχει διαμορφώσει μια κοινότητα που είναι πηγή έμπνευσης και μάθησης για όλους.
Με τον προσωπικό του χαρακτήρα και την τεχνογνωσία του, έχει δημιουργήσει έναν χώρο όπου οι λάτρεις του hacking μπορούν να συναντιούνται, να μοιράζονται γνώσεις και να εξελίσσονται.
Πως να πιάσετε συχνότητα WiFI ακτίνας 2-5 Χιλιομέτρων ( + Amplified Aircrack )
Γενικές Πληροφορίες
Σε αυτόν τον οδηγό θα σας δείξω πως μπορείτε να πιάσετε σήμα WiFi σε ακτίνα 2 – 5 χιλιομέτρων. Τώρα θα μου πει κάποιος είναι εφικτό αυτό; Φυσικά και ναι. Οπότε πάω στον οδηγό κατευθείαν.
Τι Θα χρειαστούμε;
Αρχικά θα χρειαστούμε κάποια πράγματα προς αγορά για να τελέσουμε τον οδηγό μας και φυσικά κοστίζουν καθώς είναι υλικά αγαθά οπότε έχουμε και λέμε.
1. Yagi Antenna Είναι τύπος κεραίας ώστε να πιάσουμε μεγάλες συχνότητες. ( RP-SMA connector / DBI )
Ο Αλέξανδρος είναι ο ιδρυτής του hacks.gr και η κινητήρια δύναμη πίσω από το όραμά μας.
Με πολυετή εμπειρία στον κόσμο του hacking, έχει διαμορφώσει μια κοινότητα που είναι πηγή έμπνευσης και μάθησης για όλους.
Με τον προσωπικό του χαρακτήρα και την τεχνογνωσία του, έχει δημιουργήσει έναν χώρο όπου οι λάτρεις του hacking μπορούν να συναντιούνται, να μοιράζονται γνώσεις και να εξελίσσονται.
A buffer overflow (bof), or buffer overrun, is an anomaly whereby a program, while writing data to a buffer, overruns the buffer’s boundary and overwrites adjacent memory locations (Wikipedia).
Θα αναλύσουμε σε αυτό το άρθρο αυτή την πολύ παλιά ευπάθεια λογισμικού και θα δούμε αν αυτή εξακολουθεί να μετράει…
Από το πρώτο άρθρο του Aleph One (Elias Levy) το 1996, “Smashing The Stack For Fun And Profit“, έχουν περάσει πάνω από 25 χρόνια. Η απάντηση στην ερώτηση “Είναι αυτή η ευπάθεια ακόμα ενεργή;” είναι ένα μεγάλο: ΝΑΙ!
Αλλά πράγματι, σήμερα, με τα σύγχρονα περιβάλλοντα & γλώσσες ανάπτυξης λογισμικού (.Net, J2EE, RoR, κλπ) δεν είναι τόσο εύκολο να πραγματοποιηθεί μια τέτοια επίθεση, αλλά… οι εφαρμογές που δημιουργήθηκαν σε περισσότερο low level γλώσσες προγραμματισμού που είναι ευάλωτες στην buffer overflow (όπως η C ή η C++) εξακολουθούν να υπάρχουν, και είναι πολλές: Web servers, Λειτουργικά Συστήματα, DBMSs και γενικά, σχεδόν σε όλα όσα βάζουμε να “τρέχουν” οι “ασφαλείς” εφαρμογές μας…
Σε αυτή τη σειρά άρθρων θα προσπαθήσω να εξηγήσω στους νεοεισερχόμενους πώς μπορεί να γίνει μια τέτοια επίθεση σε σύγχρονα περιβάλλοντα και Λειτουργικά Συστήματα.
Δεδομένου ότι η συγκεκριμένη επίθεση έχει να κάνει με την αρχιτεκτονική της μνήμης, την αρχιτεκτονική των λειτουργικών συστημάτων και τις συγκεκριμένες υλοποιήσεις μεταγλωττιστών, υπάρχουν αρκετές παραδοχές που πρέπει να κάνουμε.
Θα συζητήσουμε αυτές τις υποθέσεις για κάθε αρχιτεκτονική που επιλέγουμε.
Ας ξεκινήσουμε το ταξίδι μας με Linux…
0x1. Linux 64bit σε εφαρμογή 64bit
Ας δημιουργήσουμε τη δοκιμαστική μας εφαρμογή σε γλώσσα C για να ολοκληρώσουμε τη δοκιμή.
Ο πηγαίος κώδικας είναι ο εξής:
Αυτό το πολύ απλό πρόγραμμα επίδειξης, αυτό που κάνει είναι να λάβει ένα κλειδί προϊόντος ως είσοδο και αν το κλειδί προϊόντος είναι σωστό θα συνεχίσει στην κύρια ροή, διαφορετικά παράγει ένα σφάλμα και εξέρχεται.
Η είσοδος μπορεί να δοθεί από όρισμα της γραμμής εντολών ή (αν δεν δοθούν ορίσματα) θα ζητήσει από τον χρήστη να το εισάγει.
Για να μπορέσουμε να πραγματοποιήσουμε μια επιτυχημένη επίθεση, κάνουμε κάποιες παραδοχές χρησιμοποιώντας συγκεκριμένες σημαίες (flags) του μεταγλωττιστή.
Μεταγλωττίζω το πρόγραμμα ως εξής:
-m64: δημιουργία ενός εκτελέσιμου αρχείου σε αρχιτεκτονική 64bit (για να είμαι ειλικρινής, θα μπορούσα να το παραλείψω στο συγκεκριμένο σύστημα, αφού χρησιμοποιείται ως προεπιλογή).
-g: για την παραγωγή ειδικών μεταδεδομένων για τον αποσφαλματωτή (debugger – που θα χρησιμοποιήσουμε αργότερα)
-fno-stack-protector: κατά την εκτέλεση του προγράμματος δεν θα πραγματοποιείται έλεγχος στοίβας μνήμης (no stack protection).
-z execstack: επιτρέπει την εκτέλεση κώδικα σε τμήμα στοίβας (στη μνήμη).
-o demo: όνομα του τελικού εκτελέσιμου αρχείου θα είναι demo.
Το συγκεκριμένο παράδειγμα έχει υλοποιηθεί στο KALI Linux 2022.4:
Επιπλέον, είναι πολύ σημαντικό να απενεργοποιήσετε την προστασία ASLR (Address Space Layout Randomization).
Για να το κάνετε αυτό, στο kali απλά εισάγετε την εντολή ως root:
Και… btw, αν θέλετε να ελέγξετε, ποια είναι η τρέχουσα κατάσταση του ASLR, εισάγετε αυτό:
$ sudo cat /proc/sys/kernel/randomize_va_space
Στην παρακάτω εικόνα βλέπουμε μια κανονική εκτέλεση του μικρού μου προγράμματος επίδειξης.
Όπως μπορείτε να δείτε, υπάρχουν δύο (τουλάχιστον!!) κύρια τρωτά σημεία στο πρόγραμμα: Είναι όπου χρησιμοποιείται η ευάλωτη συνάρτηση strcpy και ας το δούμε αυτό στην πράξη:
O παραπάνω είναι ένας σχετικά εύκολος ο τρόπος για να ελέγξουμε αν το πρόγραμμά μας είναι ευάλωτο σε μια επίθεση buffer overflow: Δίνουμε ένα πολύ μεγάλο αλφαριθμητικό και στη συνέχεια ελέγχουμε την απόκριση του προγράμματος. Αν λάβουμε ένα ‘segmentation fault’ τότε είναι πιθανό να έχουμε μια ευπάθεια bof (buffer overflow)…
0x1.0x1. Η προσέγγιση ROP
Σύμφωνα με τη Wikipedia: Return-oriented programming (ROP) is a computer security exploit technique that allows an attacker to execute code in the presence of security defenses such as executable space protection and code signing.
Ο κύριος στόχος μας εδώ είναι να εκμεταλλευτούμε την ευπάθεια ενός προγράμματος προκειμένου να ανακατευθύνουμε τη ροή του προγράμματος εκεί που μας αρέσει (και εκεί που μπορούμε, βεβαίως βεβαίως)…
Ας εξετάσουμε τη συμπεριφορά του προγράμματος χρησιμοποιώντας τον αποσφαλματωτή gdb.
Βάζουμε ένα σημείο διακοπής (break point) στη γραμμή 7, αμέσως μετά την strcpy, μέσα στη συνάρτηση checkProductKey.
Εκτελούμε την εφαρμογή μέσα στον αποσφαλματωτή ( απλά πληκτρολογούμε dbg ./demo ) περνώντας ένα κανονικό αλφαριθμητικό, προκειμένου να ελέγξουμε πού βρίσκεται η διεύθυνση RET (περισσότερα γι’ αυτό παρακάτω). Έτσι θα έχουμε:
Ας συζητήσουμε μερικά πραγματάκια εδώ…
Η παραπάνω εικόνα χωρίζεται σε 2 κονσόλες:
Η αριστερή κονσόλα είναι ο disassembled κώδικας του προγράμματος που λαμβάνω μετά την τοποθέτηση του σημείου διακοπής στη γραμμή 7 (break 7) και την εισαγωγή disassemble /s main. Η παράμετρος “/s” δίνει εντολή στον αποσφαλματωτή να παράγει τον disassembled κώδικα μαζί με τον αντίστοιχο πηγαίο κώδικα C (thanks to the flag -g στη φάση της μεταγλώττισης).
Η δεξιά κονσόλα είναι η κονσόλα εκτέλεσης στην οποία δουλεύουμε δοκιμάζοντας το πρόγραμμα μας.
Σημειώστε επίσης το εξής σημαντικό: οι διευθύνσεις μνήμης (που ορίζονται με μπλε χρώμα) είναι ίδιες και στις δύο εικόνες. Αυτό είναι πολύ δύσκολο να συμβεί σε πραγματικές καταστάσεις, επειδή αυτές οι διευθύνσεις μπορεί να μην είναι πάντα οι ίδιες κάθε φορά που εκτελούμε το πρόγραμμα. Αυτό συμβαίνει εξαιτίας του ASLR, και γι’ αυτό το λόγο το απενεργοποιούμε, παραπάνω, αλλιώς μπορεί να καταλήξουμε να κυνηγάμε… φαντάσματα, πιστέψτε με! — burned-burned-burned!!
Όπως μπορείτε να δείτε στα ΠΡΑΣΙΝΑ ΚΟΥΤΙΑ τρέχουμε το πρόγραμμα στον αποσφαλματωτή περνώντας 10 “Α” ως όρισμα: run AAAAAAAAAA
Αυτό αποθηκεύεται στη στοίβα (stack – μην μου πείτε οτι δεν το ξέρετε – see part I) καθώς καλείται η συνάρτηση checkProductKey αφού περνάει ως όρισμα στη συνάρτηση.
Μπορούμε να δούμε τη στοίβα στη μνήμη εισάγοντας την εντολή x/24xg $rsp στον αποσφαλματωτή. Αυτή η εντολή δίνει εντολή στον αποσφαλματωτή να εμφανίσει σε δεκαεξαδική μορφή “x”, τις επόμενες 24 θέσεις μνήμης σε γιγαντιαία (“g”) μορφή 8-bytes.
Το $rsp είναι το γνωστό Stack Pointer (το παλιό ESP στα 32bit συστήματα – see again part I) όπου στην περίπτωσή μας δείχνει τις μεταβλητές που πέρασαν ως ορίσματα μέσα στη συνάρτησή μας.
Τα “AAAAAAAAAA” αναπαρίστανται εδώ σε δεκαεξαδική μορφή (“x”) από τον αριθμό “41” που είναι η ASCII δεκαεξαδική αναπαράσταση του γράμματος “A”.
Επίσης, σημειώστε ότι τα 10 “Α” αποθηκεύονται στη θέση μνήμης με αντίστροφη σειρά, καθώς πρόκειται για την αρχιτεκτονική little endian.
Έτσι, η πραγματική συμβολοσειρά που διατηρείται στη στοίβα (στη μνήμη) είναι η “41.41.41.41.41.41.41.41.41.41.00” (έβαλα το “.” για να είναι πιο ευανάγνωστο).
Σημειώστε ότι το “00” είναι ο μηδενικός χαρακτήρας που δηλώνει τον τερματισμό της συμβολοσειράς. Να θυμάστε αυτό το “00” επειδή παίζει σημαντικό ρόλο (ως εμπόδιο) στην ανάπτυξη exploits γενικότερα, και ειδικά στη δημιουργία shellcode (ή bytecode) (περισσότερα για αυτό στο part III). Το βασικό σημείο που πρέπει να γνωρίζετε εδώ είναι το εξής: Η ανάγνωση (ή μερικές φορές η εκτέλεση) μιας σειράς θέσεων μνήμης διακόπτεται όταν το σύστημα συναντήσει ένα byte 00.
Επικεντρωθείτε τώρα στα κόκκινα κουτάκια της εικόνας μας και θυμηθείτε πού βρισκόμαστε: Βρισκόμαστε μέσα στη συνάρτηση checkProductKey.
Όταν η συνάρτηση τελειώσει, η λειτουργικότητα του προγράμματος πρέπει να επιστρέψει στο σημείο που κλήθηκε. Για να είμαστε πιο συγκεκριμένοι: πρέπει να επιστρέψει στη διεύθυνση του καλούντα.
Προκειμένου το σύστημα να θυμάται αυτή τη διεύθυνση, την αποθηκεύει σε μια συγκεκριμένη θέση μνήμης μέσα στο buffer της τρέχουσας συνάρτησης. Ονομάζουμε αυτή τη διεύθυνση: διεύθυνση RET (RETurn). Είναι μια από τις πιο σημαντικές διευθύνσεις των επιθέσεων buffer overflow και θεωρείται το “ιερό δισκοπότηρο” κάθε εκμετάλλευσης μιας αδυναμίας buffer overflow.
Όπως μπορείτε να δείτε στο κόκκινο πλαίσιο στη δεξιά κονσόλα, η διεύθυνση RET αποθηκεύεται στο τέλος του buffer, μετά τη διεύθυνση του αλφαριθμητικού εισόδου μας “AAAAAAAAAA” και κάποιες άλλες διευθύνσεις (όπως ο Base Pointer, κάποιες μεταβλητές περιβάλλοντος κ.λπ. που είναι σημαντικές… αλλά όχι τόσο σημαντικές για την ώρα).
Όπως μπορείτε να φανταστείτε αν εισάγουμε ένα πολύ μεγάλο αλφαριθμητικό εισόδου, μεγαλύτερο από αυτό που έχει κρατήσει το πρόγραμμα μας (στην περίπτωσή μας είναι 12 – λόγω της char key[12]; στη γραμμή 5) τότε αυτό θα γράψουμε από πάνω από όλες τις διευθύνσεις που ακολουθούν αυτή τη μεταβλητή, συμπεριλαμβανομένης της διεύθυνσης RET. Αυτό είναι πολύ σημαντικό και πολύ δύσκολο!
και αυτός είναι ο λόγος:
Έστω οτι δώσουμε αυτό σαν input: “AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”.
To buffer μας μπορεί να χωρέσει μόνο τους πρώτους 12 χαρακτήρες (ή bytes στην αρχιτεκτονική i386), συμπεριλαμβανομένου του χαρακτήρα τερματισμού, δηλαδή του “00”. Τι γίνεται λοιπόν με τους υπόλοιπους χαρακτήρες; Μα, θα αντικαταστήσουν τις γειτονικές διευθύνσεις μνήμης… συμπεριλαμβανομένης της διεύθυνσης που βρίσκεται το RET .
Έτσι, η διεύθυνση RET θα γεμίσει με “A”, άρα “AAAAAAAA” ή “4141414141414141”.
Σημειώστε ότι επίτηδες επέλεξα 8 bytes για να δηλώσω τη διεύθυνση σε συστήματα 64bit.
Γενικά, θα πρέπει να γνωρίζετε ότι στα 64bit συστήματα (σε αντίθεση με τα 32bit συστήματα που είδαμε σαν θεωρία στο Part I) έχουμε τις εξής διαφορές:
Οι καταχωρητές γενικού σκοπού έχουν επεκταθεί σε 64-bit. Έτσι έχουμε τώρα τους RAX, RBX, RCX, RDX, RSI και RDI.
Ο Instruction Pointer, ο Base Pointer και ο Stack Pointer έχουν επίσης επεκταθεί σε 64-bit ως RIP, RBP και RSP αντίστοιχα.
Έχουν παρασχεθεί οι πρόσθετοι καταχωρητές: R8 έως R15.
Οι pointers έχουν μήκος 8-bytes.
Τα push/pop στο STACK έχουν μήκος 8-bytes.
To μέγιστο μέγεθος μιας επιτρεπτής διεύθυνσης είναι: 0x00007FFFFFFFFFFFFFFF (περισσότερα σχετικά με αυτό θα πούμε λίγο αργότερα).
Δείτε τώρα τη διεύθυνση RET σε συνδυασμό με μια άλλη πολύ σημαντική διεύθυνση, η οποία είναι αποθηκευμένη στη μνήμη του επεξεργαστή: Ο Instruction Pointer ή $RIP. Αυτή η διεύθυνση έχει πάντα τη διεύθυνση της επόμενης εντολής που θα εκτελέσει το πρόγραμμα. Έτσι, όταν φτάσουμε στο τέλος της συνάρτησης μας, εκτελείται η εντολή $RIP = RET. Έτσι, η λειτουργικότητα του προγράμματος θα επιστρέψει στον καλούντα, αφού η διεύθυνση RET διατηρεί τη διεύθυνση του καλούντος, και για να είμαστε πιο συγκεκριμένοι διατηρεί τη διεύθυνση της επόμενης εντολής από αυτή που κλήθηκε τη συνάρτηση.
Έτσι, στο παραπάνω θεωρητικό μας παράδειγμα η διεύθυνση RET θα γεμίσει με “4141414141414141”, δηλαδή το πρόγραμμα, στο τέλος της συνάρτησης checkProductKey θα προσπαθήσει να μεταβεί στη διεύθυνση 0x4141414141414141.
Αλλά μια τέτοια διεύθυνση δεν υπάρχει στο πλαίσιο του προγράμματός μας, οπότε λαμβάνουμε το γνωστό σφάλμα: segmentation fault
Έχοντας κατά νου τις παραπάνω γνώσεις ας προσπαθήσουμε να εκμεταλλευτούμε το πρόγραμμά μας.
Εξετάζοντας τη δομή $rsp στο αρχικό μας παράδειγμα (στην παραπάνω εικόνα) μπορούμε να δούμε ότι χρειαζόμαστε 3 x 8 bytes προκειμένου να ικανοποιήσουμε τη διεύθυνση RET.
Ας το αποδείξουμε αυτό με το ακόλουθο παράδειγμα:
Όπως μπορείτε να δείτε, εισάγουμε 24 x “A” = “AAAAAAAAAAAAAAAAAAAAAAAA” και τα 8 “B” “BBBBBBBB” αντικαθιστούν τη διεύθυνση RET.
Το πρόγραμμα κατέρρευσε… Αυτό που θα θέλαμε να κάνουμε στην πραγματικότητα είναι να αντικαταστήσουμε την $RIP με μια άκυρη διεύθυνση. Αλλά, στην πραγματικότητα δεν ελέγχουμε καθόλου την $RIP. Έχουμε έλεγχο μόνο στην RET όπως ήδη βλέπετε.
Για την ενημέρωσή σας πρέπει να το ξέρετε αυτό: Το μέγιστο μέγεθος διεύθυνσης που μπορούμε να χειριστούμε στην αρχιτεκτονική 64bit είναι 0x00007FFFFFFFFFFFFFFF. Αυτό που κάναμε μέχρι εδώ, είναι ότι γράψαμε επάνω στην $RIP, μέσω της RET, τη μη κανονική διεύθυνση 0x4242424242424242, η οποία προκαλεί τον επεξεργαστή να εγείρει μια εξαίρεση.
[Αν έχετε μπερδευτεί λίγο με τις 64μπιτες διευθύνσεις, μπορείτε να διαβάσετε περισσότερα για αυτή την αρχιτεκτονική των 64bit εδώ.]
Οπότε, ο στόχος ήταν να βρούμε το offset με το οποίο θα αντικαταστήσουμε την RET και κατά συνέπεια την $RIP με μια κανονική (υπαρκτή) διεύθυνση.
Για το λόγο αυτό χρησιμοποιώ ένα κυκλικό μοτίβο (ας πούμε “AAAAAABBBB” κλπ) και το δοκιμάζω μέχρι να καταλήξω στην απαραίτητη διεύθυνση (και ναι, ξέρω ότι υπάρχουν και άλλες δημοσιευμένοι μέθοδοι που υπολογίζουν διαφορετικά το απαιτούμενο offset, αλλά αυτή που παρουσίασα εδώ επίσης λειτουργεί… οπότε… ΟΚ! 😎 ).
Έτσι, θα πάω να αντικαταστήσω το “BBBBBBBBBB” με μια υπάρχουσα διεύθυνση του υπάρχοντος πηγαίου κώδικα (Code Segment) προκειμένου να παρακάμψω τους ελέγχους που γίνονται στον κώδικα για το σωστό κλειδί.
Αυτή η διεύθυνση είναι η ακόλουθη:
Σε αυτό το σημείο έχουν περάσει όλοι οι έλεγχοι σχετικά με το κλειδί προϊόντος, και αυτό είναι που ονομάζω ROP (βλ. τον τίτλο της παραγράφου).
Πρέπει να αντικαταστήσω το “B” με αυτή τη διεύθυνση: 0x0000555555555261
Αλλά πρέπει να περάσω την τιμή της ως bytes… και όχι ως συμβολοσειρά! Πώς να το κάνω αυτό;
Υπάρχουν διάφοροι τρόποι για να περάσετε αυτό το αλφαριθμητικό ως “bytes” στον αποσφαλματωτή:
Θα επιλέξω τον πιο γρήγορο… ρίξτε μια ματιά εδώ:
Ας εξετάσουμε λίγο την επίθεση “string” :
Εδώ χρησιμοποιώ λίγο την python v.2 (και στην v.3 λειτουργεί επίσης αν βάλω την εκτύπωση συμβολοσειράς σε παρενθέσεις: “(” και “)” ) : python2 -c ‘print “1”*24 + “\x55\x55\x55\x55\x55\x52\x61″[::-1]’
Αντί να γράψω μια εξήγηση σε κείμενο εδώ θα δείξω την εικόνα του αποτελέσματος όταν το εκτελώ στη γραμμή εντολών:
Όπως μπορείτε να δείτε, περνάω τα παραπάνω αποτελέσματα, ως όρισμα γραμμής εντολών στο dbg χρησιμοποιώντας τον συμβολισμό run $( <SYSTEM_COMMAND> ).
Αυτός είναι ένας εύκολος τρόπος για να περάσετε τη συμβολοσειρά της γραμμής εντολών ως bytes σε ένα πρόγραμμα.
Το πρόγραμμα “σκάει” (με segmentation fault), αλλά στο τέλος, έκανα μια επιτυχημένη ανακατεύθυνση, όπως μπορείτε να δείτε το μήνυμα ‘Welcome’ (στο πράσινο πλαίσιο παραπάνω). Έτσι, παρακάμπτω τον μηχανισμό ελέγχου!!
Σημειώστε επίσης, τον τρόπο με τον οποίο περνάω τη διεύθυνση στόχου, με αντίστροφη σειρά: ο συμβολισμός [::-1] της python απλά έβαλε τη δεκαεξαδική συμβολοσειρά αντίστροφα.
Έτσι, το “55.55.55.55.55.52.61” θα μπει στα string arguments ως “61.52.55.55.55.55.55.55” (θυμηθείτε την αρχιτεκτονική little endian που ανέφερα παραπάνω).
Σημαντική σημείωση: το “555555555261” τοποθετείται στη μνήμη με αντίστροφη σειρά ανά ζεύγος: το “55.55.55.55.55.52.61” θα τοποθετηθεί στη μνήμη ως “61.52.55.55.55.55.55“.
Και γενικά, κάθε διεύθυνση μνήμης που θα διαβάσουμε, είναι μια σειρά από ζεύγη – ή μια σειρά από 1 byte (8bits, από το 0 έως το 255 – ή αλλιώς 2^8=256 πιθανές διαφορετικές τιμές). “Historically, the byte was the number of bits used to encode a single character of text in a computer and for this reason it is the smallest addressable unit of memory in many computer architectures.” (wikipedia)
Το ίδιο ισχύει και για τα i386 64-bit Windows 10 αλλά και στο i386 64-bit Kali Linux.
Επιπλέον, ο συμβολισμός ‘\x’ υποδηλώνει ότι μιλάω στο πρόγραμμα όχι σε δεκαδικό αλλά σε δεκαεξαδικό σύστημα.
Το κάνω αυτό επειδή ο αποσφαλματωτής εμφανίζει τις διευθύνσεις μνήμης σε δεκαεξαδική σημειογραφία.
Αν αναρωτιέστε γιατί ο αποσφαλματωτής προτιμά τη δεκαεξαδική σημειογραφία, θα έλεγα το εξής:
Η δεκαδική αναπαράσταση της δεκαεξαδικής διεύθυνσης 555555555261 είναι αυτός ο αριθμός: 93824992236129. Λοιπόν, φαίνεται σαν έναν τηλεφωνικό αριθμό, ε;! 😆
Έτσι… δεν είναι τόσο εύκολο για τον άνθρωπο να αντιμετωπίσει τόσο μεγάλους αριθμούς μήκους. Η δεκαεξαδική σημειογραφία είναι πιο εύχρηστη και συνεπώς διαχειρίσιμη. Αυτός είναι ο λόγος για τον οποίο έχει υιοθετηθεί από (σχεδόν) όλα τα προγράμματα εντοπισμού σφαλμάτων στον κόσμο για την αναπαράσταση διευθύνσεων η 16δική αναπαράσταση.
Μέχρι στιγμής, λοιπόν, έχω εκτελέσει, στην ουσία, ένα “goto” (θυμάστε στη BASIC την εντολή goto😉 ή ένα JUMP (assembly-wise) με τη χρήση του debugger.
Αυτό που χρειάζομαι τώρα είναι να κάνω το ίδιο στο τελικό εκτελέσιμο από τη γραμμή εντολών σε μια κονσόλα, και ΟΧΙ με τη χρήση του dbg.
Λοιπόν, η απάντηση φαίνεται αρκετά απλή: Απλά το τρέχω από τη γραμμή εντολών αυτό:
Όπως μπορείτε να δείτε, ανοίγω την οθόνη καλωσορίσματος χωρίς να πληκτρολογήσω κανένα κλειδί προϊόντος και μόλις δημιούργησα την πρώτη μου εκμετάλλευση buffer overflow… 😎
Σημειώστε ότι τα αποτελέσματα στην παραπάνω εικόνα δεν είναι πάντα τόσο προφανή, ειδικά όταν πειράζουμε τις διευθύνσεις μνήμης και τη στοίβα απευθείας. Αρκετές φορές αυτό που βλέπω στον αποσφαλματωτή δεν είναι ακριβώς το ίδιο με αυτό που βλέπω όταν εκτελώ το πρόγραμμα απευθείας από τη γραμμή εντολών και αυτό είναι πολύ συνηθισμένο όταν πρέπει να αναφερθώ σε διευθύνσεις στη στοίβα (και όχι στο τμήμα κώδικα όπως έκανα εδώ).
Τέτοιο παράδειγμα θα δούμε στο Μέρος ΙΙI αυτής της σειράς άρθρων, όταν θα δείξω πώς να βάλω ένα “shell” στη στοίβα και πώς να το εκτελέσω. Επιπλέον στο Μέρος ΙΙI θα δούμε τι είναι το bytecode, πώς θα δημιουργήσουμε ή θα βρούμε κάποιους έτοιμα byte-codes και πώς θα τα ελέγξουμε. Θα δούμε, οτι σε τέτοιες περιπτώσεις ότι τα αποτελέσματα μπορεί να μην είναι τόσο ντετερμινιστικά όσο θα περιμέναμε…
Με πολύτιμη εμπειρία στον κόσμο της κυβερνοασφάλειας συμβάλλει ενεργά στην κοινότητά μας με αναλύσεις ευπαθειών και οδηγούς.
Με τη συνεισφορά του, προσφέρει στην κοινότητα μας ένα πλούσιο φάσμα γνώσεων και δεξιοτήτων που ενισχύουν την ανάπτυξη και την ασφάλεια του ψηφιακού μας κόσμου.