使用wsrepl简化WebSocket渗透测试

本文介绍了Doyensec开发的wsrepl工具,旨在简化WebSocket应用的审计和渗透测试。wsrepl提供交互式REPL界面,支持自动化,并显示完整的RFC 6455 opcode,帮助测试人员更高效地处理WebSocket协议。

使用wsrepl简化WebSocket渗透测试

18 Jul 2023 - 发布者:Andrew Konstantinov

在一个即时满足的时代,生活比青少年刷TikTok还快,WebSocket已成为Web应用的心跳。它们是数据流和双向通信的无名英雄,实时提供一切,因为显然,等待已经过时了。

然而,当 tasked with pentesting these WebSockets,感觉就像在钢丝上骑独轮车 juggling flaming torches!现有工具虽然在其特定领域 proficient,但就像 mismatched puzzle pieces – 它们不太 fit together, leaving you to bridge the gaps。因此,您发现自己从一个工具切换到另一个,试图同时管理它们,并希望有更 streamlined approach。

这就是 https://github.com/doyensec/wsrepl 来救援的地方。这个工具,Doyensec安全工具的最新 addition,旨在简化基于WebSocket的应用的审计。wsrepl strike a much needed balance by offering an interactive REPL interface that’s user-friendly, while also being conveniently easy to automate。With wsrepl, we aim to turn the tide in websocket pentesting, providing a tool that is as efficient as it is intuitive。

Doyensec挑战

曾经,我们接手了一个客户的 engagement,其Web应用 heavily relied on WebSockets for soft real-time communication。这不是 easy feat。客户有 robust bug bounty policy and had undergone multiple pentests before。因此,我们 fully aware that the lowest hanging fruits were probably plucked。尽管如此,作为 true Doyensec warriors(‘doyen’ - Merriam-Webster描述为‘a person considered to be knowledgeable or uniquely skilled as a result of long experience in some field of endeavor’),我们 prepared to dig deeper for potential vulnerabilities。

我们的 primary obstacle 是应用的 custom protocol for data streaming。Pentesters中的 conventional wisdom suggests that the most challenging targets are often the ones most overlooked。Intriguing, isn’t it?

寻找完美工具

Pentesting WebSockets的 immediate go-to tool 通常是 Burp Suite。While it’s a heavyweight in web pentesting, we found its implementation of WebSockets mirrored HTTP requests a little bit too closely, which didn’t sit well with near-realtime communications。

Sure, it does provide a neat way to get an interactive WS session, but it’s a bit tedious - navigating through ‘Upgrade: websocket’, hopping between ‘Repeater’, ‘Websocket’, ‘New WebSocket’, filling in details, and altering HTTP/2 to HTTP/1.1。The result is a decent REPL but the process? Not so much。

Don’t get me wrong, Burp does have its advantages。Pentesters already have it open most times, it highlights JSON or XML, and integrates well with existing extensions。Despite that, it falls short when you have to automate custom authentication schemes, protocols, connection tracking, or data serialization schemes。

其他工具,如 websocketking.com 和 hoppscotch.io/realtime/websocket,提供易于使用且美观的图形客户端 within the browser。然而,它们 lack comprehensive options for automation。Tools like websocket-harness and WSSiP bridge the gap between HTTP and WebSockets, which can be useful, but again, they don’t offer an interactive REPL for manual inspection of traffic。

最后,我们 landed on websocat, a netcat inspired command line WebSockets client that comes closest to what we had in mind。While it does offer a host of features, it’s predominantly geared towards debugging WebSocket servers, not pentesting。

wsrepl: WebSocket渗透测试英雄

Enter wsrepl, born out of necessity as our answer to the challenges we faced。It is not just another pentesting tool, but an agile solution that sits comfortably in the middle - offering an interactive REPL experience while also providing simple and convenient path to automation。

Built with Python’s fantastic TUI framework Textual, it enables an accessible experience that is easy to navigate both by mouse and keyboard。That’s just scratching the surface though。Its interoperability with curl’s arguments enables a fluid transition from the Upgrade request in Burp to wsrepl。All it takes is to copy a request through ‘Copy as curl command’ menu option and replace curl with wsrepl。

On the surface, wsrepl is just like any other tool, showing incoming and outgoing traffic with the added option of sending new messages。The real magic however, is in the details。It leaves nothing to guesswork。Every hexadecimal opcode is shown as per RFC 6455, a feature that could potentially save you from many unnecessary debugging hours。

一个学到的教训

Here’s an anecdote to illustrate this point。At the beginning of our engagement with WebSockets, I wasn’t thoroughly familiar with the WebSocket RFC and built my understanding based on what Burp showed me。However, Burp was only displaying text messages, obscuring message opcodes and autonomously handling pings without revealing them in the UI。This partial visibility led to some misconceptions about how WebSockets operate。The developers of the service we were testing seemingly had the same misunderstanding, as they implemented ping traffic using 0x1 - text type messages。This caused confusion and wasted time when my scripts kept losing the connection, even though the traffic appeared to align with my Burp observations。

To avoid similar pitfalls, wsrepl is designed to give you the whole picture, without any hidden corners。Here’s a quick rundown of WebSocket opcodes defined in RFC6544 that you can expect to see in wsrepl:

Opcode Description
0x0 Continuation Frame
0x1 Text Frame
0x2 Binary Frame
0x8 Connection Close
0x9 Ping
0xA Pong (must carry the same payload as the corresponding Ping frame)

Contrary to most WebSocket protocols that mainly use 0x1 type messages, wsrepl accompanies all messages with their opcodes, ensuring full transparency。We’ve intentionally made the decision not to conceal ping traffic by default, although you have the choice to hide them using the –hide-ping-pong option。

Additionally, wsrepl introduces the unique capability of sending ‘fake’ ping messages, that use the 0x1 message frame。Payloads can be defined with options –ping-0x1-payload and –pong-0x1-payload, and the interval controlled by –ping-0x1-interval。It also supports client-induced ping messages (protocol level, 0x9), even though typically this is done by the server: –ping-interval。

It’s also noteworth that wsrepl incorporates an automatic reconnection feature in case of disconnects。Coupled with granular ping control, these features empower you to initiate long-lasting and stable WebSocket connections, which have proven useful for executing certain attacks。

使用wsrepl简化自动化

Moreover, wsrepl is crafted with a primary goal in mind: enabling you to quickly transition into WebSocket automation。To do this, you just need to write a Python plugin, which is pretty straightforward and, unlike Burp, feels quintessentially pythonic。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from wsrepl import Plugin

MESSAGES = [
    "hello",
    "world"
]

class Demo(Plugin):
    """Demo plugin that sends a static list of messages to the server."""
    def init(self):
        self.messages = MESSAGES

It’s Python, so really, the sky’s the limit。For instance, here is how to send a HTTP request to acquire the auth token, and then use it to authenticate with the WebSocket server:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from wsrepl import Plugin
from wsrepl.WSMessage import WSMessage

import json
import requests

class Demo(Plugin):
    """Demo plugin that dynamically acquires authentication token."""
    def init(self):
        # Here we simulate an API request to get a session token by supplying a username and password.
        # For the demo, we're using a dummy endpoint "https://hb.cran.dev/uuid" that returns a UUID.
        # In a real-life scenario, replace this with your own authentication endpoint and provide necessary credentials.
        token = requests.get("https://hb.cran.dev/uuid").json()["uuid"]

        # The acquired session token is then used to populate self.messages with an authentication message.
        # The exact format of this message will depend on your WebSocket server requirements.
        self.messages = [
            json.dumps({
                "auth": "session",
                "sessionId": token
            })
        ]

The plugin system is designed to be as flexible as possible。You can define hooks that are executed at various stages of the WebSocket lifecycle。For instance, you can use on_message_sent to modify messages before they are sent to the server, or on_message_received to parse and extract meaningful data from the server’s responses。The full list of hooks is as follows:

自定义REPL UI

The true triumph of wsrepl lies in its capacity to automate even the most complicated protocols。It is easy to add custom serialization routines, allowing you to focus on the stuff that matters。

Say you’re dealing with a protocol that uses JSON for data serialization, and you’re only interested in a single field within that data structure。wsrepl allows you to hide all the boilerplate, yet preserve the option to retrieve the raw data when necessary。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from wsrepl import Plugin

import json
from wsrepl.WSMessage import WSMessage

class Demo(Plugin):
    async def on_message_sent(self, message: WSMessage) -> None:
        # Grab the original message entered by the user
        original = message.msg

        # Prepare a more complex message structure that our server requires.
        message.msg = json.dumps({
            "type": "message",
            "data": {
                "text": original
            }
        })

        # Short and long versions of the message are used for display purposes in REPL UI.
        # By default they are the same as 'message.msg', but here we modify them for better UX.
        message.short = original
        message.long = message.msg


    async def on_message_received(self, message: WSMessage) -> None:
        # Get the original message received from the server
        original = message.msg

        try:
            # Try to parse the received message and extract meaningful data.
            # The exact structure here will depend on your websocket server's responses.
            message.short = json.loads(original)["data"]["text"]
        except:
            # In case of a parsing error, let's inform the user about it in the history view.
            message.short = "Error: could not parse message"

        # Show the original message when the user focuses on it in the UI.
        message.long = original

In conclusion, wsrepl is designed to make your WebSocket pentesting life easier。It’s the perfect blend of an interactive REPL experience with the ease of automation。It may not be the magical solution to every challenge you’ll face in pentesting WebSockets, but it is a powerful tool in your arsenal。Give it a try and let us know your experiences!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计