Leveraging WebSockets for Command and Control (C2) Communications
A proof of concept to explore how WebSockets can be leveraged for C2 communications and should they be?
In my last post, I wrote about WebSocket handshake and how WebSockets can be leveraged for red team use cases. One of the use case I discussed was leveraging WebSockets for communication between the Command and Control (C2) server and an implant.
This made me curious to understand how practical it would be for a C2 software to support WebSockets as a communication channel and why haven’t well-known C2 software implemented it already?
Follow my journey of 100 Days of Red Team on WhatsApp, Telegram or Discord.
My first step was to create an absolutely basic Proof of Concept (PoC) of a miniature command and control (C2) that leverages WebSockets for communication. This gave me an opportunity to understand the complexity behind it. Turns out it isn’t that complicated (if AI could create it, well-known C2 software can definitely implement it).
This PoC had three components:
Server - Accepts incoming connection from the implant and upgrades the connection to use WebSocket. Sends commands to the implant and receives output. Also recieves a periodic heartbeat from the implant.
Implant - Initiates a connection to the server with a request to upgrade it to a WebSocket connection. Supports limited commands such as whoami, hostname, net (ipconfig / ifconfig) etc. Sends a periodic heartbeat to the server.
Relay (optional) - Intercepts traffic between the server and the implant and redirects it to a proxy software such as BurpSuite.
Both the server and the implant use Base64 encoding to simulate “encrypted” messages (notice the use of double quotes and italics for the word encrypted → this means I know Base64 is not encryption). They also support breaking larger output (such as that of ipconfig) into smaller chunks of 1024 bytes.
Did it work? Let’s see…
Lets peak behind the scenes of this communication and understand the traffic flow.
When the implant is deployed, it initiates a connection to the server via HTTP and requests it to upgrade the connection to WebSocket. The server responds with HTTP 101 Switching Protocols
upgrading the connection to WebSocket. This is also known as the WebSocket Handshake (as explained here).
Once the WebSocket connection has been established, the implant sends an intro
message to the server along with it’s client_id (aka implant ID).
In response, server sends an ack
message along with a custom message.
Post this, the server and the implant communicate via Base64 encoded messages.
The implant also sends a periodic heartbeat to the server. The default interval is 10 seconds but can be customized using --beacon
flag.
The code for this PoC is available in 100 Days of Red Team GitHub repository.
So, now that we know that WebSockets can work for C2 communications, the question is, should a red team actually use them? And if so, when does it makes sense to leverage them?
Before I answer these questions, lets understand why using WebSockets as a C2 communication channel may not make sense:
A long-lived WebSocket connection is a dead give away. As an alternative, WebSocket connections could be broken and re-established periodically. But then why not just leverage HTTP / HTTPS!
WebSockets are stateful connections (unlike HTTP / HTTPS). If the red team is dealing with multiple implants, this may put unnecessary load on the server resources and can pose scalability issues.
WebSocket handshake/upgrade can be more easily fingerprinted. Defenders can write signatures for suspicious ws/wss traffic.
Classic C2 frameworks put a lot of effort into fallback transports (HTTP(S) ↔ DNS ↔ SMB ↔ named pipes, etc.) and multi-stage staging to traverse different environments. HTTP(S) request/response maps naturally to these fallbacks. WebSockets are not as easy to downgrade to other transports without reengineering the agent.
WebSockets give true duplex channels and lower latency which is useful for interactive UIs. The communication between the C2 server and an implant is rarely real-time, making it impractical for most C2 related use cases.
When does it make sense to leverage WebSockets for C2 communications?
When low latency interactive shells or live remote desktop-style streams are required. They can benefit from the reliability provided by persistent duplex channels.
When the target is already using WebSockets frequently within their internal network then C2 related WebSocket connections can easily blend in (specially with wss).
If the implant runs inside a browser (e.g., script in a compromised web app).
To learn more about WebSockets, check out the official WebSockets website.
TL;DR
- WebSockets can be used for communication between a C2 server and implant as demonstrated by the absolutely basic Proof of Concept (PoC) of a miniature command and control (C2).
- Characterstics like long-lived WebSocket connections, WebSocket Handshake, statefulness may make WebSockets an immpractical choice for most red team ops.
- They can be leveraged in scenarios where low latency access is required or if the target environment is already leveraging WebSockets heavily within its network.
Follow my journey of 100 Days of Red Team on WhatsApp, Telegram or Discord.