Blind SQL Injection

In this article I will demonstrate a blind SQL injection attack against level 17 of the Natas hacking game at overthewire.org.

Upon logging into natas17 we are presented with a simple form that allows us to submit a username to check if it exists in the backend database:

natas17home

This is further verified by the PHP source code:

natas17src

Examining this code reveals key indicators as to how this website may be compromised. Firstly, the commented lines at the very beginning indicate that the backend SQL database contains a table called “users” where usernames and passwords are stored:

CREATE TABLE `users` (`username` varchar(64) DEFAULT NULL,`password` varchar(64) DEFAULT NULL);

Next we have the variable $query that contains and SQL query string.  This is passed to the database by the form when checking for a valid username:

$query = “SELECT * from users where username=\””.$_REQUEST[“username”].”\””;

Finally, there is an if statement that returns query result.  However, in this case the output messages are commented.

if(mysql_num_rows($res) > 0) {

//echo “This user exists.<br>”;

} else {

//echo “This user doesn’t exist.<br>”;

}

} else {

//echo “Error in query.<br>”;

Testing this form we find that a blank page is returned no mater what the input or result:

natas17blank

This confirms that we need to query the database using a fully blind SQL injection.  In order to implement this attack, we first turn our attention to the hard coded SQL query.

SELECT * from users where username=\””.$_REQUEST[“username”].”\”

The code uses character escaping \” to enforce double quotes around the form input to ensure that is passed as the value of the table column username.  However, due to the fact that the form input is not correctly sanitized, we are able append this query with additional commands using the following string:

natas18” and password like “________________________________” collate latin1_general_cs and sleep(7)#

This alters the query to search for a 32 character string in the password column as well as allowing for case sensitive queries.  This is required as Natas level passwords have so far consisted of 32 upper and lowercase alphanumeric characters. However, it is the final condition, sleep(7) that enables a blind SQL injection attack.

As previousy discussed, no output or response from the database is returned by this page.  Therefore, the only way to determine if a query has returned valid results is to delay the database response by a given number of seconds using the sleep() command.  The hash character at the end comments out one of the double quotes at the end to allow for correct SQL syntax.

We now have sufficient conditions to brute force the password, this can be done manually by testing one alphanumeric character at a time and observing the 7 second delay. However, this is certainly not the most efficient approach and we are better off writing a Python script to automate it (click to enlarge):

natas19python

Executing our script outputs the valid password characters on at a time as they are found followed by the complete password:

scriptoutput

Advertisements

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