wafw00f介绍
这不是本次的重点,相关介绍及使用方法相信大家已经了解,所以此处就直接引用其开发者对该工具的介绍。
To do its magic, WAFW00F does the following:
- Sends a normal HTTP request and analyses the response; this identifies a number of WAF solutions.
通过发送正常的HTTP
请求并且分析其返回包,判断其是否使用 WAF ,若使用确认WAF
类型
- If that is not successful, it sends a number of (potentially malicious) HTTP requests and uses simple logic to deduce which WAF it is.
若是无法通过正常的HTTP
请求结果分析出是否使用WAF
以及其类型,则构造恶意的请求通过简单的逻辑再次进行判断
- If that is also not successful, it analyses the responses previously returned and uses another simple algorithm to guess if a WAF or security solution is actively responding to our attacks.
如果这也不成功,它会分析之前返回的响应,并使用另一种简单的算法来猜测WAF
或安全解决方案是否正在积极响应我们的攻击
使用场景/方法
这不是本次的重点,想要具体了解其用法去其
github
主页即可
https://github.com/EnableSecurity/wafw00f
本工具的作用上面已经很详细的描述出来了,概括一下很简单:
探测目标是否存在WAF
,也可以说wafw00f
是一个Web
应用防火墙(WAF
)指纹识别的工具。
使用方法不难,此处不做介绍,若想进一步了解见:WEB 防火墙探测工具 – wafw00f 使用教程 - General
的个人博客
wafw00f 源码解析
所谓源码解析并不会完整分析其源码中的所有功能,比如 日志、输出、展示 等功能不在我们分析的范围内,而其对 WAF 的检测逻辑 、
所发流量的特征 、 WAF 识别的指纹 等将是重点要分析的地方。
流程:
- 解析源码含义,分析特征
- 抓包观察
源码文件结构
为了方便大家之后去看源码,此处简单描述一下源码的组成,其中没有描述的说明其用不大,大家自己去看就知道了,其中标注
important
是本工具的主要功能文件,后续将重点说明。
-
bin
-
lib
asciiarts.py
evillib.py
用于向目标建立连接发起请求 ( important )
-
plugins
用于判断各个WAF
的指纹 ( important )aliyundun.py
阿里云盾的特征值匹配文件huaweicloud.py
华为云的特征值匹配文件baidu.py
百度云加速的特征匹配文件- ……
还有很多特征文件大家自己去看就好
-
__init__.py
-
main.py
该工具主要的检测、判断功能的类与函数都在该文件中实现( important ) -
manager.py
加载plugins
中的WAF
指纹判断文件识别目标WAF
类型 -
wafprio.py
上述非important
的文件起到的作用多是一些起到 输出选项、连接 等功能的文件/函数,所以不做特殊介绍
基本流程
请求的流程并不复杂,和最开始介绍处的流程如出一辙:
- 发送正常
HTTP
请求,并判断是否存在WAF
若存在根据指纹判断其类型 - 若正常
HTTP
检测不出WAF
,则附加恶意的请求尝试出发WAF
并分析其类型
最后所谓的根据算法猜测,流量特征不明显,不在此次分析的范围内,实际用处也不大。
请求运行流程( important )
以第一次的正常
HTTP
请求探测为例(其余的都一致)。
由于对 Python 并不是太了解,所以作用域的表示采用了C++
中的::
(若是不对请及时指出会做更改)。
main.py
分析
完整的源码就不放在这占地方了,大家随时可到其github
主页获取,此处直接分析其重点部分
由上述流程可以看出,所有的请求均是从class WAFW00F
中发起,所以该类就是我们分析的重中之重!
请求的具体实现(比如请求中携带了哪些内容)将在分析evillib.py
文件是分析, 此处主要分析何时要发出何种请求。
从main()
函数出发看其逻辑:(解析参数等功能将直接略过)
没有指定其余参数
-
对输入的
URL
做相关处理后放到target
中传入WAFW00F
进行处理attacker = WAFW00F(target, debuglevel=options.verbose, path=path,followredirect=options.followredirect, extraheaders=extraheaders,proxies=proxies)
若请求没有结果则说明目标网站或本地网络有问题
if attacker.rq is None:
log.error(‘Site %s appears to be down’ % hostname)
continue -
由于第一次做的是常规探测,若此处就匹配到了
WAF
的指纹则输出结束即可,具体的输出等逻辑不是重点,略过; -
若无法分析出其是否存在
WAF
或匹配不出WAF
则通过identwaf()
函数进步拼凑恶意参数进行探测;waf = attacker.identwaf(options.findall)
log.info(‘Identified WAF: %s’ % waf)
-
进入
identwaf()
函数后,便会尝试匹配各个WAF
的特征;def identwaf(self, findall=False): detected = list() try: self.attackres = self.performCheck(self.centralAttack) except RequestBlocked: return detected for wafvendor in self.checklist: self.log.info('Checking for %s' % wafvendor) if self.wafdetections[wafvendor](self): detected.append(wafvendor) if not findall: break self.knowledge['wafname'] = detected return detected
这就是基本的流程。
解析来如果还没有确定出WAF
便会进入其自己提供的一个算法,但这并不是我们对流量特征分析所要关注的地方,所以就不探讨了。
下面到了激动人心的时刻,WAFW00F
类中到底是如何实现的呢?
class WAFW00F
一上来就中了大奖:
class WAFW00F(waftoolsengine):
xsstring = '<script>alert("XSS");</script>'
sqlistring = "UNION SELECT ALL FROM information_schema AND ' or SLEEP(5) or '"
lfistring = '../../../../etc/passwd'
rcestring = '/bin/cat /etc/passwd; ping 127.0.0.1; curl google.com'
xxestring = '<!ENTITY xxe SYSTEM "file:///etc/shadow">]><pwn>&hack;</pwn>'
WAFW00F
这个工具所要构造拼接的恶意代码在一开始就全部列出了,
而且在之后的使用中绝无变化,要构造恶意的请求就是从上述5
个字符串中选择1
个或多个直接使用。
可以看到改用据 用于判断是否存在WAF
的语句就以下五类:
- **XSS类 **
<script>alert("XSS");</script>
- **SQL注入类 **
UNION SELECT ALL FROM information_schema AND ' or SLEEP(5) or '
- **遍历类 **
../../../../etc/passwd
- **命令执行/拼接类 **
/bin/cat /etc/passwd; ping 127.0.0.1; curl google.com
- **XXE类 **
<!ENTITY xxe SYSTEM "file:///etc/shadow">]><pwn>&hack;</pwn>
那么有了这些语句,WAFW00F
又该如何拼接呢?
def normalRequest(self):
return self.Request()
def customRequest(self, headers=None):
return self.Request(headers=headers)
def nonExistent(self):
return self.Request(path=self.path + str(random.randrange(100, 999)) + '.html')
def xssAttack(self):
return self.Request(path=self.path, params= {'s': self.xsstring})
def xxeAttack(self):
return self.Request(path=self.path, params= {'s': self.xxestring})
def lfiAttack(self):
return self.Request(path=self.path + self.lfistring)
def centralAttack(self):
return self.Request(path=self.path, params={'a': self.xsstring, 'b': self.sqlistring, 'c': self.lfistring})
def sqliAttack(self):
return self.Request(path=self.path, params= {'s': self.sqlistring})
def oscAttack(self):
return self.Request(path=self.path, params= {'s': self.rcestring})
具体逻辑并不难理解,拿出几种几个来说一下。
1:def xssAttack(self)
def xssAttack(self):
return self.Request(path=self.path, params= {'s': self.xsstring})
例如给一个简单的例子:我们传给wafw00f
的URL
为:http://127.0.0.1:9000
则经过该参数拼接后的请求就为:
http://127.0.0.1:9000/?s=<script>alert("XSS");</script>
(URL
编码前 )。
2: def centralAttack(self):
def centralAttack(self):
return self.Request(path=self.path, params={'a': self.xsstring, 'b': self.sqlistring, 'c': self.lfistring})
例如给一个简单的例子:我们传给wafw00f
的URL
为:http://127.0.0.1:9000
则经过该参数拼接后的请求就为:
http://127.0.0.1:9000/?s=<script>alert("XSS");</script>&b=UNION SELECT ALL FROM information_schema AND ' or SLEEP(5) or '&c=../../../../etc/passwd
(URL
编码前 )
从前面的流程可以看出,在def identwaf(self, findall=False):
中调用的拼接的语句的方法就是本方法,拼接进三个语句,
其他的逻辑相同。
evillib.py
分析
上面只是在上层对要拼接哪些参数进行构造,实际上组合成完整的 HTTP 报文调用requests.get()
进行请求的是在该文件中。
wafw00f
中若没有通过—headers
指定头部的话,会使用自己默认的—headers
这个默认的 headers 就定义在该文件中。
def_headers = {'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'en-US,en;q=0.9',
'DNT' : '1', # Do Not Track request header
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3770.100 Safari/537.36',
'Upgrade-Insecure-Requests': '1' #
}
默认情况下,接下来通过requests.get()
请求时便会使用该头部,
def Request(self, headers=None, path=None, params={}, delay=0, timeout=7):
try:
time.sleep(delay)
if not headers:
h = self.headers
else: h = headers
req = requests.get(self.target, proxies=self.proxies, headers=h, timeout=timeout,
allow_redirects=self.allowredir, params=params, verify=False)
self.log.info('Request Succeeded')
self.log.debug('Headers: %s\\n' % req.headers)
self.log.debug('Content: %s\\n' % req.content)
self.requestnumber += 1
return req
except requests.exceptions.RequestException as e:
self.log.error('Something went wrong %s' % (e.__str__()))
指纹的识别
拿Huawei Cloud WAF
的指纹来说
#!/usr/bin/env python
'''
Copyright (C) 2022, WAFW00F Developers.
See the LICENSE file for copying permission.
'''
NAME = 'Huawei Cloud Firewall (Huawei)'
def is_waf(self):
schemes = [
# 匹配 cookie
self.matchCookie(r'^HWWAFSESID='),
# 匹配 header 中的 Server
self.matchHeader(('Server', r'HuaweiCloudWAF')),
# 匹配 body
self.matchContent(r'hwclouds\\.com'),
self.matchContent(r'hws_security@')
]
if any(i for i in schemes):
return True
return False
CSDN
使用华为云防护
其余脚本见:wafw00f/wafw00f/plugins at master ·
EnableSecurity/wafw00f
wafw00f 流量
CSDN
使用华为云防护
[外链图片转存中…(img-2XUm2e6B-1676465985889)]
其余脚本见:wafw00f/wafw00f/plugins at master ·
EnableSecurity/wafw00f
wafw00f 流量
[外链图片转存中…(img-bvlVndeR-1676465985889)]
[外链图片转存中…(img-Dfxdushb-1676465985889)]
网络安全工程师企业级学习路线
这时候你当然需要一份系统性的学习路线
如图片过大被平台压缩导致看不清的话,可以在文末下载(无偿的),大家也可以一起学习交流一下。
一些我收集的网络安全自学入门书籍
一些我白嫖到的不错的视频教程:
上述资料【扫下方二维码】就可以领取了,无偿分享