Testing for SQL Injection (OTG-INPVAL-005)

[Up]

Brief Summary
An SQL injection attack consists to insert or "inject" an SQL query through the input data from the client to the application. A successful sql injection could read sensitive data from the database, to modify the values, to execute administration operations on the database (such shutdown the DBMS) or to recover the content of a given file present on the DBMS filesystem.

Description of the Issue
Three classes of SQL Injection exist: inband, out-of-band and inferential type. The type inband uses the same channel of the attack in order to receive the information, the channel out-of-band uses an external channel regarding that one used for the attack to receive the information (for example taking advantage of other protocols of communication, like as smtp protocol), at last the inferential uses inferential methods for being able to gain the wished value. We can find an sql injection vulnerability generally through the presence of particular error messages, products as a result of the tests carry out from the tester. However in some cases the application is written in such way that return one customized error page. In this case we'll speak about Blind Sql Injection. Extending such meant, we can suppose be found in presence of a sql injection vulnerability of type blind in those cases in which, we are not in degree, through the analysis of the page, to got some useful information.

Standard Sql Injection Attack
Consider the following sql query:

SELECT * FROM Users WHERE Username='$username' AND Password='$password'

A query enough similar is generally used from the web applications in order to authenticate a user. If the query returns a value it means that inside the database a user with that credentials exists, then the user is allowed to login the system, otherwise the access is denied. The values of the input fields are inserted from the user generally through a web form. We suppose to insert the following Username and Password values:

$username = 1' or '1' = '1 $password = 1' or '1' = '1

The query will be:

SELECT * FROM Users WHERE Username=  OR '1' = '1' AND Password=  OR '1' = '1'

Supposing that the values of the parameters are sent to the server through the GET method, and supposing that the domain of the vulnerable web site is www.example.com, the request that we'll carry out will be:

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1

After a short analysis we notice that the query return a value (or a series of values) because the condition is always true. In this way the system has authenticated the user without knowing the username and password. We consider another query, similar to the previous one, but more similar to the query really used in the web applications for the user authentication:

SELECT * FROM Users WHERE ((Username='$username') AND (Password=MD5 ('$password')))

In this case, there are two problems, one due to the use of the parentheses and one due to the use of MD5 hash function. First of all we resolve the problem of the parenthesis. That simply consist of adding a number of closing parenthesis until when we'll obtain a corrected query. To resolve the second problem we try to invalidate the second condition. We add to our query a final symbol that means that a comment is beginning. In this way everything that follows such symbol is considered as a comment. Every DBMS has the own symbols of comment, however a common symbol to the greater part of the database is /*. Saying this, the values that we'll use as Username and Password are:

$username = 1' or '1' = '1'))/* $password = foo

In this way we'll get the following query:

SELECT * FROM Users WHERE ((Username='1' or '1' = '1'))/*') AND (Password=MD5 ('$password')))

The url request will be:

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))/*&password=foo

Which return a number of values. Sometimes, the authentication code verify that the number of returned tuple is exactly equal to 1. In the previous examples, this situation will be difficult (in the database there is only one value). In order to go around to this problem, it is enough to insert a sql command, that it imposes that the number of the returned tuple must be one In order to make this, we use the command "LIMIT ", where is the number of the tuple that have to be returned. The values of the fields of Username and Password regarding the previous example will be modified according the following way:

$username = 1' or '1' = '1')) LIMIT 1/* $password = foo

Producing a request like the follow:

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))%20LIMIT%201/*&password=foo

Union Query Sql Injection Attack
Another test to carry out, regards uses of the UNION operation. Through such operation is possible, in case of Sql Injection vulnerability, to join a query, purposely forged from the tester, to the original query. The result of the forget query will be joined to the result of the original query, allowing the tester to obtain the values of fields of other tables. We suppose for our examples that the query executed from the server is the following:

SELECT Name, Phone, Address FROM Users WHERE Id=$id

We will set the following Id value:

$id=1 UNION ALL SELECT crediNumber,1,1 FROM CreditCarTable

We got the following query:

SELECT Name, Phone, Address FROM Users WHERE Id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable

which will join the result of the original query whit all the users credi card. The keyword ALL is necessary to go around the query that make use of keyword DISTINCT Moreover we notice that beyond the credit card numbers, we have selected other two values without meant. This is necessary, because the two query must have an equal number of parameters, pain the raising of a Syntax Error.

Blind Sql Injection
TO-DO