- 1 Bypassing modern SQL injection security measures
- 1.1 Basic signature evasion
- 1.2 Defeating partial sanitizing
- 1.3 Bypassing XSS filters during SQL injection
Bypassing modern SQL injection security measures
|Simply triggering an IPS or WAF and having the request blocked under only certain conditions does not confirm the vulnerability of the page.|
To exploit or even test web applications in the modern world, countermeasures that are in place would need to be recognized and defeated. A WAF is probably in the way if the following things are being experienced:
- Having the connection to the server reset ONLY when testing the site for vulnerabilities
- 403 Forbidden responses ONLY when testing the site for vulnerabilities
- Being blocked by the remote firewall after a repeatable number of injection attempts
Many IDS and WAF systems can be easily evaded by either:
- Simply using SSL or HTTPS
- Using a de-syncronization attack like session-splicing when SSL is not an option.
Basic signature evasion
Signature evasion is very similar to evading partial sanitizing. Instead of modifying the characters, an IPS drops traffic if the characters appear in a particular sequence in order to match a pattern. By discovering that sequence, adjustments can be made to the queries to evade the IPS or WAF in the way of the testing. Many web application firewalls will recognize the "1=1" test simply due to its popularity. Other queries that are very similar may also be noticed. Lets suppose the signature is looking for something along the lines of [integer][equal sign][integer], or that a request with "AND 1=1" had its connection reset, but the page without the injection continues to load.
Take note of the whitespace around the = operator. If there is none, try adding a space. If there is a space on each side, try removing or adding one to see if there isn't a proper length delimiter on the signature. Lopsided, missing, or extra whitespace may be found that can bypass signature-based analysis engines.
%20and%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%201=%20%20%20%201 (TRUE) %20and%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%201=%20%20%20%200 (FALSE)
Integer and string size delimiters
Because there is usually a size delimiter or a maximum size to the integer, the size to stop detection can be exceeded. Ten digit random numbers, instead of the single digit predictable numbers might do the trick.
%20and%402837649781237849=402837649781237849 (TRUE) %20and%201789236419872364=128756128398671289 (FALSE)
Switching up the data types
If integers are proving a hard time, the signature may be tuned too specifically to integers. Try mixing the comparisons up a bit, using strings or floating point values to de-rail the signature.
%20and%205.8=5.8 (TRUE) %20and%200.2=0.3 (FALSE)
Instead of comparing a value like "1=1", compare mathematical expressions. Mathematical expressions may be the key to bypassing the problem if there are still problems with signature detection.
%20and%201.2+3=4.2 (TRUE) %20and%200.2-1=0 (FALSE)
If there are still problems during testing, this probably isn't the issue. Try changing the case of the letters making up the boolean operator (and to AnD and or to oR).
Extending conditional statements
Many IDS signatures will look for a boolean operator ("and" or "or") before a conditional statement if it is being appended to another conditional statement (e.g. after query reconstruction we have where id=1 and 1=1, there are two conditions there).
- Using IF for MySQL injection:
The syntax for the IF statement in MySQL is:
IF([condition],[VALUE TO RETURN IF TRUE],[ELSE RETURN VALUE])
%20and%20if(10829361=10829361,1,0) (TRUE) %20and%20if(98276232=72619126,1,0) (FALSE)
Any combination of the above techniques can be used in conjunction with one another as long as the queries still return true and false.
Defeating partial sanitizing
If an attempt is made to bypass the sanitizing by breaking the sanitizing method, there will most likely be trouble. Instead, bypass the sanitizing by crafting queries that do not require sanitized characters.
MySQL and certain versions of Microsoft SQL allow for string literals to be passed in hexadecimal format.:
select 'abc'; ...is equivalent to... select 0x616263;. Additionally, PostgreSQL allows the use of two dollar signs as string delimiters select $$abc$$;
Therefore, 0x616263 can be used in place of 'abc'. This will come in handy while exploiting a WHERE clause and not being able to use quotes.}}
String concatenation can avoid the use of quotes the use of quotes in:
Using the char() function to construct the string 'abc': select char(97,98,99); ->Similar to the hex example, char(97,98,99) can be used interchangeably with the string 'abc'.
Using the chr() function and double-pipe concatenation operator: select chr(97)||chr(98)||chr(99); ->Similar to the above example, chr(97)||chr(98)||chr(99) can be used interchangeably with the string 'abc'.
- Microsoft SQL Server:
Using the char() function and plus operator: select char(97)+char(98)+char(99); ->Similar to the other examples, char(97)+char(98)+char(99) can be used interchangeably with the string 'abc'.
Filtering can be bypassed on the space character by using alternative whitespace characters to the space character (%20). Most SQL engines consider a line return (%0a in a *NIX environment, %0a%0d in a Windows environment), tab characters, or the + character as valid whitespace:
and%0a1=1 and%0a1=0 and+1=1 and+1=0
MySQL treats block comments as whitespace.
Bypassing XSS filters during SQL injection
If XSS filtering is encountered, chances are the standard comparison operators (=, <,>) are being filtered out. If this is the case, 'alternative comparison operators will need to be used':
Testing with BETWEEN
The between operator is universal across all SQL platforms with the same syntax, and as a result is a more reliable testing method.
- The between comparison operator will return true or false based on whether or not the preceding value is between a ceiling and a floor in a range. For example, 50 is between 0 and 100, but 300 is not, which safely avoids using the = operator in the query:
and%2050%20between%200%20and%20100 (True) and%20300%20between%200%20and%20100 (False)
- This turns the query into something like:
select * from articles where id=1 and 50 between 0 and 100 select * from articles where id=1 and 300 between 0 and 100
The between operator can also be used on strings:
and%20'c'%20between%20'a'%20and%20'm (True) and%20'z'%20between%20'a'%20and%20'm (False)
Testing with Regular Expression Operators (REGEXP, ~, and RLIKE)
- Different database engines have different operators for Regular Expressions:
MySQL uses the REGEXP operator.
PostgreSQL uses the ~ operator.
MS SQL uses the RLIKE operator.
The following tests contruct strings using native string constructors to bypass any requirement for quotes. For more information regarding this, please see the entry on sql injection without quotes.
Below are either hexadecimal character codes or ascii code equivilent characters being translated into a string by the SQL server. Understanding is required in order to become proficient in SQL injection.</i>