1.1 General SQL Injection Technology Overview
There is no standard definition of SQL injection technology, and the Microsoft China Technology Center is described in 2 ways :
(1) Script-injected attacks
(2) Malicious user input used to influence the SQL script being executed
According to Chris Anley's definition , when an attacker writes data to an application by inserting a series of SQL statements into a query statement, this method can be defined as SQL injection. Stephen Kost gives another feature of this form of attack, "obtaining unauthorized access and direct retrieval from a database," which, by its very nature, uses a tool that is SQL syntax for vulnerabilities in the programming process of the application developer, " SQL injection attacks occur when an attacker is able to manipulate the data and insert some SQL statements into the application. In fact, SQL injection is a vulnerability in common multi-connected applications, where an attacker deceives a database server to execute an arbitrary, non-authoritative query by adding additional SQL statement elements to the end of a predefined query statement in the application. This type of application is typically a network application (Web application) that allows the user to enter query criteria and embed the query criteria into the SQL request statement and send it to the database server associated with the application to execute. By constructing some malformed inputs, an attacker can manipulate such request statements to obtain pre-unknown results.
In terms of risk, SQL injection attacks are at the forefront, similar to vulnerabilities such as buffer overruns. And if a buffer overflow attack is to be implemented, the attacker must first be able to bypass the site's firewall, whereas for a SQL injection attack, the firewall must allow a forward connection from the Internet to the Web server in order for the user to access the network application, so that once the network application has an injection vulnerability, Attackers can access the database directly and even gain access to the server on which the database resides, so in some cases SQL injection attacks are more risky than all other vulnerabilities.
SQL injection attacks take advantage of SQL syntax, which makes this attack extensive. Theoretically, for all SQL language-based database software including SQL Server,oracle,mysql, Db2,informix, and network applications connected to it include Active/java Server Pages, Cold Fusion Management, PHP, or perl are all valid. Of course, the various software has its own characteristics, the actual attack code may be different. The principle of SQL injection attack is relatively simple, and all kinds of applications based on database system are widely used, and the public publications that introduce the injection and exploit methods have been introduced, resulting in the increasing number of SQL injection attacks in recent years, and the trend of injecting attacks is abused.
For a detailed introduction to the general SQL injection technology for MS SQL Server, refer to the "Advanced SQL injection in SQL Server application"  article in Chris Anley and its subsequent "more advanced SQL injection" ,cesar Cerrundo wrote the article "using SQL injection to manipulate Microsoft SQL Server" , and Kevin Spett of the SPI Lab writes the white Paper "is SQL injection your Web application vulnerable?"  While general SQL injection technology for Oracle is presented, you can refer to Stephen Kost's "Introduction to SQL injection attacks against Oracle developers"  article.
1.2 The defense of SQL injection attacks
As more and more attacks take advantage of SQL injection technology, there are a number of scenarios that attempt to address injection vulnerabilities. The programmes currently being proposed are:
(1) The legality of the submitted data is checked before the official processing of the service side;
(2) Encapsulation client submits information;
(3) Replace or delete sensitive characters/strings;
(4) Shielding error messages.
Scenario (1) is recognized as the most fundamental solution, and the server refuses to perform critical processing operations until the client's input is validated, but this requires a developer to build a Web application in a secure manner, although there has been a large number of documents published to secure access to the database in Web application development, However, there are still many developers lack adequate security awareness, resulting in the development of the product is still an injection vulnerability, the practice of the scenario (2) requires RDBMS support, only Oracle uses this technology, the scenario (3) is an incomplete solution, for example, when the client input is "... Ccmdmcmdd. "When you replace a sensitive string" cmd "with a delete, the remaining characters are exactly" ... ", and the Scenario (4) is the most commonly used method, and many security documents assume that SQL injection attacks require information to be collected through error messages. Some even claim that certain special tasks cannot be completed without detailed error messages, which has led many security experts to develop the notion that injecting attacks cannot be implemented without detailed errors.
In fact, the masking error message is remedied after the server has finished processing, and the attack has actually occurred, just trying to stop the attacker from knowing the outcome of the attack. The SQL blind technique described in this article is a new technique used by attackers to enable attackers to they need and continue to inject attacks in the event that the error message is masked.
1.3 Structure organization of this article
To understand the blind attack, we will first describe the minimum response of the server required to determine the SQL injection vulnerability, and secondly, we will construct a syntax-compliant SQL request and replace it with any valid SQL request; Finally, we will discuss how to use the union without detailed error information SELECT statement. The condition of the blind attack discussed in this paper is that we know nothing about the network application, database type, table structure and so on before the attack, all of which need to be obtained through probing in the process of injection.
2 Identify injection vulnerabilities
A SQL injection attack is, of course, a confirmation of an injection vulnerability in the network application to be attacked, so an attacker would first have to establish some type of hint related to a server-generated error. Although the error message itself is masked, the network application still has the ability to differentiate between the correct request and the wrong request, and the attacker simply learns to identify the hints, look for related errors, and verify that they are related to SQL.
2.1 Identifying Errors
A network application primarily produces two types of errors, the first being a code exception generated by the Web server (exception), similar to "500:internal server error", usually if there is a syntax error in the SQL injection statement, such as an unclosed quotation mark, Will cause the server to throw such exceptions. If you want to block this type of error, you will typically replace the default error message with a custom HTML page, but as long as you observe that the response appears, you can confirm that a server error has actually occurred. In other cases, in order to further block such errors, some servers will simply jump to the main page or the previous visited page, or display a simple error message without providing any details, in case of an exception.
The second type of error is generated by application code, which means that its developers have good programming habits. This type of application takes into account that there may be some invalid situations and generates a specific error message for each of them. Although this type of error typically returns a request-valid response, the page still jumps to the main page, or uses some sort of hidden information, similar to "Internal Server Error."
To differentiate between these two types of errors, let's look at an example: there are two e-commerce applications, A and B, and two applications that use the same page called Proddetails.asp, which expects to get a parameter called ProdID. After it obtains the parameter, it extracts the corresponding product detail data from the database, and then takes some processing of the returned results. All two applications are called proddetails.asp via a link on a product List page, ensuring that the prodid is always present and valid. Application A believes that this will not cause problems, so no additional checks are made on the parameters, and if an attacker tampered with ProdID and inserted an ID that does not exist in the data table, the database returns an empty record. Because application A does not anticipate a possible empty record, an exception can occur when it attempts to process the data in the record, resulting in a "500:internal Server Error". While application B confirms that the record is larger than 0 before processing the record, if it is an empty record, an error message "The product does not exist" or the developer will relocate the page to the product's list page in order to hide the error.
Thus, in order to make the SQL blind, an attacker would first attempt to commit some invalid requests and observe how the application handles those errors, and what happens if a SQL error occurs.
2.2 Locating errors
After a preliminary understanding of the application to be attacked, an attacker would attempt to locate an error message generated by an artificially constructed input. At this point, the attacker would use standard SQL injection testing techniques, such as adding some SQL keywords (such as or,and, etc.) and some meta characters (such as; or ' etc.). Each parameter is tested independently, and the resulting response is tested to determine if an error has occurred. A blocking proxy (intercepting proxy) or similar tool makes it easy to identify page jumps and other predictable hidden errors, and any parameter that returns an error may have a SQL injection vulnerability. In the process of testing each parameter individually, it is important to ensure that the other parameters are valid, as it is necessary to avoid errors that result from any other possible causes other than injection. The results of the test are generally a list of suspicious parameters, some of the parameters in the list may indeed be injected, others may be caused by some SQL-independent errors, and therefore need to be rejected. The attacker would then need to pick from these parameters a real injection vulnerability parameter, which we call a definite injection point.
2.3 Determining the injection point
A SQL field can be divided into three main types: numbers, strings, and dates. Although each type has its own characteristics, it has nothing to do with the injected process. Each parameter that is submitted to a SQL query from a network application belongs to one of the above three types, where the numeric parameter is directly submitted to the server, and the string and date are quoted to be committed, for example:
SELECT * FROM Products WHERE ProdID = 4
SELECT * FROM products WHERE prodname = ' book '
The SQL Server, however, does not care what type of parameter expression it receives, as long as the expression is of the relevant type. This feature makes it easy for an attacker to verify that an error is related to SQL. In the case of numeric types, the simplest approach is to use basic arithmetic operations, such as the following requests:
One way to test this parameter is to insert 4 ' as a parameter, and the other is to use 3+1 as a parameter, assuming that the two parameters have been directly submitted to the SQL request statement, the following two SQL request statements will be formed:
(1) SELECT * FROM products WHERE ProdID = 4 '
(2) SELECT * FROM products WHERE ProdID = 3 + 1
There is a problem with the first SQL syntax, there will be an error, and the second, if executed successfully, returns the same product information as the original request (that is, ProdID equals 4), suggesting that the parameter is an injection vulnerability.
A similar technique can be applied to replace the parameter with a string expression that conforms to the SQL syntax, where there are two differences: first, the string representation is enclosed in quotation marks, so you need to block the quotation marks; second, different SQL Server string syntax, such as MS SQL Server using the symbol + To concatenate strings, while Oracle uses symbols | | To link. For example, the following request:
To test if the ProdName parameter has an injection vulnerability, you can replace it with an invalid string such as book ' and then replace it with an expression that might generate the correct string, such as B ' + ' Ook (for Oracle, B ' | | ' ook). This will form the following two SQL request statements:
(1) SELECT * FROM products WHERE prodname = ' book '
(2) SELECT * FROM products WHERE ProdID = ' B ' + ' ook '
The first one may still produce a SQL error, while the second may return the same value as the original request for the book product.
We note that even if the application has filtered the ' and + ' meta characters, we can still bypass the check by converting the characters into URL encodings (that is, 16 of the ASCII code of the characters) at input, for example:
/mysite/proddetails.asp? Prodid=3+1 is equal to/mysite/proddetails.asp? Prodid=3%2b1
/mysite/proddetails.asp? Prodid=b ' + ' ook equals/mysite/proddetails.asp? Prodid=b%27%2b%27ook
Similarly, any expression can be used to replace the original argument. A special system function can also be used to commit to return a number, a string, or a date, such as Sysdate in Oracle returns a date expression, and in SQL Server, GETDATE () returns a date expression. Other techniques can also be used to determine if there is a SQL injection vulnerability.
The above introduction reveals that even without detailed error information, it is still a very simple task for an attacker to determine whether a SQL injection vulnerability exists.
3 Implementing an injection attack
After the attacker has identified the injection point, an attempt is made to inject the exploit, which requires it to determine an injection request expression that conforms to the SQL syntax, determine the type of the backend database, and then construct the desired exploit code.
3.1 Determining the correct injection syntax
This is the most difficult and tricky step in a SQL blind attack, and if the initial SQL request statement is simple, it is relatively easy to determine the correct injection syntax, and if the initial SQL request statement is more complex, it will take many attempts to break through its limitations, but the basic techniques needed to make these attempts are simple.
The process of determining the basic syntax is through the standard select ... The where statement, the injected parameter (that is, the injection point) is part of the where statement. In order to determine the correct injection syntax, an attacker would have to be able to add additional data after the original where statement so that it could return unexpected results. For some simple applications, just adding or 1=1 can be done, but in most cases it is not enough to construct a successful exploit. The problem that often needs to be solved is how to pair the caret (parenthesis, such as a pair of parentheses) so that it matches the previous used symbol, such as the opening parenthesis. Another common problem is that a tampered request statement can cause an application to produce other errors, which are often difficult to differentiate from a SQL error, such as when an application can only process one record at a time, adding or 1=1 after the request statement may cause the database to return 1000 records, resulting in an error. Since the where statement is essentially a string of expressions that are either true or false, connected by an Or, an, and or a caret symbol, the key to determining the correct injection syntax is the ability to successfully break through the caret limit and to end the request statement smoothly, which requires multiple combinations of tests. For example, adding and 1=2 can change the value of an entire expression to false, and adding or 1=2 will not affect the value of the entire expression unless the operator has precedence.
For some injection exploits, just changing the where statement is sufficient, but for other situations, such as the Union select injection or the stored procedures injection, you need to be able to successfully end the entire SQL request statement. You can then add the SQL statements that are required by other attackers. In this case, an attacker could choose to use the SQL comment symbol to end the statement, which is two consecutive dashes (--), which requires SQL Server to ignore all input from the same line thereafter. For example, a login page requires the visitor to enter a user name and password and submit it to the SQL request statement:
SELECT Username, UserID, Password from Users WHERE Username = ' user ' and Password = ' Pass '
By entering John '--as the user name, the following where statement will be constructed:
WHERE Username = ' John '--' and Password = ' Pass '
At this point, the statement not only conforms to the SQL syntax, but also allows the user to skip the password authentication. But if it is a different where statement:
WHERE (Username = ' user ' and Password = ' pass ')
Notice that the caret appears here, and then use John '--as the user name, the request statement will be wrong:
WHERE (Username = ' John '--' and Password = ' pass ')
This is because there is an unpaired caret, and the request statement is not executed.
This example shows that using an annotation symbol can be used to determine whether the request statement has been successfully terminated, if a comment symbol is added and no error is generated, which means that the statement before the comment symbol has been successfully terminated. If an error occurs, this requires an attacker to make more requests.
3.2 Determining Database types
Once the attacker has identified the correct injection syntax, it will begin to use injection to determine the type of background database, a step that is much simpler than determining the injected syntax. Attackers typically use the following techniques, based on differences in the implementation of different types of database engines. Here are just a few ways to differentiate between Oracle and MS SQL Server:
The simplest way to do this is to use the string's link symbol as mentioned earlier, where an attacker can freely add an additional expression to a where statement if the injected syntax has been determined, then the comparison of strings can be used to differentiate the database, for example:
and ' xxx ' = ' x ' + ' xx ' (OR and%27xxx%27+%3d+%27x%27+%2b+%27xx%27)
By replacing + with | |, you can determine whether the database is Oracle or MS SQL Server, or another type.
The other way is to take advantage of the semicolon character (i.e.;), in SQL, where semicolons are used to concatenate several SQL statements on the same line. Semicolons can also be used in injected code when injected, but the Oracle driver does not allow the use of semicolons. Assuming that there is no error with the comment symbol in front of you, adding a semicolon to the comment symbol has no effect on MS SQL Server, but if it is Oracle, it will produce an error. Alternatively, you can use the COMMIT statement to confirm that you are allowed to execute other statements after the semicolon (for example, inject statement xxx '; COMMIT--to allow multiple sentences to be executed if no error occurs.
Finally, expressions can also be replaced with system functions that return the correct values, because the system functions used by different types of databases are also different, so you can also use system functions to determine the database type, such as the Date function getdate () of MS SQL Server mentioned in section 2.3. With Oracle's sysdate.
3.3 Construction Injection exploit code
Once all the relevant information has been obtained, an attacker can begin to inject, and no detailed error information is required during the construction of the injection exploit code, and the code itself can refer to other documents describing standard SQL injection attacks.
Because there are many other papers that have been discussed in detail for common SQL injection exploits, this article will only introduce a union select injection in the next section.
4 UNION Select injection
Despite tampering with select ... The where statement to inject is very effective for many applications, but in the case of blinds, the attacker would still be willing to use the Union SELECT statement because, unlike the operations that the where statement does, using the Union Select allows an attacker to access all tables in the database without error messages.
The Union select injection requires a pre-knowledge of the number and type of fields in a table in the database, which is generally considered impossible without detailed error information, but the method that resolves the problem is given below.
It is also important to note that the Union select is premised on the fact that the attacker has identified the correct injection syntax, which is explained in the previous section of this article, which is achievable under blind conditions, and before the Union SELECT statement is used, All of the caret symbols in the SQL statement should have been paired so that they are free to inject with union or other directives. The UNION Select also requires that the current statement and the original statement query information must have the same number and the same data type, or else an error will occur.
4.1 Number of columns of statistics
When the error message is not masked, the number of columns that are currently being tried is correct when the number of columns to get is only required to use a different number of fields each time the union select injection occurs, and when the error message is changed from column number mismatch to column type mismatch. However, in blind conditions, this method also loses its role because we are not aware of what the error message is.
The new approach is to use the order BY statement, with the order by at the end of the SELECT statement, to change the order of the returned recordset, which is typically sorted by the value of a specified column name. For example, when querying a product by product number, a valid injection statement is as follows:
SELECT Prodnum from Products WHERE (prodid=1234) ORDER by Prodnum--
and prodname= ' computer ') and Username= ' John '
It is often overlooked that the order by statement can also use a number to refer to the column name, in the above example, if Prodnum is the first column in the record returned by the query request, then inject 1234) The order by is returned with the same result. Because the previous query request returns only one field, inject 1234) ORDER by 2--An error occurs that the returned record cannot be sorted by the second field specified. In this way, ORDER by can be used to count the number of columns. Because each SELECT statement returns at least one field, an attacker could first add an order by in the injected syntax to determine whether the statement can be executed correctly, and sometimes the ordering of the field may produce an error, when adding the keyword ASC or desc resolves the problem. Once the order by syntax is determined to be valid, the attacker will traverse the row sequence number from column 1 to column 100 (or to column 1000, until the column number is determined to be invalid), in theory, when the first error occurs, the previous column number is the number of columns to be counted, but in practical terms, some fields may not allow sorting. Then you can try one or two more digits in the first error to confirm that the column number has been traversed.
4.2 Determining the data type of a column
After counting the number of columns, the attacker will need to determine the data type of the column, and it is tricky to judge the type in the case of the blind, because the union select requires the same field type as the query statement query, so if the number of fields is limited, you can simply use the Union The SELECT statement Acts violently against the field type (brute force), but if there are a large number of fields, the problem is judged. According to the previous article, the type of the field only number, string and date three possible types, once the number of fields has 10, then it means that there are 310 (about 60,000) possible combinations, assuming that every second can be automatically 20 attempts, it will take nearly one hours to exhaustive, if the number of fields more, The time required for testing would be unbearable.
An easy way to do this is to use the SQL keyword NULL, and the injection of a static field needs to distinguish between a numeric type or a different character type, and null can match any one of the data types. Therefore, you can inject a union SELECT statement that all query fields are NULL, then there will be no type mismatch errors. Let's give another example similar to the previous one:
SELECT Prodnum,prodtype,prodprice,prodprovider from Products
WHERE (prodid=1234 and prodname= ' computer ') and Username= ' John '
Assuming that the attacker has obtained the number of columns (in this case, 4), it is simple to construct a union SELECT statement, where all the query fields are null, and a from statement that does not produce a permission problem is required. For MS SQL Server, even ignoring the from statement is not an error, but for Oracle, you can use a table called dual. Finally, you need a where statement with a value of false (such as where 1=2), to ensure that the query does not return a recordset that contains only null values to prevent other possible errors. Then the injection statements for MS SQL Server are as follows:
SELECT Prodnum,prodtype,prodprice,prodprovider from Products
WHERE (prodid=1234) UNION SELECT null,null,null,null
WHERE 1=2--and Prodname= ' computer ') and Username= ' John '
This NULL injection statement has two purposes, and the main purpose is to construct a UNION SELECT statement that does not produce any errors to test whether the Union statement can be executed, and the other is to determine the database type 100% Confirm (you can test by adding a Database Developer preset table name in the FROM statement).
If the null injection statement is executed smoothly, you can quickly determine the type of each column. In each round of attempts, only one field type is tested, because the type has only three classes, so each field is tested up to three times, so the number of attempts is three times times the number of columns, rather than the number of columns indexed by 3. Assuming that Prodnum is a numeric type and the other three fields are string types, the following sequence of injected statements can determine the correct type:
? 1234) UNION SELECT null,null,null,null WHERE 1=2--
Error-free syntax is correct, MS SQL Server database is used
? 1234) UNION SELECT 1,null,null,null WHERE 1=2--
Error-Free the first field is a numeric type
? 1234) UNION SELECT 1,2,null,null WHERE 1=2--
Error The second field is not a numeric type
? 1234) UNION SELECT 1, ' 2 ', null,null where 1=2--
Error-Free the second field is a string type
? 1234) UNION SELECT 1, ' 2 ', 3,null where 1=2--
Error The third field is not a numeric type
? 1234) UNION SELECT 1, ' 2 ', ' 3 ', NULL WHERE 1=2--
Error-Free the third field is a string type
? 1234) UNION SELECT 1, ' 2 ', ' 3 ', 4 WHERE 1=2--
Error fourth field is not a numeric type
? 1234) UNION SELECT 1, ' 2 ', ' 3 ', ' 4 ' WHERE 1=2--
Error-Free fourth field is a string type
The attacker now has the data type for each column, and the blinds can also be applied to fetch data from tables in the database, such as getting a list of data tables and their respective column names, as well as getting data from the application, which is already discussed in some other papers on SQL injection. Therefore, this article will not continue to introduce.