Δημοσιεύτηκε: 17 Απρ 2011, 23:03
από Star_Light
Σε αυτόν τον οδηγό θα προσπαθήσω να προσεγγίσω θεωρητικά το θεματάκι(και οχι με πολυ κουραστική πολυλογία) με το Buffer Overflow και να δούμε και 2-3 πρακτικά απλά τίπς για το πώς μπορούμε να είμαστε ενήμεροι ως προς την ασφάλεια για αυτο το θέμα ως προς τις διάφορες εφαρμογές που παίζουν.

Καταρχήν με τον όρο Buffer Overflow εννοούμε μια μη επιθυμητή κατάσταση κατα την οποία μια διεργασία / ένα πρόγραμμα προσπαθεί να αποθηκεύσει δεδομένα πέραν των ορίων ενός buffer , ένας buffer είναι μια περιοχή προσωρινής αποθήκευσης ελεγχόμενη απο το λειτουργικό σύστημα και δεν σχετίζεται με την φυσική μνήμη του συστήματος μας.

Η πρόσβαση για παράδειγμα σε έναν δίσκο ή σε μια άλλη συσκευή εισόδου/εξόδου ειναι γενικά πολυ πιο αργή απο μια άμεση πρόσβαση στην μνήμη. Μπορούν να γίνουν διάφορες λειτουργίες εισόδου - εξόδου σε ένα buffer που αντιπροσωπεύει το αρχείο εισόδου/εξόδου αντι για το ίδιο το αρχείο.

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

Φυσικά το τελευταίο μπορεί να γίνει απο την στιγμή που αλλάξει η ροή εκτέλεσης του προγράμματος και την εκτέλεση μετα κακόβουλου κώδικα. :!: :!: :!:

Ο πιο συνηθισμένος τρόπος για να επιτευχθεί το παραπάνω είναι με το να επικαλύψεις ενα τμήμα της στοίβας του προγράμματος που τρέχει. Η στοίβα του προγράμματος μεταξύ άλλων περιέχει και την διευθυνσή επιστροφής δηλαδή την ΘΕΣΗ μνήμης στην οποία το πρόγραμμα θα μεταφέρει τον έλεγχο όταν η συνάρτηση τερματίσει. :idea: :idea: :idea: :idea:

Ακριβώς σε αυτό το σημείο μπορείς να αλλάξεις την διεύθυνση επιστροφής να δείχνει σε εκείνο το κομμάτι μνήμης στο οποίο έχεις τοποθετήσει τον κώδικα που θέλεις να εκτελεστεί. Όταν το πρόγραμμα επιστρέψει απο την συνάρτηση που συζητήσαμε προηγουμένως θα πηδήσει στον νέο κώδικα και θα εκτελέσει το οτιδήποτε τρέχοντας με τα προνόμια φυσικά της υφιστάμενης διεργασίας.

Με λίγα λόγια λοιπον και πολυ απλά μια επίθεση υπερχείλισης μνήμης συμβαίνει οταν μια εφαρμογή δεν ελέγχει αν το μέγεθος της εισόδου (μια τιμή απο τον χρήστη) είναι μικρότερη ή ιση απο το μέγεθος της μνήμης που έχει δεσμευτεί για αυτήν τη μεταβλητή η οποια και θα αποθηκεύσει την τιμή που δίνει ο χρήστης.

Πάμε να δούμε τώρα ένα παράδειγμα Υπερχείλισης μνήμης σε πραγματική εφαρμογή :!: :!: :!:

Όλοι γνωρίζουμε την εφαρμογή MTA sendmail. Όλοι ή εστω οι περισσότεροι συζητούσαν για το ότι το sendmail δεν ειναι τόσο ασφαλές πχ απο το Postfix , αρκετά ζητήματα ασφάλειας υπήρχαν στο πρώτο . Ένα απο αυτά σχετίζεται με την Υπερχείλιση μνήμης για την οποία κάνουμε λόγο στον συγκεκριμένο οδηγό. ΠΙο συγκεκριμένα ο sendmail daemon χρησιμοποιεί μια σταθερού μεγέθους συμβολοσειρά buffer.
Ταυτόχρονα επιτρέπει στους πελάτες του δικτύου να παραθέτουν συμβολοσειρές που υπερχειλίζουν το buffer .

Ας δούμε και το πιο κάτω τμήμα κώδικα σε γλώσσα C.

Κώδικας: Επιλογή όλων


#include <stdio.h>
int main ( )
{
char username[32]; /*Wstoso to UNix epitrepei mexri 8 xaraktirwn onomata*/
printf("Please enter your username: ");
gets(username);      /* Diavazei eisodo xrhsth */
return 0;
}


Όταν γράφουμε κώδικα καλό είναι να λαμβάνουμε υπόψιν τι μπορεί να κάνει ένας κακόβουλος. ( Οι επισημάνσεις και οι προειδοποιήσεις που μας δινει o geany editor δεν είναι τυχαίες)
Αν εδω δοθεί σκόπιμα ενα πολύ μεγάλο όνομα χρήστη θα αποθηκευτεί στην στοίβα και θα επικαλύψει κομμάτια επιτρέποντας την επίθεση κάποιου κακόβουλου.

:idea: :idea: :idea: :idea:

Όταν διαβάζουμε συμβολοσειρές μπορούμε να παίζουμε με την δυναμική δέσμευση μνήμης την οποία μας παρέχει η C σαν μια χαμηλού επιπέδου λειτουργία (διαχείριση μνήμης επι της ουσίας) αλλα μπορει να αποδειχθεί σωτήρια. Σε γενικές γραμμές υπερχείλιση μπορεί να συμβεί σε οποιουδήποτε πίνακα στατικής μορφής - στατικού δηλαδη μεγέθους

Όταν προγραμματίζουμε δεν θα πρέπει να μας ενδιαφέρει μονο η αποτελεσματικότητα ενος προγράμματος αλλα και η ασφάλεια του. Στην C υπάρχουν συναρτήσεις που όταν χρησιμοποιούνται θέλουν ιδιαίτερη προσοχή.

Κώδικας: Επιλογή όλων
strcpy() , gets() , scanf()


Όταν πάμε να αντιγράψουμε κάτι με την με την strcpy θα υπάρξει αδυναμία - κενό αν δεν κάνουμε κάποιον έλεγχο στο μέγεθος. Αν ένας επιτιθέμενος διαπιστώσει τέτοιου είδους αδυναμία μπορεί να εισάγει μια μεγάλου μήκους συμβολοσειρά για παράδειγμα που στο τέλος της να περιέχει εκτελέσιμο κώδικα .

Συμπερασματικά η λύση γυρω απο τέτοιου είδους επιθέσεις ειναι η ενημέρωση.
Οι εκδόσεις 5.2 , 5.3 , 5.3.5 & 5.2.17 της PHP αντιμετωπίζουν ενα πρόβλημα σχετικα με την υπερχείλιση μνήμης.
Απο το τερματικό μπορούμε να δώσουμε την εξής εντολή

Κώδικας: Επιλογή όλων
kostas@kostas-SSL:~$ php -v
PHP 5.3.3-1ubuntu9.3 with Suhosin-Patch (cli) (built: Jan 12 2011 16:07:38)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
kostas@kostas-SSL:~$


για να δούμε ποια έκδοση της εφαρμογής χρησιμοποιούμε. Μπορούμε να το κάνουμε αυτο γενικά και για κάθε εφαρμογή απο το τερματικό
Κώδικας: Επιλογή όλων
<application> -v


Μια παρόμοια εντολή με την πιο πάνω ειναι επίσης και η

Κώδικας: Επιλογή όλων
kostas@kostas-SSL:/etc$ dpkg -l apache2
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Όνομα     Έκδοση   Περιγραφή
+++-==============-==============-============================================
ii  apache2        2.2.16-1ubuntu Apache HTTP Server metapackage
kostas@kostas-SSL:/etc$


Μπορούμε να επισκεφτούμε και την σελίδα

Κώδικας: Επιλογή όλων
http://packages.qa.debian.org/pkg-name


ή την

Κώδικας: Επιλογή όλων
http://bugs.debian.org/pkg-name



Οπότε μπορούμε μετά να μπαίνουμε στην αντίστοιχη σελίδα αναφοράς
Κώδικας: Επιλογή όλων
http://www.php.net/


και να βλέπουμε αν η συγκεκριμένη εφαρμογή αντιμετωπίζει θέματα σχετικά με την υπερχείλιση μνήμης. Η έκδοση 5.3.3 της δικιάς μου PHP αναφέρεται σε αριθμό δευτερεύουσας έκδοσης η ομάδα της PHP χρησιμοποιεί αριθμούς δευτερεύουσας έκδοσης (παρόμοια φιλοσοφία θα παίζει και σε πληθώρα εφαρμογών) για να χαρακτηρίσει τις ενημερώσεις της κύριας έκδοσης του λογισμικού που περιέχουν σχετιζόμενες με την ασφάλεια βελτιώσεις ή διορθώσεις σφαλμάτων.

Ένας επίσης πολύ καλύτερος τρόπος απο τον παραπάνω (ως προς την εκτενέστατη έξοδο του σχετικά με τις πληροφορίες για την php μας είναι χρησιμοποιώντας την συνάρτηση)

Κώδικας: Επιλογή όλων
<?php phpinfo()
?>


Η έξοδος του παραπάνω script άν το δώσουμε απο το localhost του apache δείχνει μια μεγάλη ποσότητα πληροφοριών σχετικά με την τρέχουσα κατάσταση της PHP . Πληροφορίες σχετικά με την μεταγλώττιση , επεκτάσεις , την έκδοση (που με την προηγούμενη εντολή php -v βλέπαμε μονο αυτο το στοιχείο ) το περιβάλλον της PHP και άλλα πολλά.

ΣΤην συνέχεια μπορούμε να διαβάσουμε και την τεκμηρίωση της PHP για την ασφάλεια.

http://www.php.net/manual/en/security.php

:!: :!: :!: :!: Ευχαριστώ τον Αποστόλη για την παραπάνω επισήμανση μιας και ο ίδιος μου το τόνισε την αξία της phpinfo()

Υπάρχουν και άλλοι πιο γρήγοροι - αξιοπιστοι και ευκολοι τρόποι για να μπορέσει κάποιος να μάθει απο τι είδους ευπάθεια μπορει να πάσχουν οι εφαρμογές που τρέχει το συστημά του συμπεριλαμβανομένης και της υπερχείλισης μνήμης :

Εγκατάσταση του network mapper (nmap)

Κώδικας: Επιλογή όλων
sudo apt-get install nmap


και απο το κέλυφος η εντολή

Κώδικας: Επιλογή όλων
nmap -sV 127.0.0.1

το flag -sV που δέχεται σαν παράμετρος το nmap ουσιαστικά δεν κάνει τιποτε αλλο
απο ενα scan σε όλες τις ανοικτές πόρτες για να επιστρέψει τις εκδόσεις των εφαρμογών που τρέχουν σε αυτες.

Αν υποθέσουμε πως στο σύστημα τρέχει εφαρμογή εξυπηρετητή ProFTPD 1.3.2rc3 τότε υπάρχει ευπάθεια υπερχείλισης μνήμης οπως μπορει κανεις να διαβάσει και εδω

Κώδικας: Επιλογή όλων
http://www.saintcorporation.com/cgi-bin/demo_tut.pl?tutorial_name=ProFTPD_vulnerabilities.html&fact_color=&tag=


ΌΠως επισημάνθηκε και πιο πάνω η καλύτερη λύση είναι η συνεχής ενημέρωση. Ωστόσο υπάρχει ενα χρονικό διάστημα στο οποίο ένα κενό ασφάλειας έχει βρεθεί μεν αλλα πρεπει και να δημοσιοποιηθεί , σε τέτοιες περιπτώσεις κάποιος οφείλει να ακολουθεί ένα απο τα βασικά τιπ ασφάλειας περα απο το Buffer Overflow και να απενεργοποιεί υπηρεσίες που δεν του χρειάζονται ετσι οι πιθανότητες κάποιας παραβίασης φυσικα μειώνονται



Τέλος αξίζει να επισημανθεί οτι το θέμα με την συγκεκριμένη ευπάθεια ειναι ιδιαίτερα σημαντικό για την ασφάλεια ενός συστήματος καθώς αρκετά προγράμματα τα οποία θα τρέχουν ως root οπότε καταλαβαίνουμε όλοι τι θα συμβεί αν κάποιος αποκτήσει τον έλεγχο πάνω τους.

Ελπίζω να τον βρείτε χρήσιμο και περιεκτικό. Αναμένω για διορθώσεις , επισημάνσεις και συμπληρώσεις :thumbup: :thumbup: :thumbup: