Οι συνέπειες μιας υπ3rxεiλ1ση$,.. &+@~
Αν μιλάμε για το φράγμα ενός ποταμού, οι συνέπειες είναι δυσάρεστες για όλους! Εάν όμως μιλάμε για ένα στοιχείο στη στοίβα ενός προγράμματος, το πράγμα αλλάζει: Για τον επιτιθέμενο αυτή η κατάσταση είναι μάλλον ευχάριστη και τον γεμίζει με αισιοδοξία! Όσο για το υποψήφιο θύμα, καλά θα κάνει ν’ ανησυχεί…
Το λεγόμενο stack overflow είναι μια κατάσταση η οποία, σύμφωνα με τον οργανισμό Web Application Security Consortium, είναι πολύ συχνή και πολύ επικίνδυνη. Για να γίνει κατανοητός ο μηχανισμός μιας επίθεσης stack overflow, απαιτούνται ορισμένες γνώσεις για τα όσα συμβαίνουν κατά την εκτέλεση ενός προγράμματος. Ελπίζουμε να καλύψαμε τα κενά με το άρθρο μας που αρχίζει από τη σελίδα 46, οπότε στο παρόν θα περάσουμε αμέσως στο ψητό: Θα περιγράψουμε βήμα προς βήμα —και με πραγματικά παραδείγματα—, όλες τις ενέργειες που μπορεί να κάνει κάποιος για να ανακαλύψει μια τέτοια αδυναμία σ’ ένα πρόγραμμα. Φυσικά, θα αναφέρουμε και όλα όσα πρέπει να προσέχει ένας προγραμματιστής, ώστε να εξασφαλίσει ότι το δημιούργημά του θα είναι θωρακισμένο απέναντι στις επιθέσεις buffer overflow.
Πριν συνεχίσουμε, οφείλουμε να ξεκαθαρίσουμε ότι οι λόγοι για τους οποίους παρουσιάζουμε τεχνικές σαν αυτή είναι αποκλειστικά εκπαιδευτικοί. Δεν θέλουμε να δημιουργήσουμε υποψήφιους επιτιθέμενους, ούτε να βοηθήσουμε κάποιους να παραβιάσουν την προστασία ξένων προγραμμάτων. Επιθυμούμε μόνο να σας προβληματίσουμε, ώστε να γίνετε πιο προσεκτικοί. Τελικός στόχος είναι το να μπορείτε να γράφετε ασφαλέστερα προγράμματα, όπως και το να βοηθάτε άλλους προγραμματιστές προς αυτή την κατεύθυνση. Το πρόβλημα, με όποιους δεν θέλουν να χρησιμοποιήσουν τη γνώση για καλό, βρίσκεται στο κεφάλι τους και στη μετριότητά τους. Η γνώση δεν πρέπει να θάβεται, με πρόφαση την προστασία μας από μερικούς κομπλεξικούς. Διαφορετικά την “πληρώνουμε” όλοι μας, περιορίζοντας τη δύναμη και τις δυνατότητές μας σε εκείνες του πιο αδύναμου κρίκου…
Σε πολύ γενικές γραμμές, μια επίθεση buffer overflow εκμεταλλεύεται τις συνέπειες που επιφέρει το γράψιμο σε μη προβλεπόμενες περιοχές της μνήμης. Διαβάζοντας την αμέσως προηγούμενη πρόταση, θα μπορούσε κάποιος να υποθέσει ότι τα αποτελέσματα μιας τέτοιας ενέργειας είναι απρόβλεπτα! Χμ, εν μέρει σωστό είναι αυτό, αλλά όχι πάντα. Αρκεί να ξέρουμε ακριβώς τι κάνουμε ;) Για την επίθεση stack overflow ο πρώτος που μίλησε επίσημα ήταν ο Aleph One το 1996, στο περίφημο άρθρο του Smashing the stack for fun and profit. Από τότε μέχρι σήμερα έχουν αλλάξει πάρα πολλά. Ωστόσο οι σχετικές αδυναμίες δεν έχουν εξαλειφθεί, παρά την ανάπτυξη πολλών μηχανισμών προστασίας στις γλώσσες προγραμματισμού (συγκεκριμένα στους αντίστοιχους compilers) αλλά και στα λειτουργικά συστήματα. Πριν προχωρήσουμε, να διευκρινίσουμε ότι όσα θα αναφέρουμε για διευθύνσεις μνήμης και καταχωρητές ισχύουν για επεξεργαστές αρχιτεκτονικής i386. Πάμε, λοιπόν!
Διαβάστε ολόκληρο το άρθρο στο deltaHacker Ιανουαρίου (τεύχος 004).
Για αγορές τευχών ή συνδρομών στο περιοδικό deltaHacker, απλά συμπληρώστε τη φόρμα.
Σημείωση: Οι συνδρομές μπορούν ν’ αρχίζουν από όποιο τεύχος επιθυμείτε, αρκεί να υπάρχει σε stock.
Το deltaHacker είναι το μοναδικό, μηνιαίο συνδρομητικό περιοδικό με θεματολογία ethical hacking και infosec που δεν κυκλοφορεί στα περίπτερα. Αν δεν το διαβάζετε ακόμα, κάτι μας λέει ότι σύντομα θ’ αρχίσετε. Εκτός δηλαδή κι αν δεν αγαπάτε πολύ-πολύ-πολύ τον υπολογιστή σας, ούτε την τεχνολογία :S
Το παρασκήνιο μιας εκτέλεσης!
Πώς γράφονται τα προγράμματα; Πώς χρησιμοποιείται η μνήμη για την εκτέλεση ενός προγράμματος; Τι αποθηκεύεται και πού; Πότε και από ποιον; Σε μια προσπάθεια να μάθουμε όσα συμβαίνουν κατά την εκτέλεση ενός προγράμματος, απαντάμε σε όλα αυτά τα ερωτήματα — και σε αρκετά ακόμα!
Ένα πρόγραμμα, στη μορφή που το γράφει ο δημιουργός του, αποτελείται από εντολές κατανοητές μόνο από ανθρώπους και ονομάζεται πηγαίος κώδικας ή απλά κώδικας. Αυτός ο κώδικας περνάει από μια επεξεργασία με ειδικά εργαλεία, που ονομάζονται μεταγλωττιστές (compilers) ή διερμηνευτές (interpreters), για να μεταφραστεί σε μια γλώσσα κατανοητή μόνο από τον επεξεργαστή του υπολογιστή. Τώρα θα αναρωτηθούν κάποιοι: Σε τι διαφέρει ένας compiler από έναν interpreter; Σε πολλά! Ένας compiler μεταφράζει ολόκληρο τον πηγαίο κώδικα και παράγει ένα ολοκληρωμένο πρόγραμμα, το οποίο ονομάζουμε εκτελέσιμο (βλ., π.χ., τα γνωστά αρχεία exe στα Windows). Ένα εκτελέσιμο αρχείο αποτελείται από εντολές στη λεγόμενη γλώσσα μηχανής. Όπως αντιλαμβάνεστε, αυτή η γλώσσα είναι κατανοητή από τον υπολογιστή χωρίς να απαιτούνται περαιτέρω μεταφράσεις. Οι μεταγλωττιστές χρησιμοποιούνται σε πηγαίο κώδικα που γράφτηκε σε C, C++, Pascal κ.ά. Οι διερμηνευτές (interpreters) από την άλλη μεταφράζουν τον πηγαίο κώδικα εντολή προς εντολή. Συνήθως φορτώνουν τον πηγαίο κώδικα στη μνήμη, διαβάζουν μία γραμμή, την εκτελούν και προχωρούν στην επόμενη. Οι διερμηνευτές, λοιπόν, δεν παράγουν κανένα νέο αρχείο. Διερμηνευτές υπάρχουν για πολλές γλώσσες και μάλλον για όλες όσες χρησιμοποιούνται στο web (PHP, ASP κ.ά.).
Φυσικά, κάθε προσέγγιση έχει τα καλά αλλά και τα κακά της: Ένα μεταγλωττισμένο πρόγραμμα εκτελείται πολύ πιο γρήγορα από κάποιο που διερμηνεύεται γραμμή προς γραμμή. Επίσης, ένα μεταγλωττισμένο πρόγραμμα είναι σίγουρα απαλλαγμένο από κάθε συντακτικό λάθος. Μιλάμε για τα λάθη που μπορεί να κάνει ένας προγραμματιστής επειδή πληκτρολογεί βιαστικά ή γιατί ξέχασε έναν απαραίτητο χαρακτήρα (π.χ. εκείνον που τερματίζει μία γραμμή κώδικα). Αυτό για την απουσία συντακτικών σφαλμάτων είναι βέβαιο, διότι πριν ξεκινήσει την εργασία του ένας μεταγλωττιστής, εξασφαλίζει ότι ο πηγαίος κώδικας είναι 100% σωστά γραμμένος. Ένα εκτελέσιμο πρόγραμμα είναι —τουλάχιστον θεωρητικά— πολύ δύσκολο να διαβαστεί από κάποιον τρίτο, ο οποίος προσπαθεί να μάθει την εσωτερική/κρυφή λογική ενός προγράμματος.
Από την άλλη, τα προγράμματα που περνάνε από διερμηνευτές είναι πολύ πιο εύκολα στην συντήρηση και στην επέκταση, αφού αν μη τι άλλο δεν απαιτείται η χρονοβόρα διαδικασία του compilation κάθε φορά που αλλάζουμε/δοκιμάζουμε κάτι. Για προγράμματα στα οποία η ταχύτητα δεν είναι κρίσιμη και στα οποία επεμβαίνουμε συχνά, οι διερμηνευόμενες (interpreted) γλώσσες είναι ιδανικές!
Για λόγους πληρότητας, πρέπει να αναφέρουμε και μια τρίτη κατηγορία προγραμμάτων. Πρόκειται για εκείνα που εκτελούνται σε εικονικές μηχανές (virtual machines ) και δεν μεταγλωττίζονται σε γλώσσα μηχανής αλλά σε μία γλώσσα κατανοητή από την εικονική μηχανή. Αυτή η προσέγγιση ακολουθείται σε γλώσσες όπως η Java και για το γνωστό Microsoft .Net. Βέβαια μη νομίζετε ότι αυτή η ιστορία είναι και πολύ καινούρια! Τη 10ετία του 1980 υπήρχε το περίφημο P-System της Pascal, για το οποίο είχαν γραφτεί πολλές εφαρμογές! Το κύριο πλεονέκτημα που προκύπτει από τη χρήση μιας εικονικής μηχανής είναι η φορητότητα. Ένα πρόγραμμα που γράφτηκε για μία εικονική μηχανή θα μπορεί να εκτελείται σε κάθε υπολογιστή και σε κάθε λειτουργικό σύστημα, στο οποίο τρέχει η σχετική εικονική μηχανή. Όσο για την ταχύτητα εκτέλεσης, ένα πρόγραμμα που τρέχει σε εικονική μηχανή είναι συνήθως ταχύτερο από ένα διερμηνευόμενο (interpreted) αλλά πιο αργό από ένα μεταγλωττισμένο σε γλώσσα μηχανής.
Διαβάστε ολόκληρο το άρθρο στο deltaHacker Ιανουαρίου (τεύχος 004).
Για αγορές τευχών ή συνδρομών στο περιοδικό deltaHacker, απλά συμπληρώστε τη φόρμα.
Σημείωση: Οι συνδρομές μπορούν ν’ αρχίζουν από όποιο τεύχος επιθυμείτε, αρκεί να υπάρχει σε stock.
Το deltaHacker είναι το μοναδικό, μηνιαίο συνδρομητικό περιοδικό με θεματολογία ethical hacking και infosec που δεν κυκλοφορεί στα περίπτερα. Αν δεν το διαβάζετε ακόμα, κάτι μας λέει ότι σύντομα θ’ αρχίσετε. Εκτός δηλαδή κι αν δεν αγαπάτε πολύ-πολύ-πολύ τον υπολογιστή σας, ούτε την τεχνολογία :S

