Mastering WebSocket C2 Detection: A Guide to Finding Hidden C2 Traffic

The modern threat landscape has evolved, and adversaries are increasingly moving away from traditional HTTP requests toward more persistent, stealthy communication channels. WebSockets (RFC 6455) have become a favorite for Command and Control (C2) operators because they provide a full-duplex communication channel that can bypass simple firewall rules by masquerading as legitimate application traffic. Because WebSockets begin with an HTTP handshake (Upgrade header), they often blend in with normal web traffic, making them an ideal vector for data exfiltration and remote control.
Detecting C2 traffic hidden within these connections requires a combination of packet-level analysis, statistical examination of timing, and behavioral analysis of the payloads. As defenders and red teamers, we must move beyond simple signature-based detection and understand the underlying patterns of how botnets and RATs (Remote Access Trojans) communicate. This guide will walk you through the technical process of identifying these covert channels using the industry-standard Wireshark tool and custom Python scripts for data analysis.
Understanding the WebSocket Protocol and C2 Abuse
WebSockets provide a way to establish a long-lived connection between a client and server, allowing for real-time, two-way communication without the overhead of repeated HTTP request-response cycles. In a typical environment, WebSockets are used for chat apps, live stock tickers, or collaborative document editing. However, from a cybersecurity perspective, this persistence is a double-edged sword. An adversary who has successfully compromised a host can use a WebSocket to maintain a persistent connection to their C2 server, allowing them to issue commands and receive exfiltrated data in real-time without triggering the same alerts that a new outbound TCP connection might.
From a network perspective, a WebSocket connection starts with a standard HTTP request that includes the Upgrade: websocket header. Once the server agrees, the connection is upgraded, and the two parties switch to the WebSocket protocol. This is critical for detection because the initial handshake is often logged by firewalls or SIEMs, but the subsequent binary or text frames—which contain the actual C2 traffic—are often ignored or treated as opaque data. In a C2 scenario, the attacker typically masks their traffic to look like legitimate API calls or common application data, such as JSON objects or encrypted binary blobs.
One of the primary challenges in WebSocket C2 detection is the prevalence of encryption. Since most WebSocket traffic is wrapped in TLS (WSS), the payload is encrypted. To analyze the content, you must either have access to the private keys for the TLS session or be performing the analysis at the endpoint where the traffic is decrypted. In the latter case, tools like Wireshark can be configured to use SSL keylog files to decrypt the traffic in real-time, exposing the frames hidden within the encrypted stream. Without decryption, analysts must rely on traffic analysis (TA) techniques, such as analyzing packet sizes and inter-arrival times to find patterns indicative of beaconing.
| Feature | Standard WebSocket Traffic | C2 WebSocket Traffic |
|---|---|---|
| Communication Flow | Driven by user interaction or app events | Driven by the remote C2 server or fixed intervals |
| Payload Size | Variable, often large (e.g., JSON, images) | Small, consistent, or structured for stealth |
| Connection Duration | Varies by app functionality | Often kept open for extended periods (persistence) |
| Traffic Volume | Bursty, aligned with user activity | Regular heartbeat patterns (beaconing) |
| Header Entropy | Standard browser/app headers | May contain anomalies or specific C2 signatures |
Technical Insight: The most common way attackers hide C2 traffic is by utilizing popular domains (e.g., Cloudflare, AWS, Google) as fronts. By using a legitimate service as a proxy, they ensure the traffic blends into the background of an enterprise environment.
Capturing WebSocket Traffic with Wireshark
To begin the process of WebSocket C2 detection, you need a precise capture of the network traffic. Wireshark is the gold standard for this task, providing the granularity needed to inspect the handshake and the subsequent frames. To isolate WebSocket traffic, you should focus your capture on the specific IP addresses of the suspected compromised host and the remote server. If you are monitoring a large network, you will need a strong display filter to reduce the noise.
Start by applying a display filter to isolate the WebSocket protocol. In Wireshark, the filter websocket will show you all packets that have been successfully upgraded to the WebSocket protocol. If you are looking for the initial handshake, use http.upgrade == "websocket". This allows you to see the Sec-WebSocket-Key and Sec-WebSocket-Accept headers, which are required to establish the connection. If the C2 is using a custom implementation of the protocol, you might find that the handshake lacks certain standard headers, which can be a tell-tale sign of non-browser-based C2 agents.
Once you have isolated the connection, analyze the frames. WebSocket frames are composed of an opcode, a payload length, and the payload itself. C2 traffic often employs a simple beaconing pattern: the client sends a small frame to the server, and the server responds with either a "no task" signal or a set of instructions. By examining the time between these frames, you can calculate the beaconing interval. If the interval is strictly regular (e.g., exactly every 30 seconds) or follows a recognizable jitter pattern (e.g., 30 seconds +/- 10%), you are likely looking at an automated process rather than human-generated traffic.
Warning: Many modern C2 frameworks implement "jitter" to avoid simple frequency analysis. Jitter introduces a random percentage of time variation to each beacon, making the traffic appear more organic and less like a machine-generated heartbeat.
Actionable Takeaway: Use the Wireshark "Statistics" menu and select "Conversations" to find long-lived TCP connections that persist for hours, then filter those specific streams for WebSocket frames to identify potential C2 activity.
Analyzing Traffic Patterns with Python for C2 Detection
While Wireshark is excellent for manual inspection, analyzing hours of traffic for beaconing patterns requires automation. Python, combined with the scapy or pyshark libraries, allows you to programmatically analyze pcap files and identify the rhythmic patterns typical of C2 communications. The goal is to calculate the delta time between consecutive WebSocket frames and perform a statistical analysis to see if the variance is low enough to suggest an automated beacon.
Below is a Python example using pyshark to extract the timestamps of WebSocket frames and detect potential beaconing behavior. This script calculates the time differences between frames and flags connections that show a consistent heartbeat.
python import pyshark import collections
def detect_websocket_beaconing(pcap_file, threshold=0.1): # Load the pcap file using pyshark cap = pyshark.FileCapture(pcap_file, display_filter='websocket') timestamps = []
for pkt in cap: try: # Get the timestamp of the packet timestamps.append(float(pkt.sniff_time)) except AttributeError: continue
if len(timestamps) < 2: print("Not enough WebSocket packets to determine patterns.") return# Calculate deltas between consecutive packetsdeltas = [timestamps[i+1] - timestamps[i] for i in range(len(timestamps)-1)]# Calculate the average deltaavg_delta = sum(deltas) / len(deltas)# Calculate the variance to check for jittervariance = sum((d - avg_delta) ** 2 for d in deltas) / len(deltas)std_dev = variance ** 0.5print(f"Average Delta: {avg_delta:.2f} seconds")print(f"Standard Deviation: {std_dev:.2f} seconds")# If the standard deviation is very low, it's likely a beaconif std_dev < threshold: print("[!] Potential C2 Beaconing Detected: High regularity in traffic.")else: print("[-] Traffic appears organic or has high jitter.")Example usage
detect_websocket_beaconing('capture.pcap')
This script provides a foundation for detecting the temporal footprints of C2 traffic. In a real-world scenario, you would correlate this with other indicators, such as the destination IP's reputation or the presence of non-standard payloads. By automating this analysis, you can scan thousands of connections across your network in seconds, identifying the few that exhibit the suspicious regularity of a C2 channel.
Automate this: mr7 Agent can run these security assessments automatically on your local machine. Combine it with KaliGPT for AI-powered analysis. Get 10,000 free tokens at mr7.ai.
Distinguishing Between Application Traffic and C2 Beacons
One of the biggest challenges in WebSocket C2 detection is the "noise" created by legitimate applications. Many modern web apps use WebSockets for legitimate notifications or heartbeat checks to keep the session alive. To distinguish these from malicious C2 traffic, you must look for anomalies in payload size and the specific nature of the data being transmitted. Legitimate application traffic typically has a variable payload size based on the actual data being sent to the user. In contrast, C2 beacons often send very small, fixed-size packets (e.g., a few bytes) when there are no commands to execute.
Furthermore, the direction of the traffic is a key indicator. In a standard application, the client typically requests data from the server. In a C2 scenario, the server may initiate the communication to push a command to the compromised host. While WebSockets allow for this, it is less common in standard web apps except for specific real-time notifications. If you see the server sending unsolicited frames to the client, and those frames are small and cryptic, it warrants further investigation.
Another distinguishing factor is the destination of the traffic. Legitimate WebSockets usually connect to known services or the organization's own infrastructure. C2 traffic often connects to external VPS providers, cloud-hosted instances, or known C2 relay points. By correlating the network flow metadata with the packet analysis, you can build a higher-confidence profile of the suspicious connection. This involves mapping the IP addresses against threat intelligence feeds and checking for domain-fronting techniques where the DNS query and the actual connection target are masqueraded.
| Aspect | Legitimate App Traffic | C2 Beaconing Traffic |
|---|---|---|
| Payload Content | Human-readable JSON, XML, or known binary formats | Obfuscated, encrypted, or very small heartbeats |
| Packet Frequency | Event-driven (user clicks, page updates) | Time-driven (fixed intervals or jittered) |
| Connection Origin | Usually initiated by user action | Often initiated by a background process/service |
| Data Volume | Varies significantly based on usage | Low and consistent baseline volume |
| Host Reputation | Known vendors, internal corporate IP space | VPS providers, dynamic DNS, or unknown IPs |
Technical Insight: Adversaries often use custom encoding (like Base64 or XOR) within the WebSocket frame to hide the actual commands being sent. If you see a pattern of strings ending in = or characters that do not form a recognizable word in any language, it is a strong indicator of obfuscated C2 traffic.
Inspecting Payload Data and Detecting Obfuscation
Once you have identified a suspicious WebSocket connection, the next step is to inspect the actual frames. If the traffic is not encrypted via TLS (which is rare but possible) or if you have the decryption keys, you can look for patterns in the data. C2 traffic is rarely sent in plain text; it is almost always obfuscated or encrypted to avoid detection by simple pattern-matching systems. Common obfuscation techniques include Base64 encoding, hexadecimal representation, or custom XOR operations with a static key.
For example, an attacker might use a simple XOR cipher to hide the commands they send to the infected host. To them, the traffic looks like random bytes, but with the correct key, the commands become visible. You can write a simple Python tool to attempt to decode these frames if you suspect a specific obfuscation method. Below is a basic example of how you might decode potential Base64 C2 traffic found in a WebSocket stream.
python import base64
def analyze_websocket_payload(payload): try: # Attempt to decode Base64 decoded = base64.b64decode(payload).decode('utf-8') return f"Decoded Payload: {decoded}" except Exception: return "Payload is not Base64 or is encrypted/obfuscated differently."
Example payload that might be found in a WebSocket frame
'SGVsbG8gQ09NLU5FV1RLRQ==' translates to 'Hello COM-NETWORK'
payload_sample = "SGVsbG8gQ09NLU5FV1RLRQ==" print(analyze_websocket_payload(payload_sample))
If the payload is not Base64, it may be encrypted using a library like AES. In that case, you would need the symmetric key, which might be embedded in the binary of the malware sample itself. Advanced analysts use reverse engineering tools to find the encryption key and then use it to decrypt the WebSocket traffic in Wireshark or via a custom script. This reveals the true nature of the communication, such as shell commands being passed to the host (whoami, ls, net user /domain) or data being exfiltrated to the C2 server.
Furthermore, look for the presence of "heartbeat" messages. Many C2 frameworks send a small, meaningless string every few minutes to keep the connection alive and verify that the implant is still active. If you see the same small string repeated at regular intervals, you have likely found the C2 heartbeat. This is a critical discovery because it allows you to establish a baseline for the implant's activity and predict when the next check-in will occur.
Actionable Takeaway: If you encounter encrypted WebSocket traffic, look for the presence of the Sec-WebSocket-Protocol header during the handshake; custom C2 frameworks often define their own sub-protocols here, which can serve as a fingerprint for the C2 framework being used.
Implementing Advanced Hunting Queries for C2
To scale your detection efforts, you cannot rely solely on manual Wireshark analysis. You must implement hunting queries in your SIEM or network monitoring tool to identify suspicious WebSocket patterns across your entire environment. The goal is to create alerts based on the behavioral characteristics of C2 traffic rather than relying on static indicators of compromise (IOCs), which change rapidly.
One effective approach is to monitor for long-lived outbound WebSocket connections to destinations that do not resolve to your known business services. You can use a query that identifies any WebSocket connection lasting more than 24 hours. While some legitimate apps (like messaging platforms) do this, many do not. By filtering out known-good services, you can narrow down the list of suspicious hosts. Another powerful query involves looking for connections where the ratio of data sent by the client to data received from the server is highly unbalanced, suggesting exfiltration or a command-driven relationship.
Additionally, you can create a query that flags WebSockets connecting to IPs with a low reputation score or those that have recently been flagged as malicious. The combination of behavioral patterns (long-duration, regular beaconing) and reputation data significantly increases the accuracy of your detection. Many advanced hunters also track the volume of data sent over these connections; a sudden spike in the amount of data sent over a previously quiet WebSocket session can indicate a bulk data exfiltrate event.
| Detection Strategy | Query Logic | Goal |
|---|---|---|
| Duration Analysis | duration > 86400s (24 hours) | Find persistent C2 channels |
| Repetition Analysis | std_dev(packet_interval) < 1s | Identify automated beaconing |
| Data Ratio | outbound_bytes / inbound_bytes > 10 | Detect potential data exfiltration |
| Domain Analysis | domain_age < 30 days AND protocol == WebSocket | Find recently registered C2 domains |
| Header Anomaly | http_header !~ "User-Agent: *Firefox*" | Detect non-browser WebSocket clients |
Technical Insight: The most sophisticated C2 frameworks now use "Malleable C2 profiles," which allow the operator to change the appearance of the traffic to mimic legitimate services like Amazon, Google, or Microsoft. This makes signature-based detection nearly impossible and forces analysts to rely on the behavioral techniques discussed above.
Mitigating C2 Traffic and Improving Network Visibility
Once you have identified potential WebSocket C2 traffic, the next step is mitigation and hardening. Simply blocking the identified IP or domain may not be enough, as the attacker may have fallback mechanisms. A comprehensive strategy involves restricting WebSocket connections to only authorized proxies or gateways and implementing deep packet inspection (DPI) to analyze the content of the frames in real-time. By enforcing a strict policy on outbound WebSocket connections, you can significantly reduce the attack surface available to threat actors.
One of the most effective mitigation strategies is the implementation of a network proxy that performs SSL/TLS inspection. This allows your security stack to decrypt WebSocket traffic and apply security rules based on the actual content of the frames, rather than just the destination IP and port. You can then write custom rules to block WebSocket frames that contain known C2 signatures or that deviate from the expected structure of your legitimate application traffic. This turns your network from a blind pipe into an active defense mechanism.
Furthermore, you should implement strict egress filtering. Instead of allowing all outbound traffic on ports 80 and 443, you can restrict WebSocket connections to a predefined list of allowed domains. This forces an attacker to use a domain or service that your organization already trusts, making it harder for them to establish a covert channel to a random VPS. If an attacker is forced to use a domain like github.com or discord.com for their C2, they are more likely to be detected by behavioral monitoring tools that track unusual patterns of communication with those services.
Finally, consider monitoring for "hidden" WebSockets. Some advanced C2 frameworks don't start with a standard HTTP handshake; instead, they use custom TCP protocols that look like HTTP at first glance but diverge into a proprietary binary format. By comparing the initial packets of a suspected C2 connection with the RFC 6455 standard, you can identify these non-compliant implementations. Any connection that claims to be a WebSocket but fails to follow the proper handshake or framing rules is highly suspicious and should be investigated immediately.
Actionable Takeaway: Implement a strategy of "Least Privilege" for your network connections. Only allow WebSocket traffic to verified, business-necessary domains, and use a proxy to inspect and log all outbound WebSocket frames.
Key Takeaways
- WebSockets are a prime C2 vector due to their full-duplex nature and ability to blend in with legitimate web application traffic.
- Beaconing detection requires analyzing the inter-arrival time of packets; a low standard deviation in the time between frames often indicates an automated C2 heartbeat.
- Wireshark and Python are critical tools for this process. Wireshark allows for initial capture and inspection, while Python enables the statistical analysis of large datasets.
- Payload obfuscation is common; analysts should look for Base64, XOR, or custom encryption within the WebSocket frames to identify hidden commands.
- Behavioral analysis is superior to signature-based detection since modern C2 frameworks can mimic legitimate traffic profiles.
- Network hardening such as TLS inspection and strict egress filtering is the best way to prevent and detect covert C2 channels.
- Automation tools like the mr7 Agent can significantly reduce the manual overhead of analyzing these patterns across an enterprise network.
Frequently Asked Questions
Q: How can I tell the difference between a C2 beacon and a legitimate app heartbeat?
Legitimate heartbeats are typically more irregular and aligned with user activity or specific app events. C2 beacons, however, tend to follow a strict time interval, even when the system is idle, and often have consistent, very small payload sizes that do not change over time.
Q: What are the most common ports used for covert WebSocket C2?
Most C2 frameworks use port 443 (HTTPS) to blend in with encrypted web traffic. Some may attempt to use port 80, but this is less common today as most WebSocket traffic requires the encryption provided by WSS (Secure WebSockets) to bypass modern corporate firewalls.
Q: Can I detect WebSocket C2 traffic if the payloads are encrypted?
Yes, you can use traffic analysis (TA) to detect the connection based on timing patterns, packet size, and destination reputation. While you cannot see the content, the metadata — such as the frequency of check-ins — is often enough to trigger a high-confidence alert.
Q: Does the use of a proxy make C2 detection easier or harder?
It makes it easier if the proxy is configured for SSL/TLS inspection, as it allows you to see the plain-text WebSocket handshake and frames. Without inspection, the proxy may hide the true destination of the traffic, making it harder to identify the C2 server.
Q: What is "jitter" in the context of C2 beaconing?
Jitter is a random amount of time added to each beaconing interval to break up the perfect regularity of the traffic. This is done to evade simple timing-based detection algorithms that look for a perfectly consistent heartbeat.
Stop Manual Testing. Start Using AI.
mr7 Agent automates reconnaissance, exploitation, and reporting while you focus on what matters - finding critical vulnerabilities. Plus, use KaliGPT and 0Day Coder for real-time AI assistance.


