LevelBlue + SentinelOne: Global Partnership to Deliver AI-Powered Managed Security Operations and Incident Response. Learn More
Access immediate incident response support, available 24/7
Access immediate incident response support, available 24/7
LevelBlue + SentinelOne: Global Partnership to Deliver AI-Powered Managed Security Operations and Incident Response. Learn More
In offensive security, the ability to blend seamlessly with legitimate traffic is vital to avoid detection. Establishing command-and-control (C2) communications can be challenging in environments fortified with security measures like perimeter firewalls and web proxies.
Flangvik’s CobaltBus project leverages Azure Service Bus, a popular enterprise messaging service, to facilitate C2 communication. Azure Service Bus offers an interesting avenue for covert channels due to its ability to mimic legitimate traffic and its use of trusted Azure domain names, which can potentially exploit inherent trust in the Azure ecosystem.
However, there is a catch: by default, it uses TCP connections (tcp/5671) establish communication with the Service Bus. On a recent Purple Team engagement conducted by LevelBlue SpiderLabs, the client was blocking outbound traffic to Azure Service Bus on tcp/5671. While this is a good security practice (blocking unwanted or unknown traffic), this prevented the beacon from establishing a connection back to the C2 server.
However, it is possible to establish Azure Service Bus connections using WebSockets.
Let’s explore the integration of Azure Service Bus with Cobalt Strike, using WebSockets instead of TCP. It builds on Flangvik’s CobaltBus with simple modifications to enhance stealth. By using WebSockets as opposed to TCP, it becomes possible to bypass traditional network security controls by leveraging WebSocket support, which operates over HTTPS and is typically allowed in enterprise environments.
Before answering this, let’s learn what is Azure Service Bus?:
Azure Service Bus is a fully managed enterprise message broker with message queues and publish-subscribe topics. Service Bus is used to decouple applications and services from each other, providing the following benefits:
Data is transferred between different applications and services using **messages**. A message is a container decorated with metadata and contains data. The data can be any kind of information, including structured data encoded with the common formats such as the following ones: JSON, XML, Apache Avro, plain text.
Essentially, the Azure Service Bus allows for messages to be sent and received between applications.
So why WebSockets?
In its default configuration, Azure Service Bus uses TCP on port 5671 for communication. However, many enterprise networks block outbound TCP connections on uncommon ports, which can disrupt C2 operations. WebSockets, on the other hand, operate over HTTPS (port 443), a ubiquitous protocol that blends in seamlessly with legitimate traffic. Additionally, proxies often have difficulty inspecting WebSocket traffic compared to traditional HTTPS traffic.
Once a WebSocket connection is established, proxies typically can’t perform the same level of deep packet inspection on WebSocket frames, meaning they cannot easily detect malicious payloads or unauthorized actions unless the entire WebSocket connection is being decrypted, which was certainly the case within this particular Purple Team engagement.
The modification to CobaltBus involves replacing the 'ServiceBusTransportType' from 'TCP' (default) to 'AmqpWebSockets', allowing the beacon to communicate with the TeamServer in restrictive environments.
The core modification is located in the ServiceBusHandler constructor, where the original TCP-based transport is replaced with a WebSocket-based transport.
public ServiceBusHandler(string connectionString, string queueName, string beaconId, NamePipeHandler cobaltHandler) { ConnectionString = connectionString; NamePipeHandler = cobaltHandler; QueueName = queueName; BeaconId = beaconId; client = new ServiceBusClient(ConnectionString);
}
Figure 1. Original code in Beacon/Handles/ServiceBusHandler.cs
public ServiceBusHandler(string connectionString, string queueName, string beaconId, NamePipeHandler cobaltHandler) { ConnectionString = connectionString; NamePipeHandler = cobaltHandler; QueueName = queueName; //orchestrationQueueName = queueName; BeaconId = beaconId; //client = new ServiceBusClient(ConnectionString); // uses TCP by default client = new ServiceBusClient(connectionString, new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpWebSockets }); //use WebSocket not TCP 5671
Figure 2. Modified version
The core modification is located in the ServiceBusHandler constructor, where the original TCP-based transport is replaced with a WebSocket-based transport.
The CobaltBus integration operates as follows:

Figure 3. Creation of a new External C2 listener
Figure 4. Creation of a namespace
Figure 5. Addition of a SAS policy with send and listen access
Take note of the primary connection strings for both access policies (root and public).
Figure 6. Beacon / program.cs
.jpg?width=640&height=226&name=Figure%207.%20CobaltBus%20program.cs%20(server%20side).jpg)
Figure 7. CobaltBus / program.cs (server side)
When we compile using the unmodified client connection string (using tcp/5671) and execute the beacon in our lab, we clearly see the Service Bus traffic is using tcp/5671.

Figure 8. The Service Bus traffic is using TCP port 5671.
The CobaltBus.exe binary shows the communications between the Service Bus message queue and handles everything nicely into the CobaltStrike External C2 listener.

Figure 9. Communications between the Service Bus message queue as shown via CobaltBus.exe./protector/ open directory
Resulting in a beacon calling back to the C2 server:
![]()
Figure 10. Beacon calling back to the C2 server.
This works nicely in the lab, but of course, this port (tcp/5671) will likely (and was on the Purple Team) be blocked by the firewall.
When changing the connection string with the simple configuration to set the transport type to WebSockets, compile and execute again:

Figure 11. Setting the transport type to WebSockets.
We see that there is no traffic on tcp/5671:

Figure 12. No port traffic on tcp/5671.
Instead, it is now via tcp/443 (https) using WebSockets:

Figure 13. Web traffic is found on tcp/443 via WebSockets.
Again, resulting in a C2 connection back from the beacon, this time via HTTPS WebSockets, bypassing the firewall restrictions by routing the traffic via an allowed protocol (HTTPS).

Figure 14. Successful C2 connection via HTTPS WebSockets.
While this approach demonstrates the feasibility of using Azure Service Bus for covert C2, it could be optimized to reduce opportunities for detection. Several aspects, such as message flow and queue naming, could be refined to further minimize detection risks.
For defenders, monitoring Azure Service Bus activity for unusual patterns (e.g., excessive queue creation or unauthorized access) is essential.
LevelBlue is a globally recognized cybersecurity leader that reduces cyber risk and fortifies organizations against disruptive and damaging cyber threats. Our comprehensive offensive and defensive cybersecurity portfolio detects what others cannot, responds with greater speed and effectiveness, optimizes client investment, and improves security resilience. Learn more about us.