<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.owasp.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Muhaimin+Dzulfakar</id>
		<title>OWASP - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.owasp.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Muhaimin+Dzulfakar"/>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php/Special:Contributions/Muhaimin_Dzulfakar"/>
		<updated>2026-04-28T10:07:46Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.2</generator>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Testing_for_SQL_Injection_(OTG-INPVAL-005)&amp;diff=68826</id>
		<title>Testing for SQL Injection (OTG-INPVAL-005)</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Testing_for_SQL_Injection_(OTG-INPVAL-005)&amp;diff=68826"/>
				<updated>2009-09-14T14:03:44Z</updated>
		
		<summary type="html">&lt;p&gt;Muhaimin Dzulfakar: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:OWASP Testing Guide v3}}&lt;br /&gt;
&lt;br /&gt;
== Brief Summary ==&lt;br /&gt;
&lt;br /&gt;
An [[SQL injection]] attack consists of insertion or &amp;quot;injection&amp;quot; of a SQL query via the input data from the client to the application. A successful SQL injection exploit can read sensitive data from the database, modify database data (Insert/Update/Delete), execute administration operations on the database (such as shutdown the DBMS), recover the content of a given file existing on the DBMS file system and, in some cases, issue commands to the operating system. &lt;br /&gt;
SQL injection attacks are a type of  [[Top 10 2007-Injection Flaws | injection attack]], in which SQL commands are injected into data-plane input in order to affect the execution of predefined SQL commands.&lt;br /&gt;
&lt;br /&gt;
==Related Security Activities==&lt;br /&gt;
&lt;br /&gt;
===Description of SQL Injection Vulnerabilities===&lt;br /&gt;
&lt;br /&gt;
See the OWASP article on [[SQL Injection]] Vulnerabilities.&lt;br /&gt;
&lt;br /&gt;
See the OWASP article on [[Blind_SQL_Injection]] Vulnerabilities.&lt;br /&gt;
&lt;br /&gt;
===How to Avoid SQL Injection Vulnerabilities===&lt;br /&gt;
&lt;br /&gt;
See the [[:Category:OWASP Guide Project|OWASP Development Guide]] article on how to [[Guide to SQL Injection | Avoid SQL Injection]] Vulnerabilities.&lt;br /&gt;
&lt;br /&gt;
See the [[:Category:OWASP Code Review Project|OWASP Code Review Guide]] article on how to [[Reviewing Code for SQL Injection|Review Code for SQL Injection]] Vulnerabilities.&lt;br /&gt;
&lt;br /&gt;
See the OWASP Prevention Cheat Sheet Series article on [[SQL Injection Prevention Cheat Sheet | Preventing SQL Injection]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Security Focus Area]]&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
==  Description of the Issue ==&lt;br /&gt;
SQL Injection attacks can be divided into the following three classes:&lt;br /&gt;
* Inband: data is extracted using the same channel that is used to inject the SQL code. This is the most straightforward kind of attack, in which the retrieved data is presented directly in the application web page.&lt;br /&gt;
* Out-of-band: data is retrieved using a different channel (e.g., an email with the results of the query is generated and sent to the tester).&lt;br /&gt;
* Inferential: there is no actual transfer of data, but the tester is able to reconstruct the information by sending particular requests and observing the resulting behaviour of the DB Server.&lt;br /&gt;
&lt;br /&gt;
Independent of the attack class, a successful SQL Injection attack requires the attacker to craft a syntactically correct SQL Query. If the application returns an error message generated by an incorrect query, then it is easy to reconstruct the logic of the original query and, therefore, understand how to perform the injection correctly. However, if the application hides the error details, then the tester must be able to reverse engineer the logic of the original query. The latter case is known as &amp;quot;[[Blind SQL Injection]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==  Black Box testing and example == &lt;br /&gt;
&lt;br /&gt;
=== SQL Injection Detection ===&lt;br /&gt;
&lt;br /&gt;
The first step in this test is to understand when our application connects to a DB Server in order to access some data. Typical examples of cases when an application needs to talk to a DB include:&lt;br /&gt;
* Authentication forms: when authentication is performed using a web form, chances are that the user credentials are checked against a database that contains all usernames and passwords (or, better, password hashes)&lt;br /&gt;
* Search engines: the string submitted by the user could be used in a SQL query that extracts all relevant records from a database&lt;br /&gt;
* E-Commerce sites: the products and their characteristics (price, description, availability, ...) are very likely to be stored in a relational database.&lt;br /&gt;
The tester has to make a list of all input fields whose values could be used in crafting a SQL query, including the hidden fields of POST requests and then test them separately, trying to interfere with the query and to generate an error.&lt;br /&gt;
The very first test usually consists of adding a single quote (') or a semicolon (;) to the field under test. The first is used in SQL as a string terminator and, if not filtered by the application, would lead to an incorrect query. The second is used to end a SQL statement and, if it is not filtered, it is also likely to generate an error. &lt;br /&gt;
The output of a vulnerable field might resemble the following (on a Microsoft SQL Server, in this case):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'&lt;br /&gt;
[Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation mark before the &lt;br /&gt;
character string ''.&lt;br /&gt;
/target/target.asp, line 113&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Also comments (--) and other SQL keywords like 'AND' and 'OR' can be used to try to modify the query. A very simple but sometimes still effective technique is simply to insert a string where a number is expected, as an error like the following might be generated:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Microsoft OLE DB Provider for ODBC Drivers error '80040e07'&lt;br /&gt;
 [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the&lt;br /&gt;
 varchar value 'test' to a column of data type int.&lt;br /&gt;
 /target/target.asp, line 113&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A full error message, like those in the examples, provides a wealth of information to the tester in order to mount a successful injection. However, applications often do not provide so much detail: a simple '500 Server Error' or a custom error page might be issued, meaning that we need to use blind injection techniques.&lt;br /&gt;
In any case, it is very important to test *each field separately*: only one variable must vary while all the other remain constant, in order to precisely understand which parameters are vulnerable and which are not.&lt;br /&gt;
&lt;br /&gt;
=== Standard SQL Injection Testing ===&lt;br /&gt;
&lt;br /&gt;
Consider the following SQL query:&lt;br /&gt;
&lt;br /&gt;
 SELECT * FROM Users WHERE Username='$username' AND Password='$password' &lt;br /&gt;
&lt;br /&gt;
A similar query is generally used from the web application 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 to the system, otherwise the access is denied.&lt;br /&gt;
The values of the input fields are generally obtained from the user through a web form. &lt;br /&gt;
Suppose we insert the following Username and Password values: &lt;br /&gt;
&lt;br /&gt;
 $username = 1' or '1' = '1&lt;br /&gt;
 $password = 1' or '1' = '1&lt;br /&gt;
&lt;br /&gt;
The query will be: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;SELECT * FROM Users WHERE Username='1' OR '1' = '1' AND Password='1' OR '1' = '1'&amp;lt;/nowiki&amp;gt; &lt;br /&gt;
If we suppose that the values of the parameters are sent to the server through the GET method, and if the domain of the vulnerable web site is www.example.com, the request that we'll carry out will be:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&amp;amp;password=1'%20or%20'1'%20=%20'1 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After a short analysis we notice that the query returns a value (or a set of values) because the  condition is always true (OR 1=1). In this way the system has authenticated the user without knowing the username and password.&amp;lt;BR&amp;gt; ''In some systems the first row of a user table would be an administrator user. This may be the profile returned in some cases.''&lt;br /&gt;
Another example of query is the following: &lt;br /&gt;
&lt;br /&gt;
 SELECT * FROM Users WHERE ((Username='$username') AND (Password=MD5('$password'))) &lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
First of all, we resolve the problem of the parentheses. &lt;br /&gt;
That simply consists of adding a number of closing parentheses until we obtain a corrected query. To resolve the second problem, we try to invalidate the second condition.&lt;br /&gt;
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 a comment.&lt;br /&gt;
Every DBMS has its own symbols of comment, however, a common symbol to the greater part of the database is /*. In Oracle the symbol is &amp;quot;--&amp;quot;.&lt;br /&gt;
This said, the values that we'll use as Username and Password are: &lt;br /&gt;
&lt;br /&gt;
 $username = 1' or '1' = '1'))/*&lt;br /&gt;
 $password = foo&lt;br /&gt;
&lt;br /&gt;
In this way, we'll get the following query: &lt;br /&gt;
&lt;br /&gt;
 SELECT * FROM Users WHERE ((Username='1' or '1' = '1'))/*') AND (Password=MD5('$password'))) &lt;br /&gt;
&lt;br /&gt;
The URL request will be:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))/*&amp;amp;password=foo &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which returns a number of values. Sometimes, the authentication code verifies that the number of returned tuple is exactly equal to 1. In the previous examples, this situation would be difficult (in the database there is only one value per user). &lt;br /&gt;
In order to go around this problem, it is enough to insert a SQL command that imposes the condition that the number of the returned tuple must be one. (One record returned)&lt;br /&gt;
In order to reach this goal, we use the operator &amp;quot;LIMIT &amp;lt;num&amp;gt;&amp;quot;, where &amp;lt;num&amp;gt; is the number of the tuples that we expect to be returned. With respect to the previous example, the value of the fields Username and Password will be modified as follows:&lt;br /&gt;
&lt;br /&gt;
 $username = 1' or '1' = '1')) LIMIT 1/* &lt;br /&gt;
 $password = foo &lt;br /&gt;
&lt;br /&gt;
In this way, we create a request like the follow:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))%20LIMIT%201/*&amp;amp;password=foo &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Union Query SQL Injection Testing ===&lt;br /&gt;
Another test involves the use of the UNION operator. This operator is used in SQL injections to join a query, purposely forged by the tester, to the original query. The result of the forged query will be joined to the result of the original query, allowing the tester to obtain the values of fields of other tables.&lt;br /&gt;
We suppose for our examples that the query executed from the server is the following: &lt;br /&gt;
&lt;br /&gt;
 SELECT Name, Phone, Address FROM Users WHERE Id=$id &lt;br /&gt;
&lt;br /&gt;
We will set the following Id value: &lt;br /&gt;
&lt;br /&gt;
 $id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable&lt;br /&gt;
&lt;br /&gt;
We will have the following query: &lt;br /&gt;
&lt;br /&gt;
 SELECT Name, Phone, Address FROM Users WHERE Id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable &lt;br /&gt;
&lt;br /&gt;
which will join the result of the original query with all the credit card users. &lt;br /&gt;
The keyword '''ALL''' is necessary to get around queries that use the keyword DISTINCT. &lt;br /&gt;
Moreover, we notice that beyond the credit card numbers, we have selected other two values. These two values are necessary, because the two query must have an equal number of parameters, in order to avoid a syntax error.&lt;br /&gt;
&lt;br /&gt;
=== Blind SQL Injection Testing ===&lt;br /&gt;
We have pointed out that there is another category of SQL injection, called [[Blind SQL Injection]], in which nothing is known on the outcome of an operation. For example, this behavior happens in cases where the programmer has created a custom error page that does not reveal anything on the structure of the query or on the database. (The page does not return a SQL error, it may just return a HTTP 500).&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
By using the inference methods, it is possible to avoid this obstacle and thus to succeed to recover the values of some desired fields. This method consists of carrying out a series of boolean queries to the server, observing the answers and finally deducing the meaning of such answers.&lt;br /&gt;
We consider, as always, the www.example.com domain and we suppose that it contains a parameter named id vulnerable to SQL injection.&lt;br /&gt;
This means that carrying out the following request: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;http://www.example.com/index.php?id=1' &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
we will get one page with a custom message error which is due to a syntactic error in the query. We suppose that the query executed on the server is: &lt;br /&gt;
&lt;br /&gt;
 SELECT field1, field2, field3 FROM Users WHERE Id='$Id' &lt;br /&gt;
&lt;br /&gt;
which is exploitable through the methods seen previously. &lt;br /&gt;
What we want to obtain is the values of the username field. The tests that we will execute will allow us to obtain the value of the username field, extracting such value character by character. This is possible through the use of some standard functions, present practically in every database. For our examples, we will use the following pseudo-functions: &lt;br /&gt;
&lt;br /&gt;
'''SUBSTRING (text, start, length)''': it returns a substring starting from the position &amp;quot;start&amp;quot; of text and of length &amp;quot;length&amp;quot;. If &amp;quot;start&amp;quot; is greater than the length of text, the function returns a null value. &lt;br /&gt;
&lt;br /&gt;
'''ASCII (char)''': it gives back ASCII value of the input character. A null value is returned if char is 0.&lt;br /&gt;
&lt;br /&gt;
'''LENGTH (text)''': it gives back the length in characters of the input text.&lt;br /&gt;
&lt;br /&gt;
Through such functions, we will execute our tests on the first character and, when we have discovered the value, we will pass to the second and so on, until we will have discovered the entire value. &lt;br /&gt;
The tests will take advantage of the function SUBSTRING, in order to select only one character at a time (selecting a single character means to impose the length parameter to 1), and the function ASCII, in order to obtain the ASCII value, so that we can do numerical comparison. The results of the comparison will be done with all the values of the ASCII table, until the right value is found.&lt;br /&gt;
As an example, we will use the following value for ''Id'': &lt;br /&gt;
&lt;br /&gt;
 $Id=1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1 &lt;br /&gt;
&lt;br /&gt;
that creates the following query (from now on, we will call it &amp;quot;inferential query&amp;quot;): &lt;br /&gt;
&lt;br /&gt;
 SELECT field1, field2, field3 FROM Users WHERE Id='1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1'&lt;br /&gt;
&lt;br /&gt;
The previous example returns a result if and only if the first character of the field username is equal to the ASCII value 97. If we get a false value, then we increase the index of the ASCII table from 97 to 98 and we repeat the request. If instead we obtain a true value, we set to zero the index of the ASCII table and we analyze the next character, modifying the parameters of the SUBSTRING function.&lt;br /&gt;
The problem is to understand in which way we can distinguish tests returning a true value from those that return false.&lt;br /&gt;
To do this, we create a query that always returns false. &lt;br /&gt;
This is possible by using the following value for ''Id'': &lt;br /&gt;
&lt;br /&gt;
 $Id=1' AND '1' = '2 &lt;br /&gt;
&lt;br /&gt;
by which will create the following query: &lt;br /&gt;
&lt;br /&gt;
 SELECT field1, field2, field3 FROM Users WHERE Id='1' AND '1' = '2' &lt;br /&gt;
&lt;br /&gt;
The obtained response from the server (that is HTML code) will be the false value for our tests. &lt;br /&gt;
This is enough to verify whether the value obtained from the execution of the inferential query is equal to the value obtained with the test executed before. &lt;br /&gt;
Sometimes, this method does not work. If the server returns two different pages as a result of two identical consecutive web requests, we will not be able to discriminate the true value from the false value. In these particular cases, it is necessary to use particular filters that allow us to eliminate the code that changes between the two requests and to obtain a template. Later on, for every inferential request executed, we will extract the relative template from the response using the same function, and we will perform a control between the two templates in order to decide the result of the test.&lt;br /&gt;
&lt;br /&gt;
In the previous discussion, we haven't dealt with the problem of determining the termination condition for out tests, i.e., when we should end the inference procedure. &lt;br /&gt;
A techniques to do this uses one characteristic of the SUBSTRING function and the LENGTH function.&lt;br /&gt;
When the test compares the current character with the ASCII code 0 (i.e., the value null) and the test returns the value true, then either we are done with the inference procedue (we have scanned the whole string), or the value we have analyzed contains the null character.&lt;br /&gt;
&lt;br /&gt;
We will insert the following value for the field ''Id'': &lt;br /&gt;
&lt;br /&gt;
 $Id=1' AND LENGTH(username)=N AND '1' = '1 &lt;br /&gt;
&lt;br /&gt;
Where N is the number of characters that we have analyzed up to now (not counting the null value). &lt;br /&gt;
The query will be: &lt;br /&gt;
&lt;br /&gt;
 SELECT field1, field2, field3 FROM Users WHERE Id='1' AND LENGTH(username)=N AND '1' = '1' &lt;br /&gt;
&lt;br /&gt;
The query returns either true or false. If we obtain true, then we have completed inference and, therefore, we know the value of the parameter. If we obtain false, this means that the null character is present in the value of the parameter, and we must continue to analyze the next parameter until we find another null value.&lt;br /&gt;
&lt;br /&gt;
The blind SQL injection attack needs a high volume of queries. The tester may need an automatic tool to exploit the vulnerability.&lt;br /&gt;
A simple tool which performs this task, via GET requests on the MySql DB, is SqlDumper, which is shown below.&lt;br /&gt;
&lt;br /&gt;
[[Image:sqldumper.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Stored Procedure Injection ===&lt;br /&gt;
Question: How can the risk of SQL injection be eliminated? &amp;lt;br&amp;gt;&lt;br /&gt;
Answer: Stored procedures.&amp;lt;br&amp;gt;&lt;br /&gt;
I have seen this answer too many times without qualifications.  Merely the use of stored procedures does not assist in the mitigation of SQL injection.  If not handled properly, dynamic SQL within stored procedures can be just as vulnerable to SQL injection as dynamic SQL within a web page.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
When using dynamic SQL within a stored procedure, the application must properly sanitize the user input to eliminate the risk of code injection.  If not sanitized, the user could enter malicious SQL that will be executed within the stored procedure.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Black box testing uses SQL injection to compromise the system. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Consider the following &amp;lt;b&amp;gt;SQL Server Stored Procedure:&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
 Create procedure user_login @username varchar(20), @passwd varchar(20) As&lt;br /&gt;
 Declare @sqlstring varchar(250) &lt;br /&gt;
 Set @sqlstring  = ‘&lt;br /&gt;
 Select 1 from users &lt;br /&gt;
 Where username = ‘ + @username + ‘ and passwd = ‘ + @passwd&lt;br /&gt;
 exec(@sqlstring)&lt;br /&gt;
 Go&lt;br /&gt;
User input: &amp;lt;br&amp;gt;&lt;br /&gt;
 anyusername or 1=1'&lt;br /&gt;
 anypassword&lt;br /&gt;
This procedure does not sanitize the input, therefore allowing the return value to show an existing record with these parameters.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
NOTE:  This example may seem unlikely due to the use of dynamic SQL to log in a user, but consider a dynamic reporting query where the user selects the columns to view. The user could insert malicious code into this scenario and compromise the data.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Consider the following &amp;lt;b&amp;gt;SQL Server Stored Procedure:&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
 Create procedure get_report @columnamelist varchar(7900) As&lt;br /&gt;
 Declare @sqlstring varchar(8000) &lt;br /&gt;
 Set @sqlstring  = ‘&lt;br /&gt;
 Select ‘ + @columnamelist + ‘ from ReportTable‘&lt;br /&gt;
 exec(@sqlstring) &lt;br /&gt;
 Go&lt;br /&gt;
User input: &amp;lt;br&amp;gt;&lt;br /&gt;
 1 from users; update users set password = 'password'; select *&lt;br /&gt;
&lt;br /&gt;
This will result in the report running and all users’ passwords being updated.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Articles ==&lt;br /&gt;
&lt;br /&gt;
* [[Top 10 2007-Injection Flaws]]&lt;br /&gt;
* [[SQL Injection]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Technology specific Testing Guide pages have been created for the following DBMSs:&lt;br /&gt;
&lt;br /&gt;
* [[Testing for Oracle| Oracle]]&lt;br /&gt;
* [[Testing for MySQL| MySQL]]&lt;br /&gt;
* [[Testing for SQL Server  | SQL Server]]&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
'''Whitepapers'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Victor Chapela: &amp;quot;Advanced SQL Injection&amp;quot; - http://www.owasp.org/images/7/74/Advanced_SQL_Injection.ppt&lt;br /&gt;
* Chris Anley: &amp;quot;Advanced SQL Injection In SQL Server Applications&amp;quot; - http://www.nextgenss.com/papers/advanced_sql_injection.pdf&lt;br /&gt;
* Chris Anley: &amp;quot;More Advanced SQL Injection&amp;quot; - http://www.nextgenss.com/papers/more_advanced_sql_injection.pdf&lt;br /&gt;
* David Litchfield: &amp;quot;Data-mining with SQL Injection and Inference&amp;quot; - http://www.nextgenss.com/research/papers/sqlinference.pdf&lt;br /&gt;
* Imperva: &amp;quot;Blind SQL Injection&amp;quot; - http://www.imperva.com/application_defense_center/white_papers/blind_sql_server_injection.html&lt;br /&gt;
* Ferruh Mavituna: &amp;quot;SQL Injection Cheat Sheet&amp;quot; - http://ferruh.mavituna.com/makale/sql-injection-cheatsheet/&lt;br /&gt;
&lt;br /&gt;
'''Tools'''&amp;lt;br&amp;gt;&lt;br /&gt;
* [[:Category:OWASP SQLiX Project|OWASP SQLiX]]&lt;br /&gt;
* Francois Larouche: Multiple DBMS SQL Injection tool - [http://www.sqlpowerinjector.com/index.htm SQL Power Injector]&amp;lt;br&amp;gt;&lt;br /&gt;
* ilo--:  MySql Blind Injection Bruteforcing, Reversing.org - [http://www.reversing.org/node/view/11 sqlbftools]&amp;lt;br&amp;gt;&lt;br /&gt;
* Bernardo Damele A. G.: sqlmap, automatic SQL injection tool - http://sqlmap.sourceforge.net&lt;br /&gt;
* icesurfer: SQL Server Takeover Tool - [http://sqlninja.sourceforge.net sqlninja]&lt;br /&gt;
* Pangolin: Automated SQL Injection Tool - [http://www.nosec.org/en/pangolin.html Pangolin]&lt;br /&gt;
* Muhaimin Dzulfakar: MySqloit, MySql Injection takeover tool - http://code.google.com/p/mysqloit/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:FIXME|broken links&lt;br /&gt;
&lt;br /&gt;
* Kevin Spett: &amp;quot;SQL Injection&amp;quot; - http://www.spidynamics.com/papers/SQLInjectionWhitePaper.pdf&lt;br /&gt;
* Kevin Spett: &amp;quot;Blind SQL Injection&amp;quot; - http://www.spidynamics.com/whitepapers/Blind_SQLInjection.pdf&lt;br /&gt;
&lt;br /&gt;
* Antonio Parata: Dump Files by SQL inference on Mysql - [http://www.ictsc.it/site/IT/projects/sqlDumper/sqldumper.src.tar.gz SqlDumper]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
]]&lt;/div&gt;</summary>
		<author><name>Muhaimin Dzulfakar</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Testing_for_MySQL&amp;diff=68825</id>
		<title>Testing for MySQL</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Testing_for_MySQL&amp;diff=68825"/>
				<updated>2009-09-14T14:00:42Z</updated>
		
		<summary type="html">&lt;p&gt;Muhaimin Dzulfakar: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[http://www.owasp.org/index.php/Web_Application_Penetration_Testing_AoC Up]]&amp;lt;br&amp;gt;&lt;br /&gt;
{{Template:OWASP Testing Guide v3}}&lt;br /&gt;
&lt;br /&gt;
== Short Description of the Issue == &lt;br /&gt;
[[SQL Injection]] vulnerabilities occur whenever input is used in the construction of a SQL query without being adequately constrained or sanitized. The use of dynamic SQL (the construction of SQL queries by concatenation of strings) opens the door to these vulnerabilities. SQL injection allows an attacker to access the SQL servers. It allows for the execution of SQL code under the privileges of the user used to connect to the database.&lt;br /&gt;
&lt;br /&gt;
''MySQL server'' has a few particularities so that some exploits need to be &lt;br /&gt;
specially customized for this application. That's the subject of this section.&lt;br /&gt;
&lt;br /&gt;
== Black Box testing and example ==&lt;br /&gt;
&lt;br /&gt;
=== How to Test ===&lt;br /&gt;
When an SQL injection vulnerability is found in an application backed by a MySQL database,&lt;br /&gt;
there are a number of attacks that could be performed depending &lt;br /&gt;
on the MySQL version and user privileges on DBMS.&lt;br /&gt;
&lt;br /&gt;
MySQL comes with at least four versions which are used in production worldwide.&lt;br /&gt;
3.23.x, 4.0.x, 4.1.x and 5.0.x.&lt;br /&gt;
Every version has a set of features proportional to version number.&lt;br /&gt;
&lt;br /&gt;
* From Version 4.0: UNION &lt;br /&gt;
* From Version 4.1: Subqueries&lt;br /&gt;
* From Version 5.0: Stored procedures, Stored functions and the view named INFORMATION_SCHEMA&lt;br /&gt;
* From Version 5.0.2: Triggers &lt;br /&gt;
&lt;br /&gt;
It should be noted that for MySQL versions before 4.0.x, only Boolean or time-based Blind Injection attacks could be used, since the subquery functionality or UNION statements were not implemented.&lt;br /&gt;
&lt;br /&gt;
From now on, we will assume that there is a classic SQL injection vulnerability, which can be triggered by a request similar to the the one described in the Section on [[Testing for SQL Injection  (OWASP-DV-005)|Testing for SQL Injection]].&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;http://www.example.com/page.php?id=2&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Single Quotes Problem ===&lt;br /&gt;
Before taking advantage of MySQL features, &lt;br /&gt;
it has to be taken in consideration how strings could be represented&lt;br /&gt;
in a statement, as often web applications escape single quotes.&lt;br /&gt;
&lt;br /&gt;
MySQL quote escaping is the following:&amp;lt;br&amp;gt;&lt;br /&gt;
''' &amp;lt;nowiki&amp;gt;'A string with \'quotes\''&amp;lt;/nowiki&amp;gt; '''&lt;br /&gt;
&lt;br /&gt;
That is, MySQL interprets escaped apostrophes (\') as characters and not as&lt;br /&gt;
metacharacters.&lt;br /&gt;
&lt;br /&gt;
So if the application, to work properly, needs to use constant strings,&lt;br /&gt;
two cases are to be differentiated: &lt;br /&gt;
# Web app escapes single quotes (' =&amp;gt; \')&lt;br /&gt;
# Web app does not escape single quotes (' =&amp;gt; ')&lt;br /&gt;
&lt;br /&gt;
Under MySQL, there is a standard way to bypass the need of single quotes, having a constant string to be declared without the need for single quotes.&lt;br /&gt;
&lt;br /&gt;
Let's suppose we want to know the value of a field named 'password' in a record,&lt;br /&gt;
with a condition like the following:&lt;br /&gt;
password like 'A%'&lt;br /&gt;
&lt;br /&gt;
# The ASCII values in a concatenated hex:&amp;lt;br&amp;gt;&lt;br /&gt;
#: password LIKE 0x4125&lt;br /&gt;
# The char() function:&lt;br /&gt;
#: password LIKE CHAR(65,37)&lt;br /&gt;
&lt;br /&gt;
=== Multiple mixed queries: ===&lt;br /&gt;
&lt;br /&gt;
MySQL library connectors do not support multiple queries separated&lt;br /&gt;
by '''&amp;lt;nowiki&amp;gt;';'&amp;lt;/nowiki&amp;gt;''' so there's no way to inject multiple non-homogeneous SQL commands inside a single SQL injection vulnerability like in Microsoft SQL Server.&lt;br /&gt;
&lt;br /&gt;
For example the following injection will result in an error:&lt;br /&gt;
&lt;br /&gt;
 1 ; update tablename set code='javascript code' where 1 --&lt;br /&gt;
&lt;br /&gt;
=== Information gathering ===&lt;br /&gt;
&lt;br /&gt;
==== Fingerprinting MySQL ====&lt;br /&gt;
&lt;br /&gt;
Of course, the first thing to know is if there's MySQL DBMS as a backend.&lt;br /&gt;
&lt;br /&gt;
MySQL server has a feature that is used to let other DBMS ignore a clause in MySQL&lt;br /&gt;
dialect. When a comment block ''('/**/')'' contains an exlamation mark ''('/*! sql here*/')'' it is interpreted by MySQL, and is considered as a normal comment block by other DBMS&lt;br /&gt;
as explained in [http://dev.mysql.com/doc/refman/5.0/en/comments.html MySQL manual].&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 1 /*! and 1=0 */&lt;br /&gt;
&lt;br /&gt;
'''Result Expected:'''&amp;lt;br&amp;gt;&lt;br /&gt;
''If MySQL is present, the clause inside the comment block will be interpreted.''&lt;br /&gt;
&lt;br /&gt;
==== Version ====&lt;br /&gt;
&lt;br /&gt;
There are three ways to gain this information:&lt;br /&gt;
# By using the global variable @@version&lt;br /&gt;
# By using the function [[http://dev.mysql.com/doc/refman/5.0/en/information-functions.html VERSION()]]&lt;br /&gt;
# By using comment fingerprinting with a version number /*!40110 and 1=0*/&lt;br /&gt;
#: which means &lt;br /&gt;
 &amp;lt;nowiki&amp;gt;if(version &amp;gt;= 4.1.10) &lt;br /&gt;
   add 'and 1=0' to the query.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These are equivalent as the result is the same.&lt;br /&gt;
&lt;br /&gt;
In band injection:&lt;br /&gt;
&lt;br /&gt;
 1 AND 1=0 UNION SELECT @@version /*&lt;br /&gt;
&lt;br /&gt;
Inferential injection:&lt;br /&gt;
&lt;br /&gt;
 1 AND @@version like '4.0%'&lt;br /&gt;
&lt;br /&gt;
'''Result Expected:'''&amp;lt;br&amp;gt;&lt;br /&gt;
''A string like this: '''5.0.22-log''' ''&lt;br /&gt;
&lt;br /&gt;
==== Login User ====&lt;br /&gt;
&lt;br /&gt;
There are two kinds of users MySQL Server relies upon.&lt;br /&gt;
# [[http://dev.mysql.com/doc/refman/5.0/en/information-functions.html USER()]]: the user connected to the MySQL Server.&lt;br /&gt;
# [[http://dev.mysql.com/doc/refman/5.0/en/information-functions.html CURRENT_USER()]]: the internal user who is executing the query.&lt;br /&gt;
&lt;br /&gt;
There is some difference between 1 and 2.&lt;br /&gt;
&lt;br /&gt;
The main one is that an anonymous user could connect (if allowed)&lt;br /&gt;
with any name, but the MySQL internal user is an empty name (&amp;lt;nowiki&amp;gt;''&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Another difference is that a stored procedure or a stored function&lt;br /&gt;
are executed as the creator user, if not declared elsewhere. This &lt;br /&gt;
can be known by using '''CURRENT_USER'''.&lt;br /&gt;
&lt;br /&gt;
In band injection:&lt;br /&gt;
&lt;br /&gt;
 1 AND 1=0 UNION SELECT USER() &lt;br /&gt;
&lt;br /&gt;
Inferential injection:&lt;br /&gt;
&lt;br /&gt;
 1 AND USER() like 'root%'&lt;br /&gt;
&lt;br /&gt;
'''Result Expected:'''&amp;lt;br&amp;gt;&lt;br /&gt;
''A string like this: '''user@hostname''' ''&lt;br /&gt;
&lt;br /&gt;
==== Database name in use ====&lt;br /&gt;
&lt;br /&gt;
There is the native function DATABASE()&lt;br /&gt;
&lt;br /&gt;
In band injection:&lt;br /&gt;
&lt;br /&gt;
 1 AND 1=0 UNION SELECT DATABASE() &lt;br /&gt;
&lt;br /&gt;
Inferential injection:&lt;br /&gt;
&lt;br /&gt;
 1 AND DATABASE() like 'db%'&lt;br /&gt;
&lt;br /&gt;
'''Result Expected:'''&amp;lt;br&amp;gt;&lt;br /&gt;
''A string like this: '''dbname''' ''&lt;br /&gt;
&lt;br /&gt;
==== INFORMATION_SCHEMA ====&lt;br /&gt;
From MySQL 5.0 a view named [[http://dev.mysql.com/doc/refman/5.0/en/information-schema.html INFORMATION_SCHEMA]] was created.&lt;br /&gt;
It allows us to get all informations about databases, tables, and columns,&lt;br /&gt;
as well as procedures and functions.&lt;br /&gt;
&lt;br /&gt;
Here is a summary of some interesting Views.&lt;br /&gt;
{| border=1&lt;br /&gt;
 || '''Tables_in_INFORMATION_SCHEMA''' || '''DESCRIPTION'''&lt;br /&gt;
|-&lt;br /&gt;
|| ..[skipped]..|| ..[skipped].. &lt;br /&gt;
|-&lt;br /&gt;
|| SCHEMATA || All databases the user has (at least) SELECT_priv &lt;br /&gt;
|-&lt;br /&gt;
|| SCHEMA_PRIVILEGES || The privileges the user has for each DB&lt;br /&gt;
|-&lt;br /&gt;
|| TABLES || All tables  the user has (at least) SELECT_priv&lt;br /&gt;
|-&lt;br /&gt;
|| TABLE_PRIVILEGES || The privileges the user has for each table&lt;br /&gt;
|-&lt;br /&gt;
|| COLUMNS || All columns  the user has (at least) SELECT_priv&lt;br /&gt;
|-&lt;br /&gt;
|| COLUMN_PRIVILEGES || The privileges the user has for each column&lt;br /&gt;
|-&lt;br /&gt;
|| VIEWS || All columns  the user has (at least) SELECT_priv&lt;br /&gt;
|-&lt;br /&gt;
|| ROUTINES || Procedures and functions (needs EXECUTE_priv)&lt;br /&gt;
|-&lt;br /&gt;
|| TRIGGERS || Triggers (needs INSERT_priv)&lt;br /&gt;
|-&lt;br /&gt;
|| USER_PRIVILEGES || Privileges connected User has&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
All of this information could be extracted by using known techniques as &lt;br /&gt;
described in SQL Injection section.&lt;br /&gt;
&lt;br /&gt;
=== Attack vectors ===&lt;br /&gt;
&lt;br /&gt;
==== Write in a File ====&lt;br /&gt;
&lt;br /&gt;
If the connected user has '''FILE''' privileges and single quotes are not escaped,&lt;br /&gt;
the 'into outfile' clause can be used to export query results in a file.&lt;br /&gt;
&lt;br /&gt;
 Select * from table into outfile '/tmp/file'&lt;br /&gt;
&lt;br /&gt;
Note: there is no way to bypass single quotes surrounding a filename. &lt;br /&gt;
So if there's some sanitization on single quotes like escape (\') there will&lt;br /&gt;
be no way to use the 'into outfile' clause.&lt;br /&gt;
&lt;br /&gt;
This kind of attack could be used as an out-of-band technique to gain information&lt;br /&gt;
about the results of a query or to write a file which could be executed inside the &lt;br /&gt;
web server directory.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;1 limit 1 into outfile '/var/www/root/test.jsp' FIELDS ENCLOSED BY '//'  LINES TERMINATED BY '\n&amp;lt;%jsp code here%&amp;gt;';&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Result Expected:'''&amp;lt;br&amp;gt;&lt;br /&gt;
'' Results are stored in a file with rw-rw-rw privileges owned by &lt;br /&gt;
MySQL user and group.&lt;br /&gt;
&lt;br /&gt;
Where ''/var/www/root/test.jsp'' will contain:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;//field values//&lt;br /&gt;
&amp;lt;%jsp code here%&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Read from a File ====&lt;br /&gt;
&lt;br /&gt;
Load_file is a native function that can read a file when allowed by &lt;br /&gt;
filesystem permissions. &lt;br /&gt;
&lt;br /&gt;
If a connected user has '''FILE''' privileges, it could be used to get the files' content.&lt;br /&gt;
&lt;br /&gt;
Single quotes escape sanitization can by bypassed by using previously described&lt;br /&gt;
techniques.&lt;br /&gt;
&lt;br /&gt;
 load_file('filename')&lt;br /&gt;
&lt;br /&gt;
'''Result Expected:'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''The whole file will be available for exporting by using standard techniques.''&lt;br /&gt;
&lt;br /&gt;
=== Standard SQL Injection Attack ===&lt;br /&gt;
&lt;br /&gt;
In a standard SQL injection you can have results displayed directly &lt;br /&gt;
in a page as normal output or as a MySQL error.&lt;br /&gt;
By using already mentioned SQL Injection attacks and the already described&lt;br /&gt;
MySQL features, direct SQL injection could be easily accomplished at a level&lt;br /&gt;
depth depending primarily on the MySQL version the pentester is facing.&lt;br /&gt;
&lt;br /&gt;
A good attack is to know the results by forcing a function/procedure&lt;br /&gt;
or the server itself to throw an error.&lt;br /&gt;
A list of errors thrown by MySQL and in particular native functions could&lt;br /&gt;
be found on [http://dev.mysql.com/doc/refman/5.0/en/error-messages-server.html MySQL Manual].&lt;br /&gt;
&lt;br /&gt;
=== Out of band SQL Injection ===&lt;br /&gt;
&lt;br /&gt;
Out of band injection could be accomplished by using the [[#Write_in_a_File|'into outfile']] clause.&lt;br /&gt;
=== Blind SQL Injection ===&lt;br /&gt;
For blind SQL injection, there is a set of useful function natively provided by MySQL server.&lt;br /&gt;
&lt;br /&gt;
* String Length: &lt;br /&gt;
*: ''LENGTH(str)''&lt;br /&gt;
* Extract a substring from a given string: &lt;br /&gt;
*: ''SUBSTRING(string, offset, #chars_returned)''&lt;br /&gt;
* Time based Blind Injection: BENCHMARK and SLEEP &lt;br /&gt;
*: ''BENCHMARK(#ofcicles,action_to_be_performed )''&lt;br /&gt;
*: The benchmark function could be used to perform timing attacks, when blind injection by boolean values does not yield any results.&lt;br /&gt;
*: See. SLEEP() (MySQL &amp;gt; 5.0.x) for an alternative on benchmark.&lt;br /&gt;
&lt;br /&gt;
For a complete list, refer to MySQL manual - http://dev.mysql.com/doc/refman/5.0/en/functions.html&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
'''Whitepapers'''&amp;lt;br&amp;gt;&lt;br /&gt;
* Chris Anley: &amp;quot;Hackproofing MySQL&amp;quot; -http://www.nextgenss.com/papers/HackproofingMySQL.pdf&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Tools'''&amp;lt;br&amp;gt;&lt;br /&gt;
* Francois Larouche: Multiple DBMS SQL Injection tool - http://www.sqlpowerinjector.com/index.htm&amp;lt;br&amp;gt;&lt;br /&gt;
* ilo--:  MySQL Blind Injection Bruteforcing, Reversing.org - http://www.reversing.org/node/view/11 sqlbftools&amp;lt;br&amp;gt;&lt;br /&gt;
* Bernardo Damele A. G.: sqlmap, automatic SQL injection tool - http://sqlmap.sourceforge.net&lt;br /&gt;
* Antonio Parata: Dump Files by SQL inference on MySQL - http://www.ictsc.it/site/IT/projects/sqlDumper/sqldumper.src.tar.gz&amp;lt;br&amp;gt;&lt;br /&gt;
* Muhaimin Dzulfakar: MySqloit, MySql Injection takeover tool - http://code.google.com/p/mysqloit/&lt;br /&gt;
&lt;br /&gt;
[[Category:FIXME|link not working&lt;br /&gt;
&lt;br /&gt;
'''Case Studies'''&amp;lt;br&amp;gt;&lt;br /&gt;
* Time Based SQL Injection Explained - http://www.f-g.it/papers/blind-zk.txt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
]]&lt;/div&gt;</summary>
		<author><name>Muhaimin Dzulfakar</name></author>	</entry>

	</feed>