How to detect CobaltStrike Command & Control communication

By Bogdan Vennyk

CobaltStrike became part of the Cybercrime’s “toolset” almost in every Company breach. This growth is explained by the fact that CobaltStrike was leaked multiple times and became more accessible for malicious groups. Below is a statistics made by RecordedFuture for previous year.

Out of the box CobaltStrike has port scanning, different lateral movement techniques, file browser, keylogger and even remote desktop control via VNC. Besides widely used HTTP, HTTPs, DNS protocols for Command & Control communication, CobaltStrike supports SMB which often becomes unnoticed by SOC analysts.

Because CobaltStrike is highly customizable, it makes Endpoint protection solutions trivial to bypass. And its Malleable C2 Profiles [https://www.cobaltstrike.com/help-malleable-c2] settings will try to blend Command & Control communication into millions of network flows which go in and out in your organization.

With that said CobaltStrike network activity still can be detected due to the fact that some behavior characteristics are harder to customize than others, for example the way beacon check-ins for available tasks on Command & Control Server.

What is beaconing?

Beaconing is the term used to describe communication between agent and Command & Control Server. Great way to explain how it works is using agent code snippets from Empire Powershell – another Post-Exploitation framework widely used by malicious actors which deserves a separate article regarding its detection.

At first, agents sleep for specific time configured with a sleep parameter in Empire Powershell or sleep command in Cobalt Strike. Sleep is needed to make less requests and stay under radar unless there is a specific need to make more connections to Command & Control for example in case of faster data exfiltration over Command & Control channel. In both tools Empire Powershell and CobaltStrike there is a parameter called jitter which makes those sleeps more random.


# if there’s a delay (i.e. no interactive/delay 0) then sleep for the specified time

if ($script:AgentDelay -ne 0) {
              $SleepMin = [int]((1-$script:AgentJitter)*$script:AgentDelay)
              $SleepMax = [int]((1+$script:AgentJitter)*$script:AgentDelay)

              if ($SleepMin -eq $SleepMax) {
                          $SleepTime = $SleepMin
              }
              else{
                          $SleepTime = Get-Random -Minimum $SleepMin -Maximum $SleepMax
              }
             Start-Sleep -Seconds $sleepTime;
}

After sleep agent executes GetTask method to make a request to Command & Control Server and retrieve a task for further execution. If there is no task available, the server will return default response.

# get the next task from the server
$TaskData = (& $GetTask)

if ($TaskData) {
             $script:MissedCheckins = 0
             # did we get not get the default response
             if ([System.Text.Encoding]::UTF8.GetString($TaskData) -ne $script:DefaultResponse) {
                          Decode-RoutingPacket -PacketData $TaskData
             }
}

DefaultResponse is a simple “File or directory not found” HTML page set when an agent establishes connection with Command & Control Server right after encryption key exchange.

Both this characteristic can be used for detection:

  • Sleep without jitter can be calculated as time delta between requests.
  • Default response can be calculated as most occurred value for received bytes from the server.

CobaltStrike HTTP beacon

By default CobaltStrike HTTP beacon makes a GET request to send metadata in the Cookie header and check if there is an available task to be executed. Metadata is encrypted with public key injected into beacon, and more details on how to decrypt it are in this article from NCC Group.

If there is a task to be executed we will get it in the response for our beaconing GET request instead of the default empty response.

Results of executed commands are sent to the server using POST requests with default url pattern /submit.php?id=<beaconID>

That being said, most communication settings like metadata encoding, headers, header’s contents, default response can be changed with already mentioned Malleable C2 Profiles.

For analytics and detections development I will use Splunk  – big data analysis framework which often used as Security information and event management (SIEM) system and network activity collector Accedian Skylight solution. 

Visualization of CobaltStrike HTTP beacon communication with time chart shows identical intervals between each request, the main task here is to build detection which will detect those identical intervals.

Following SPL calculates time for previous event and appends it to current one using streamstats and then uses it to calculate time delta between requests. Time sorting needed in case events have messed order.

| sort 0 _time
| streamstats current=f last(_time) as prevtime by src_ip, dest_port, dest_ip, host
| eval timedelta = _time - prevtime

The one thing needed to be taken into account is different HTTP methods used for beaconing and sending results back to Command & Control, so additional grouping by HTTP method should fix this. Most occurring time delta (80 percent of total requests) will be the trigger point. To reduce false-positives, there is another threshold for the number of requests – more requests = higher chances that it is real Command & Control beaconing.

Second approach involves the number of the received bytes from the potential Command & Control server. Here response_payload is the size of an HTTP packet without headers.

In this case detection is more straightforward – compare number of requests with current packet size to total number of requests.

Beaconing detection by default response packet size is preferable because it works in most cases, including one where sleep jitter was used.

CobaltStrike SMB beacon

SMB beacon works a little bit differently than HTTP beacons. First of all SMB beacon needs a parent beacon which will communicate with it. Great analogy would be reverse and bind shells – in case of HTTP beaconing, beacon connects back to Command & Control server to retrieve tasks, while SMB beacon listens for tasks instead. For communication SMB beacon uses named pipes with default name pattern msagent_*.

Second instead of HTTP GET and POST requests SMB beacon uses SMB Write and Read commands. General schema for CobaltStrike SMB beacon communication is below.

SMB beacon inherits parent beacon sleep settings which basically means that now parent beacon will check-in on its child SMB beacon each time it beacons to Command & Control server. 

In this case the same algorithm as we used for HTTP beaconing detection by identical time intervals can be applied. The only difference is key grouping parameters are pipe name(file_name), Tree and SMB command. 

For SMB beacons default response present as well, here it has size 101 bytes with headers. Marked bytes size identify that command was sent to SMB beacon.

Detection for SMB beacons isn’t as straightforward as in the HTTP beaconing case. Because of how SMB works, write to file could happen across different TCP sessions. That’s why we should build detection around FID (File ID) which is a file handle returned when connection to a malicious named pipe was established.

Summary

Beaconing detection is a great approach to identify Command & Control communication inside the network. Beaconing across different protocols HTTP, DNS, SMB share the same characteristics like same intervals between check-ins to Command & Control server and default response to know if a task is available. This characteristic can be used to build simple yet so useful detections.

Hardest part is to select the right parameters to identify the beaconing channel. Beaconing is not always evil – software updates, ntp, wsman – you need to know your network before ringing the alarm.

Get the Help You Need

Cybersecurity is our core expertise. Let’s get in touch and you will learn more about how UnderDefense can benefit your organization 

Next Readers

by Alexander Ragulin | Feb 16, 2021 

Detecting reconnaissance activity in your network

by UnderDefense | Nov 8, 2018

Do you have any questions?

Please leave your contact below and we’ll get back to you shortly.

Pin It on Pinterest

Share This