Below is a summary of steps needed for testing for SQL injection bugs
- Step 1: Understand SQL injection attack scenarios
- Step 2: List high risk components and entry points
- Step 3: Start testing and exploring
- Step 4: Tune of test data
Step 4: Tune test cases data
At this point you have started executing an exploratory pass through the input variables. During step 4 you need to concentrate on covering all entry points of each variable in your variable table.
Learn type database version
Different database applications and versions process queries differently. For example SQL Server uses + to concatenate strings in a statement while Oracle uses ||. SQL Server allows execution of batched or multiple SQL commands within a statement as long as they are separated with a semicolon (;) while Oracle and MySQL forbids this. You can gather database brand and versions by scanning network ports at the server, sniffing network traffic, or looking at SQL related error messages.
Consider string format and encoding according to entry point
As you walk through the risky variables and entry points take into account the different formats that apply to each entry point. For example, this article described passing the following string to a web form:
xyz' OR 1=1 --
However, you can't pass a string like the one above in a URL since the URL doesn't allow blank spaces. Server applications use different encoding functions to transmit URL contents. They encode data and then decode it at the server end. The encoding and decoding depends on the server's programming language. For example, sometimes the encoding function replaces the blank spaces with a plus (+) sign so the string above looks like this:
In other encoding case, the server might replace the blank space with a %20. In that case, the test string will need to look like this:
This common encoding scheme consists of replacing spaces with their hexadecimal values %HH. In addition, it is recommended to also encode reserved characters such as the single quote. The encoded string will then look like this:
The Java URL encode function translates special characters using a string like this one %uXXXX where XXXX is the character´s Unicode value represented as four digits. The above string will look like this one:
There are different types of encoding mechanisms. It is important that you do a quick source review to see what encoding functions are used and then at the documentation available for the specific functions. To learn more, see "Percent Encoding".
Note: Try to use double encoding
It is important to attempt to execute double encoding cases. Double encoding is a specific encoding aimed at bypassing security controls. It consists of replacing the percent character by its hexadecimal value (25). If you are testing using single encoding like this:
Then try the following string for double encoding:
Try different syntax
SQL injection testing aims at changing the logic of the original SQL statement by adding additional ones. But for the additional statements to execute, the attacked query has to remain syntactically correct or else it will fail to execute. Consider different variants of test input to deal with the closing of quotes and parenthesis. Here are a few variations to try:
- x' or 1=1 --
- x' or 'a'='a
- x" or 1=1 #
- x%' or 1=1 --
Consider the different ways of getting test results
There are different channels to retrieve SQL injection data:
- In band - When the attacked server returns the data to the attacker using an existing channel such as a rendered table in a web page, or by logging on the user to a restricted page
- Out of band - When the attacker opens a new connection to get data from the server such as when installing a Trojan in the server, using an extended stored procedure such as xp_cmdshell to open a remote connection, or using MS SQL's OPENROWSET() to connect directly to the database.
- Inferred - When the attacked server doesn't send any data to the attacker and the attacker needs to execute his attack using alternate queries and observing error codes.
Cover the different methods of retrieving data from the server during this step.
Execute different payloads
Sometimes executing a simple true or false condition will not generate visible results. This is the main reasons why you need to try different payloads. There are hundreds of possible payloads to execute in a SQL injection attack. Most of these payloads vary between SQL server applications and can be found in the web. Just to get an idea of how different payloads can be, let's picture the case of trying to steal information from a database. The payload can vary between:
- An OR with simple condition that returns all rows (like OR 1=1)
- An UNION SELECT statement that executes and additional SELECT query and appends the results to the original result set. To learn more, see SQL Injection: Are your Web Applications Vulnerable?
- An OPENROWSET command that opens a connection to a hacker database and sends the data to the remote attacker. To learn more, see Manipulating Microsoft SQL Server Using SQL Injection
- A call to a stored procedure such as xp_cmdshell to open a backdoor or install a Trojan that will send the information back to the attacker
- An inference attack that uses CASE statements to get data byte by byte. To learn more, see Data-mining with SQL Injection and Inference
Tampering also has different scenarios:
- An additional DROP statement to drop a table from a database
- An additional INSERT statement to add a record to a table
- An additional UPDATE statement to replace existing data in a table
You need to try different payloads. We recommend listing all the payloads that can be executed against the database under test. Then to execute each payload with the syntactic variations previously mentioned. By doing this, you will expand their SQL injection test cases to get maximum testing coverage.
Nevertheless, keep in mind that it is also important not to overdo payload testing. If you realize that a specific variable-entry point is not susceptible to SQL injection (it might be parameterized or escaped of its command characters) then move on to the next variable and not spend unnecessary time testing numerous payloads.
NOTE: Use proper test monitors or indicators
When testing injection, especially out of bands that opens a separate channel to send data back, make sure to have in indicator that waits for the test to pass or fail. If the payload opens a backdoor then connect to the backdoor. If the payload copies a database to a remote database then have that server set up and ready to receive the stolen data. Having proper indicators and monitors in place is the only way to find out the results of all test cases.
Learn database structure and use to tune test cases
In almost all information disclosure and tampering scenarios, the attacker will need to know table and column names. One way to successfully discover database details is to use error messages smartly. Another way to discover database structure such as table names and columns is to brute force table names or column names and look for valid ones. Finally, you can discover details about the database using inference techniques.
Good SQL Injection testing relies on proper coverage of all SQL related input variables through their different entry points. Start by understanding attack scenarios and doing a comprehensive analysis of the application's SQL related input variables, query construction, and entry points. Then try basic tests, tune the test data based on different entry points, and look carefully how the application reacts. Finally, tune your data using the appropriate payloads and keep tuning test case data with learned or inferred database structure.