Πολεμικά Παίγνια: OTW Natas #12

Έχουμε καταφέρει να φτάσουμε στο δωδέκατο επίπεδο του πολεμικού παιγνίου OverTheWire Natas αλλά έχουμε ακόμα αρκετό δρόμο μέχρι την ολοκλήρωση του. Σε αυτό το άρθρο θα παρουσιάσουμε το 12ο επίπεδο μαζί με τη λύση μας. Όπως όλα τα επίπεδα έτσι και αυτό βασίζεται στις γνώσεις που έχουμε αποκομίσει από τα προηγούμενα. Γι’αυτό το λόγο παραθέτουμε τους συνδέσμους προς τις λύσεις όλων των προηγούμενων επιπέδων παρακάτω. Προσοχή! Όπως αναφέρουμε σε κάθε άρθρο αυτής της κατηγορίας, το πιο σημαντικό είναι να προσπαθήσετε μόνοι σας να λύσετε το κάθε επίπεδο και όχι απλώς να διαβάσετε μία λύση όπως η δική μας.

Πηγή: NBCNews.com

Μπαίνοντας στη σελίδα του παιχνιδιού από τη διεύθυνση natas12.natas.labs.overthewire.org και χρησιμοποιώντας τα στοιχεία πρόσβασης που αποκτήσαμε στο προηγούμενο επίπεδο, βλέπουμε τη παρακάτω φόρμα. Φαίνεται πως είναι μία φόρμα από την οποία μπορούμε να επιλέγουμε κάποιο αρχείο (Choose file) και να τον ανεβάζουμε στον εξυπηρετητή (Upload file). Και πάλι οι δημιουργοί του παιχνιδιού ήταν αρκετά γενναιόδωροι δίνοντας μας πρόσβαση στο πηγαίο κώδικα (View sourcecode) που εκτελείται από τη πλευρά του εξυπηρετητή.

Πηγή: OverTheWire.org

Ο πηγαίος κώδικας είναι και πάλι γραμμένος στη γλώσσα προγραμματισμού PHP που είναι καλό διότι ήδη έχουμε κάποια βασική εξοικείωση λόγω των προηγούμενων επιπέδων. Προτού μεταβούμε στο κώδικα, ας δούμε τη φόρμα που είναι σε HTML. Όπως βλέπετε στη συνέχεια, η φόρμα ορίζει το μέγιστο μέγεθος αρχείου σε 1000 Bytes, δηλαδή 1KB, και το όνομα του αρχείου που ανεβάζουμε είναι το αποτέλεσμα της συνάρτησης getRandomString() με την επέκταση αρχείου «.jpg».

<form enctype="multipart/form-data" action="index.php" method="POST"> 
<input type="hidden" name="MAX_FILE_SIZE" value="1000" /> 
<input type="hidden" name="filename" value="<? print genRandomString(); ?>.jpg" /> 
Choose a JPEG to upload (max 1KB):<br/> 
<input name="uploadedfile" type="file" /><br /> 
<input type="submit" value="Upload File" /> 
</form> 

Γνωρίζοντας αυτό, πάμε να δούμε τον πηγαίο κώδικα από τη πλευρά του εξυπηρετητή. Θα ξεκινήσουμε από τη συνάρτηση getRandomString() η οποία κατασκευάζει ένα τυχαίο όνομα για το αρχείο που ανεβάζουμε. Όπως βλέπετε στο κώδικα παρακάτω, ορίζει το μέγιστο μήκος του ονόματος σε 10 χαρακτήρες και έπειτα κάνει μία επανάληψη με τη πράξη «for» όπου ένας τυχαίος χαρακτήρας επιλέγεται κάθε φορά για 10 επαναλήψεις. Ο τυχαίος χαρακτήρας επιλέγεται μέσω της συνάρτησης mt_rand().

function genRandomString() { 
    $length = 10; 
    $characters = "0123456789abcdefghijklmnopqrstuvwxyz"; 
    $string = "";     

    for ($p = 0; $p < $length; $p++) { 
        $string .= $characters[mt_rand(0, strlen($characters)-1)]; 
    } 

    return $string; 
} 

Ο πηγαίος κώδικας περιλαμβάνει δύο ακόμα βοηθητικές συναρτήσεις, τη συνάρτηση makeRandomPath() και τη συνάρτηση makeRandomPathFromFilename(). Η πρώτη χρησιμοποιεί δημιουργεί ένα φάκελο με το όνομα που της δίδεται μέσω της παραμέτρου $dir και ένα αρχείο με τυχαίο όνομα μέσω της genRandomString() όπου η επέκταση του αρχείου ορίζεται από τη παράμετρο $ext.

function makeRandomPath($dir, $ext) { 
    do { 
    $path = $dir."/".genRandomString().".".$ext; 
    } while(file_exists($path)); 
    return $path; 
} 

Η δεύτερη συνάρτηση, η makeRandomPathFromFilename(), είναι αρκετά πιο απλή. Δέχεται ως παράμετρο ένα φάκελο ($dir) και ένα όνομα αρχείου ($fn) και έπειτα μέσω της συνάρτησης pathinfo() παίρνει την επέκταση του αρχείου και τη στέλνει στη συνάρτηση makeRandomPath() μαζί με το όνομα φακέλου.

function makeRandomPathFromFilename($dir, $fn) { 
    $ext = pathinfo($fn, PATHINFO_EXTENSION); 
    return makeRandomPath($dir, $ext); 
}

Τώρα που γνωρίζουμε τι κάνουν όλες οι βοηθητικές συναρτήσεις του προγράμματος, ήρθε η ώρα να δούμε το κύριο κώδικα του εξυπηρετητή που περιέχει και όλη τη λογική του. Όπως διαβάζουμε ο κώδικας είναι αρκετά απλός. Εάν υπάρχει κάτι για αποστολή, τότε στέλνει στη συνάρτηση makeRandomPathFromFilename() το όνομα φακέλου «upload» και το όνομα του αρχείου μας. Έπειτα ελέγχει ότι το αρχείο μας δεν είναι μεγαλύτερο από 1000 Bytes και σε αυτή τη περίπτωση ανεβάζει το αρχείο μέσω της συνάρτησης move_uploaded_file() στον εξυπηρετητή.

if(array_key_exists("filename", $_POST)) { 
    $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]); 


        if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) { 
        echo "File is too big"; 
    } else { 
        if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { 
            echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded"; 
        } else{ 
            echo "There was an error uploading the file, please try again!"; 
        } 
    } 
} else { 
?>

Το πρόγραμμα αυτό έχει αρκετά κενά ασφαλείας και συνδυαστικά μπορούν να μας επιτρέψουν εκτέλεση αυθαίρετου κώδικα στον εξυπηρετητή, που είναι και αυτό που θα κάνουμε για να προχωρήσουμε στο επόμενο επίπεδο. Γνωρίζουμε ότι ο κωδικός πρόσβασης για το επίπεδο 13 είναι στο αρχείο /etc/natas_webpass/natas13 άρα αυτό που θέλουμε να κάνουμε είναι να πάρουμε πρόσβαση εκεί. Ας ξεκινήσουμε με το σχέδιο δράσης μας όμως.

Πηγή: PerlTricks.com

Παρότι η φόρμα γράφει ότι μπορούμε να ανεβάζουμε αρχεία εικόνων σε μορφή JPEG, πουθενά στο κώδικα δεν γίνεται έλεγχος εάν κάνουμε κάτι τέτοιο. Έτσι, μπορούμε να ανεβάσουμε οποιοδήποτε αρχείο και εφόσον γνωρίζουμε ότι ο εξυπηρετητής εκτελεί κώδικα σε γλώσσα προγραμματισμού PHP, μπορούμε να ανεβάσουμε ένα πρόγραμμα γραμμένο σε PHP που θα μας δίνει πλήρη πρόσβαση στο απομακρυσμένο σύστημα. Υπάρχει όμως ένα μικρό πρόβλημα.

Πηγή: Tripwire.com

Εάν παρατηρήσατε, το πρόγραμμα θα μετονομάσει το αρχείο μας με κάποιο τυχαίο όνομα με την επέκταση «.jpg» προτού το στείλει στον εξυπηρετητή. Και εδώ όμως οι προγραμματιστές άφησαν ένα σοβαρό κενό ασφαλείας. Κάνοντας αυτή τη λειτουργία (τυχαίο όνομα και επέκταση αρχείου) στη πλευρά του προγράμματος-πελάτη (δηλαδή όχι στον εξυπηρετητή) σημαίνει ότι έχουμε πλήρη πρόσβαση στη παραποίηση του. Θα κάνουμε έτσι μία επίθεση τύπου MITM (Man In The Middle, άνθρωπος στη μέση) με τον ίδιο τρόπο που είχαμε κάνει και στο «Πολεμικά Παίγνια: OTW Natas #4» και θα παραποιήσουμε το όνομα και την επέκταση προτού σταλεί στον εξυπηρετητή. Βλέπετε το σχέδιο δράσης μας σχηματικά εδώ.

Πηγή: Προσωπικό αρχείο

Τώρα που έχουμε ένα ξεκάθαρο σχέδιο επίθεσης, μένει να το υλοποιήσουμε. Το κακόβουλο πρόγραμμα μας σε γλώσσα προγραμματισμού PHP θα είναι κάτι πολύ απλό. Θα χρησιμοποιήσουμε τη συνάρτηση passthru() η οποία εκτελεί οποιαδήποτε εντολή συστήματος της δοθεί. Για να είναι εύκολος ο χειρισμός της απομακρυσμένα, θα της πούμε να εκτελεί οτιδήποτε δίνουμε εμείς στη παράμετρο $entolh. Βλέπετε το τελικό αποτέλεσμα από ολόκληρο το κακόβουλο πρόγραμμα μας εδώ.

<?
    passthru($_GET['entolh']);
?>

Πηγή: Proeducis.com

Αποθηκεύουμε το παραπάνω πρόγραμμα σε ένα αρχείο με όνομα shell.php και ξεκινάμε το Burp Suite όπως ακριβώς είχαμε περιγράψει στο άρθρο μας «Πολεμικά Παίγνια: OTW Natas #4». Έχοντας ενεργοποιήσει τη λειτουργία υποκλοπής (Intercept On) στο πρόγραμμα Burp Suite επιλέγουμε το αρχείο που θέλουμε να ανεβάσουμε.

Πηγή: OverTheWire.org

Με το που πατήσουμε «Upload file» το Burp Suite θα μας ενημερώσει ότι έχει σταματήσει την επικοινωνία και έχει υποκλέψει το παρακάτω μήνυμα. Έχουμε καλύψει διάφορες πληροφορίες που δεν είναι σημαντικές και έχουμε υπογραμμίσει το πιο σημαντικό, το όνομα του αρχείου που αποστέλλεται. Αυτό που έχει σημασία εδώ είναι να αλλάξουμε το όνομα του αρχείου ώστε να έχει επέκταση «.php» για να μπορεί να εκτελεστεί στον εξυπηρετητή. Εμείς το μετονομάσαμε σε «shell.php».

Πηγή: Προσωπικό αρχείο

Εφόσον το αλλάξουμε πατάμε προώθηση (Forward) για να σταλεί το κακόβουλο πρόγραμμα με το παραποιημένο όνομα στον εξυπηρετητή. Όπως ακριβώς είχαμε υπολογίσει, ο εξυπηρετητής του έδωσε ένα άλλο τυχαίο όνομα αλλά δεν άλλαξε την επέκταση και το μετέφερε στο φάκελο «upload» επιστρέφοντας μας ένα σύνδεσμο για να το δούμε.

Πηγή: OverTheWire.org

Εάν πατήσουμε στο σύνδεσμο θα δούμε ότι η εκτέλεση του προγράμματος μας επιστρέφει κάποια σφάλματα. Ο λόγος είναι ότι η παράμετρος $entolh που πρέπει να εκτελέσει δεν περιέχει κάτι (Cannot execute blank command).

Πηγή: OverTheWire.org

Άρα πρέπει να πούμε στη παράμετρο $entolh τι ακριβώς εντολές θέλουμε να εκτελέσουμε στο απομακρυσμένο σύστημα. Στη περίπτωση μας είναι αρκετά απλό καθώς γνωρίζουμε ότι ο κωδικός πρόσβασης για το επόμενο επίπεδο είναι στο αρχείο /etc/natas_webpass/natas13. Έτσι, θα χρησιμοποιήσουμε την εντολή συστήματος «cat» που θα πρέπει να επιστρέψει όλα τα περιεχόμενα του αρχείου. Βλέπετε πως ακριβώς το κάνουμε αυτό εδώ.

Πηγή: OverTheWire.org

Και όπως το είχαμε υπολογίσει, η εντολή μας εκτελέστηκε με επιτυχία και μπορέσαμε να ανακτήσουμε το κωδικό πρόσβασης για το επόμενο επίπεδο όπως βλέπετε και μόνοι σας.

Πηγή: OverTheWire.org

Στο χώρο της ασφάλειας το κενό ασφαλείας που εκμεταλλευτήκαμε ονομάζεται «Unrestricted File Upload» (Ανέβασμα Αρχείου Χωρίς Περιορισμό) και όπως είδαμε μπορεί να μας προσφέρει πλήρη πρόσβαση στον εξυπηρετητή. Μέχρι και σήμερα αρκετά συστήματα έχουν τέτοια κενά ασφαλείας. Ένα πραγματικό παράδειγμα από το πρόσφατο παρελθόν είναι αυτό με μοναδικό αναγνωριστικό CVE-2016-9187 που έγινε γνωστό και το Νοέμβριο του 2016 στο λογισμικό Moodle και αφορά όλες τις εκδόσεις μέχρι και την 3.1.2. Συγκεκριμένα η παράμετρος «image» είχε το ίδιο κενό ασφαλείας με αυτό που περιγράψαμε και έτσι μπορούσε κανείς να ανεβάζει οποιοδήποτε αρχείο και όχι μόνο εικόνες. Αυτό το αναφέρουμε ως υπενθύμιση ότι οι γνώσεις που αποκομίζει κανείς από αυτά τα πολεμικά παίγνια έχουν ουσιαστική αξία και διδάσκουν τεχνικές και κενά ασφαλείας που είναι υπαρκτά στον ηλεκτρονικό κόσμο σήμερα.

Γράψτε τα σχόλια σας εδώ...

Εισάγετε τα παρακάτω στοιχεία ή επιλέξτε ένα εικονίδιο για να συνδεθείτε:

Λογότυπο WordPress.com

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό WordPress.com. Αποσύνδεση / Αλλαγή )

Φωτογραφία Twitter

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Twitter. Αποσύνδεση / Αλλαγή )

Φωτογραφία Facebook

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Facebook. Αποσύνδεση / Αλλαγή )

Φωτογραφία Google+

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Google+. Αποσύνδεση / Αλλαγή )

Σύνδεση με %s