WebSocket Turbo Intruder:挖掘WebSocket黄金矿
许多测试人员和工具在协议升级到WebSocket时就会放弃,或者只进行浅层分析。这是一个巨大的盲点,导致许多漏洞如破坏的访问控制、竞态条件和SQL注入未被发现。在本文中,我们看看新版本的WebSocket Turbo Intruder,这是一个Burp Suite扩展,将Turbo Intruder的快速攻击引擎引入WebSocket测试。我们还将讨论为什么自动扫描WebSocket应用程序很困难,以及这个工具如何帮助解决这些问题。
大纲
- 介绍
- 关键特性
- 入门指南
- 基本使用
- 过滤无聊内容
- 自动化测试
- 漏洞利用
- 高级特性
- 参考资料
介绍
WebSocket Turbo Intruder是一个Burp Suite扩展,用于使用自定义Python代码对WebSocket消息进行模糊测试。它扩展了Burp Suite引擎,使其能够利用WebSocket协议特定的漏洞。
关键特性
- 高速 - 支持每秒数千条消息
- HTTP适配器 - 通过与现有HTTP扫描器集成实现自动化测试
- 智能过滤 - 隐藏无聊的响应,让您专注于有趣的结果
虽然WebSocket Turbo Intruder包含一个用于速度的自定义引擎,但它不如Burp的内置引擎经过实战测试。如果您看到错误或连接问题,请尝试切换回默认引擎。此外,该工具专为针对单个目标的高容量测试而设计 - 由于WebSocket连接必须保持打开状态,测试大范围目标很棘手且不受良好支持。
入门指南
您可以直接从BApp商店安装WebSocket Turbo Intruder,这是最简单的入门方式。转到Extensions → BApp Store → WebSocket Turbo Intruder并单击Install。如果您喜欢自己构建或想探索源代码,该项目可在GitHub上获得。安装后,当您在Burp Suite中右键单击任何消息时,扩展将显示为新菜单项。
基本使用
该扩展附带两个内置工具:Turbo Intruder和HTTP Middleware。第一个工具最适合当您想向单个目标发送数千条WebSocket消息并寻找有趣行为时使用。第二个工具专为自动化扫描而设计,我们稍后会回到这一点。
让我们从一个基本的Python脚本示例开始。我们将使用它来测试PortSwigger Academy实验室:操纵WebSocket消息以利用漏洞。
当单击Attack按钮时,此脚本发送10个不同的数值作为消息JSON值的一部分。生成的表格(如屏幕截图所示)将包含扩展处理的所有请求(传出消息)和响应(传入消息)。
过滤无聊内容
与HTTP不同,WebSocket协议可以为一条传出消息发送多条传入消息。这使得测试变得更加困难,因为表格很快就会被噪音填满。在我们的案例中,单个"请求"触发了三个不同的"响应"。为了处理这个问题,扩展包含了强大的过滤器。这些过滤器让您可以隐藏不相关的流量,并将请求锁定到您只关心的响应。这是一个示例装饰器,仅保留来自用户Hal Pline的消息并过滤掉其他所有内容:
def queue_websockets(upgrade_request, message):connection = websocket_connection.create(upgrade_request)for i in range(10):connection.queue(message, str(i))def handle_outgoing_message(websocket_message):results_table.add(websocket_message)@MatchRegex(r'{"user":"Hal Pline"')
def handle_incoming_message(websocket_message):results_table.add(websocket_message)
自动化测试
如果手动查看结果表不是您的风格,您可以使用WebSocket Turbo Intruder HTTP Middleware将WebSocket连接包装在HTTP请求中。从Proxy History中选择任何WebSocket消息,然后右键单击并选择Extensions → WebSocket Turbo Intruder → Send to WebSocket HTTP Middleware。这使您可以使用过滤器仅捕获您关心的流量,同时通过本地HTTP端点与服务器交互。
例如,这里我们使用包含的ServerExample.py脚本创建WebSocket连接,并过滤传入消息仅显示从PortSwigger Academy实验室回显的消息:
def create_connection(upgrade_request):connection = websocket_connection.create(upgrade_request)return connectiondef handle_outgoing_message(websocket_message):results_table.add(websocket_message)@MatchRegex(r'{"user":"You"')
def handle_incoming_message(websocket_message):results_table.add(websocket_message)
从现在开始,我们可以向localhost发送HTTP POST请求,请求体被视为WebSocket消息。这允许您使用像Burp Suite Pro这样的自动化扫描器扫描任何WebSocket。
POST /proxy?url=https%3A%2F%2F0a7c00a903d17c5a801d35d8008a007a.web-security-academy.net%2Fchat HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16{"message":"hi"}
您可以自定义此代码以匹配目标应用程序的逻辑。此设置非常适合查找服务器端漏洞,如SQL注入、身份验证绕过或命令注入。
漏洞利用
除了常见的应用程序错误外,WebSocket还带来了自己独特的攻击面。我们接下来将看看其中一些。
WebSocket服务器端原型污染
Socket.IO是一个流行的JavaScript框架,带有自己的WebSocket实现。这使得测试更加复杂 - 但使用WebSocket Turbo Intruder,您可以绕过这些限制。
确认服务器使用Socket.IO的最简单方法是检查强制查询参数EIO,它指定协议版本。如果它等于4,服务器会发送ping数据包。我们可以使用内置的Ping和Pong装饰器自动化此过程。之后,脚本发送初始消息"40"开始对话,其余逻辑照常工作。
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter;def queue_websockets(upgrade_request, message):connection = websocket_connection.create(upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))connection.queue('40')connection.queue('42["message","hello"]')@Pong("3")
def handle_outgoing_message(websocket_message):results_table.add(websocket_message)@PingPong("2", "3")
def handle_incoming_message(websocket_message):results_table.add(websocket_message)
Socket.IO协议的HTTP适配器脚本:
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter;def create_connection(upgrade_request):connection = websocket_connection.create(upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))connection.queue('40')connection.decIn()return connection@Pong("3")
def handle_outgoing_message(websocket_message):results_table.add(websocket_message)@PingPong("2", "3")
def handle_incoming_message(websocket_message):results_table.add(websocket_message)
有趣的是,Socket.IO中的一些协议怪癖使其成为服务器端原型污染的良好候选者。如Gareth的早期研究"服务器端原型污染:无需DoS的黑盒检测"所示,可以滥用Express服务器功能来检测成功的污染。在这里使用相同的技术,我们可以通过污染initialPacket属性来欺骗Socket.IO返回新的问候消息:{"__proto__":{"initialPacket":"Polluted"}}
WebSocket竞态条件
默认的Intruder脚本通过单个连接以块形式发送消息。这对性能很好,但在测试竞态条件漏洞时没有用,因为时间和并发性很重要。
为了帮助解决这个问题,WebSocket Turbo Intruder包含一个特殊的引擎类型称为THREADED。此引擎启动多个工作线程,每个线程都有自己的WebSocket连接,并并行发送消息。这使得触发经典的竞态条件成为可能,如逻辑绕过、令牌重用或状态不同步错误。
如果您不熟悉Python线程,不用担心 - 包含的RaceConditionExample.py脚本只需要小的更改即可适应您的目标。最重要的设置在config()方法中定义:线程数控制打开多少个同时连接。
这种线程模型让您更好地控制并发性,并让您实验对单连接模糊测试不可见的时间敏感问题。
WebSocket死亡之ping
在测试竞态条件时,我在一个Java WebSocket实现中发现了一个意外的拒绝服务漏洞。
根据RFC,WebSocket帧以指定操作码和负载长度的标头开始。但是如果长度与实际负载不匹配 - 或者负载根本没有发送会发生什么?
使用TURBO引擎,我们可以发送任何类型的WebSocket帧,包括格式错误的帧。这允许我们手动调整标头中的负载长度,而无需发送千兆字节的数据。Java WebSocket实现存在以下问题。它读取消息标头并使用标头负载长度字段中用户指定的值在服务器上分配一个巨大的缓冲区,如果该值是Integer Max Value,则导致内存不足崩溃。之后服务器不再响应任何连接尝试。您可以在扩展附带的PingOfDeathExample.py中找到完整的源代码。
高级特性
命令行界面
WebSocket Turbo Intruder还包括一个独立的CLI,非常适合自动化、脚本编写或在Burp Suite外部运行攻击。这是一个基本用法示例:
java -jar WebSocketFuzzer-2.0.0.jar <scriptFile> <requestFile> <endpoint> <baseInput>
命令行支持相当基础。但对于在单个目标上运行长时间攻击非常有用,特别是在后台作业中。
调试模式
WebSocket Turbo Intruder包含一个内置的WS Logger功能,可记录多达1,000条WebSocket消息。这在调试使用HTTP Middleware的脚本时特别有用,在这些脚本中正确匹配传出和传入消息是关键。
在WebSocket Turbo Intruder → Logger On上启用记录器后,您可以跟踪消息内容及其内部ID。这些ID用于配对请求和响应 - 因此如果某些东西中断或消息不匹配,您可以检查日志以找出问题所在。
如果需要,您还可以通过使用Connection接口中的dec和inc方法来微调消息ID的处理方式。这使您可以完全控制消息的分配和分组方式。
参考资料
在开发WebSocket Turbo Intruder时,我从一些优秀的工作中汲取了灵感,包括@albinowax的"Turbo Intruder:拥抱十亿请求攻击"、@garethheyes的"服务器端原型污染:无需DoS的黑盒检测"和@vah_13的"WebSocket中的竞态条件"。
警告
快速警告 - WebSocket Turbo Intruder功能强大。它可以每秒发送数千条消息并并行打开许多连接。如果您不小心,可能会使服务器过载或触发拒绝服务条件。始终在允许自动化扫描的目标上使用它,并尽量不要在这样做时使互联网瘫痪。
报告错误和功能请求
WebSocket Turbo Intruder还支持自动Ping/Pong消息和使用isInteresting()方法的内置过滤等功能。您可以在Github存储库中了解这些和其他高级选项的更多信息。如果您发现错误或有功能请求,请随时打开新问题。
演示录像将很快在Black Hat Arsenal频道上提供。
祝你好运,玩得开心。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码
公众号二维码