Skip navigation
All Places > Products > RSA NetWitness Platform > Blog > Author: Rui Ataide

RSA NetWitness Platform

3 Posts authored by: Rui Ataide Employee
Rui Ataide

Domain Fronting Malware

Posted by Rui Ataide Employee Jun 19, 2019

Customers frequently ask me about malware that uses domain fronting and how to detect it. Simply put, domain fronting is when malware or an application pretends to be going to one domain but instead is going somewhere completely different. (Mitre ATT&CK - T1172)

 

The goal of domain fronting is to have the analysts believe that the connection is being a made to a safe site while the true destination is in fact somewhere completely different.

 

Let’s look at a piece of malware that uses this method. This is a PowerShell Empire sample:

 

 

In the configuration information of this file, we see a URL that will be requested, which is also Base64 encoded. The URL decodes to https://ajax.microsoft.com:443 as seen below:

 

 

So, this script will initiate a connection to ajax.microsoft.com:443, and appear to request /login/process.php. However, because the Host: header is pointing to content-tracker.*******.net, the request will actually go to https://content-tracker.*********.net/login/process.php instead.

 

You may be thinking that all you have to do in order to detect examples of domain fronting is to look for discrepancies between the requested URL and the domain/IP in the Host: header. However, there are  some complexities to deal with. Most of the time the initial connection is SSL encrypted, so you are limited to artifacts related to SSL traffic, unless you have SSL inspection technology in place. Another consideration is if whether a proxy is involved in this connection or not.

 

In order to describe what the analyst would see if SSL inspection technology is in place, let us use a Man-In-The-Middle proxy to inspect this traffic in its clear-text form. SSL Inspection technologies are extremely useful for this and other scenarios where malware communicates over SSL, and it is something that we highly recommend that you deploy in your organization.

 

Let us introduce two terms here to clarify the elements of this technique as we describe how to hunt for it:

            Fronting Domain (ajax.microsoft.com)

            Fronted Domain (content-tracker.*********.net)

 

Here we see the Fronting Domain request, which is also the only thing you would see if you were only relying on proxy logs. The Domain Fronting domain (ajax.microsoft.com in this case) is also what the proxy would use for URL Filtering checks. The proxy logs would not actually see the “Fronted Domain”. For all intents and purposes this would be a legitimate request to a Microsoft site.

 

 

 

However, the response is anything but what you would expect from the site. Namely, instead of some HTTP content the site returns an encoded blob of data that decodes into more PowerShell code.

 

How do I know, it was more PowerShell code, that was easy, I simply replaced the follow-up execution with the output to a file as seen below: 

 

 

Then opening the resulting stage2.ps1 file, you can see to contains additional PowerShell code that is highly obfuscated.

 

 

Let us go back one step and discuss another key aspect regarding Domain Fronting. Namely, the SSL certificates used during this communication. The SSL certificates are legitimate Microsoft signed certificates, since the initial connection is indeed to ajax.microsoft.com. This certicate is tied to many Microsoft domains and Microsoft CDN Domains.

 

 

We could try to de-obfuscate the stage2.ps1 PowerShell script but there really is no need, since by looking at the subsequent request of the malware on the proxy we can get an idea of what it does. Its initial check-in posting back victim information again in an encrypted binary blob of data.

 

 

Additionally, this particular strain of malware also seems to do a legitimate call to the ajax.microsoft.com site as shown below. While not at all relevant for domain fronting, it is important for the analysts to be aware as to why they might see both legitimate and malicious requests mixed together. The analyst will notice that the "Host:" header will match the requested domain in legitimate requests. 

 

 

 

The response from the legitimate site is also completely different and starts a redirect chain that we will show below:

 

 

And finally, the legitimate page for Microsoft Ajax Content Delivery Network.

 

 

Now that we have described in detail the sequence of requests, let us see how this all looks from the Netwitness Packet perspective. There are two cases, one where there is no proxy and one where there is one.

 

Traffic Analysis – SSL Only

 

Let’s start with the traffic without a proxy. I have isolated only the relevant events in a separate collection to facilitate the analysis. I will also point out how some of these indicators can be spotted in larger traffic patterns.

 

In the example below, the indicators are separated in two sessions: a DNS request and an SSL connection. You can see that the DNS request is for one domain name, while the SSL session displays what is referred to as the SNI, which does not match the DNS request.

 

 

For the legitimate traffic, the DNS request and the SSL SNI value both match. These are both extracted into the alias.host key.

 

 

So, how can you detect this type of behavior? It is not easy, especially on high volume environments. However, a starting point is to look for are alias.host values that only show one of the service types (DNS or SSL), but not both. Legitimate traffic will likely have both as shown below:

 

 

You should not expect these values to be balanced or equal as DNS is often cached, but you should expect to see both types of service. Some environments at times do not capture DNS due to volume, but to be successful it is critical to have both.

 

For the malicious traffic each domain will only have one type of traffic (i.e. DNS or SSL). This detection criteria is not  an exact “science” as you could easily have only DNS for all sorts of other types of traffic that are not domain fronting. The Fronting Domain will have the DNS traffic, while the Fronted Domain will have the SSL sessions.

 

 

 

Since the traffic is split between sessions on the packet side, we would need to use an ESA rule to detect this type of activity.

Traffic Analysis – Proxied Requests

 

For explicit proxied traffic things are slightly easier, as all the traffic is contained in a single session. We see the "raw" payload of one such session below. It can seem confusing at first, but Netwitness identifies this traffic as HTTP. This is correct since this part of the traffic is indeed HTTP.

 

 

Since we have all the pieces in one session here, the detection is easier. But how can we do it for high data volumes. In this case the HTTP session will have two different hostnames. While this is at times common for pure HTTP traffic due to socket re-use, it is uncommon for HTTPS/SSL traffic as the standards advise against it for privacy/security purposes, among other reasons.

 

 

This shows a possible solution to detect this type of traffic with a simple App rule that could identify traffic HTTP with 2 unique alias.host values and the presence of a certificate.

 

In summary, domain fronting is a technique used by attackers/red teams with the intent of either circumventing network policies (URL filtering), or hiding in plain sight, as the analysts are more likely to see/notice the legitimate domains than the malicious ones and assume this activity as safe/legitimate. However, this type of activity still has a certain footprint that we have described. Hopefully the information provided here will help you all improve your defenses against this technique.

 

Thank you,

 

Rui

In line with some of my other integrations, I recently decided to also create a proof-of-concept solution on how to integrate RSA NetWitness meta data into an ELK stack.

 

Given that I already had a couple of Python scripts to extract NetWitness meta via the REST API, I quickly converted one of them to generate output in an ELK-friendly format (JSON).

 

Setting up an ELK instance is outside the scope of this post, so with that done all I needed was a couple of configuration files and settings.

 

Step #1 - Define my index mapping template with the help of curl and the attached mappings.json file.

curl -XPUT http://localhost:9200/_template/netwitness_template -d @mappings.json

NOTE: The mappings file may require further customization for additional meta keys you may have in your environment.

 

Step #2 - Define my Logstash configuration settings.

# Sample Logstash configuration 
# Netwitness -> Logstash -> Elasticsearch pipeline.

input {
  exec {
    command => "/usr/bin/python2.7 /usr/share/logstash/modules/nwsdk_json.py -c https://sa:50103 -k '*' -w 'service exists' -f /var/tmp/nw.track "
    interval => 5
    type => 'netwitness'
    codec => 'json_lines'
  }
}

filter {
   mutate {
      remove_field => ["command"]
   }
}

output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "netwitness-%{+YYYY.MM.dd}"
  }
}

Again a level of ELK knowledge will be required that is outside the scope of this post. However, on the command section a few settings may require additional clarification, the Python code has them documented but for ease of reference, I'm listing them below:

 

  1. The REST endpoint from where to collect the data
  2. The list of meta keys to retrieve (in the example below '*' refers to all available meta keys)
  3. The SDK query that references the sessions that should be retrieved (in the example below, collect all "packet sessions" meta data)
  4. A tracker file location so only new data is retrieved by each execution on the input command. (i.e. continue from last data previously retrieved)
-c https://sa:50103 
-k '*'
-w 'service exists'
-f /var/tmp/nw.track

 

There will be additional configuration settings and steps required in ELK, once again, there's plenty of information available on this already as the open source solution that ELK is, so I won't go into that. I'm by no means an expert on ELK.

 

Finally, all that is left to show you is how the data looks. First, some of my Dynamic DNS events.

 

List of NetWitness Events in ELK

 

Below the details of one of those events.

 DynDNS Event Details

 

 

As a proof-of-concept all these details and scripts are provided as-is without any implied support or warranty. I'm not really that experienced in ELK as so I'm sure that someone can probably improve on this significantly, if you do feel free to share your experiences below in the comments section.

 

Thank you,

 

Rui

Eric Partington mentioned on his recent post Log - Sysmon 6 Windows Event Collection that a lot is being said about the use of Sysmon with logging solutions. 

 

As Incident Responders or even as simple malicious activity hunters one of the key sources of data we rely on daily is the ability to track all command execution and endpoint activity. Here at RSA we use NWE’s Behavioral Tracking to give the level of visibility that is comparable to what Sysmon is doing. Due to the importance of this type of visibility and the buzz that Sysmon is generating in having this data on your SIEM/Log solution, I felt that it is important to provide some guidance on how you can accomplish the same thing using NWE.

 

If you already have NWE deployed to your endpoints there is no need to configure or manage another solution. The question that needs to be answered is how to retrieve this data from NWE to feed your SIEM/Log solution. This is indeed possible, and with a little help from colleagues and peers (I can name you if you want) I started to play with an SQL query to retrieve such data from the NWE database. The following query is suitable to import NWE data into a SIEM/Log Management solution:

 

SELECT * FROM (SELECT 
      SE.PK_WinTrackingEvents,
      SE.EventUTCTIme,
      MA.MacAddress as src_mac,
      MA.LocalIp as src_ip,
      MA.MachineName,
      LOWER(PA.Path + FN.FileName) AS Source,
      MO.HashSHA256,
      LA.LaunchArguments AS SLA,
      CASE       
            WHEN SE.BehaviorFileOpenPhysicalDrive = 1 THEN 'OpenPhysicalDrive'
            WHEN SE.BehaviorFileReadDocument = 1 THEN 'ReadDocument'
            WHEN SE.BehaviorFileWriteExecutable = 1 THEN 'WriteExecutable'
            WHEN SE.BehaviorFileRenameToExecutable = 1 THEN 'RenameExecutable'
            WHEN SE.BehaviorProcessCreateProcess = 1 THEN 'CreateProcess'
            WHEN SE.BehaviorProcessCreateRemoteThread = 1 THEN 'CreateRemoteThread'
            WHEN SE.BehaviorProcessOpenOSProcess = 1 THEN 'OpenOSProcess'
            WHEN SE.BehaviorProcessOpenProcess = 1 THEN 'OpenProcess'
            WHEN SE.BehaviorFileSelfDeleteExecutable = 1 THEN 'SelfDelete'
            WHEN SE.BehaviorFileDeleteExecutable = 1 THEN 'DeleteExecutable'
            WHEN SE.BehaviorRegistryModifyBadCertificateWarningSetting = 1 THEN 'ModifyBadCertificateWarningSetting'
            WHEN SE.BehaviorRegistryModifyFirewallPolicy = 1 THEN 'ModifyFirewallPolicy'
            WHEN SE.BehaviorRegistryModifyInternetZoneSettings = 1 THEN 'ModifyInternetZoneSettings'
            WHEN SE.BehaviorRegistryModifyIntranetZoneBrowsingNotificationSetting = 1 THEN 'ModifyIntranetZoneBrowsingNotificationSetting'
            WHEN SE.BehaviorRegistryModifyLUASetting = 1 THEN 'ModifyLUASetting'
            WHEN SE.BehaviorRegistryModifyRegistryEditorSetting = 1 THEN 'ModifyRegistryEditorSetting'
            WHEN SE.BehaviorRegistryModifyRunKey = 1 THEN 'ModifyRunKey '
            WHEN SE.BehaviorRegistryModifySecurityCenterConfiguration = 1 THEN 'ModifySecurityCenterConfiguration'
            WHEN SE.BehaviorRegistryModifyServicesImagePath = 1 THEN 'ModifyServicesImagePath'
            WHEN SE.BehaviorRegistryModifyTaskManagerSetting = 1 THEN 'ModifyTaskManagerSetting'
            WHEN SE.BehaviorRegistryModifyWindowsSystemPolicy = 1 THEN 'ModifyWindowsSystemPolicy'
            WHEN SE.BehaviorRegistryModifyZoneCrossingWarningSetting = 1 THEN 'ModifyZoneCrossingWarningSetting'
      END AS Action,
      LOWER(SE.Path_Target + SE.FileName_Target) AS Destination,
      SE.LaunchArguments_Target AS TLA,
      se.HashSHA256_Target
FROM 
      dbo.WinTrackingEvents_P1 AS SE WITH(NOLOCK)
      INNER JOIN dbo.Machines AS MA WITH(NOLOCK) ON MA.PK_Machines = SE.FK_Machines
      INNER JOIN dbo.MachineModulePaths AS MP WITH(NOLOCK) ON MP.PK_MachineModulePaths = SE.FK_MachineModulePaths
      INNER JOIN dbo.Modules AS MO WITH(NOLOCK) ON MO.PK_Modules = MP.FK_Modules
      INNER JOIN dbo.FileNames AS FN WITH(NOLOCK) ON FN.PK_FileNames = MP.FK_FileNames
      INNER JOIN dbo.Paths AS PA WITH(NOLOCK) ON PA.PK_Paths = MP.FK_Paths
      INNER JOIN dbo.LaunchArguments AS LA WITH(NOLOCK) ON LA.PK_LaunchArguments = SE.FK_LaunchArguments__SourceCommandLine
UNION
SELECT
      SE.PK_WinTrackingEvents,
      SE.EventUTCTIme,
      MA.MacAddress as src_mac,
      MA.LocalIp as src_ip,
      MA.MachineName,
      LOWER(PA.Path + FN.FileName) AS Source,
      MO.HashSHA256,
      LA.LaunchArguments AS SLA,
      CASE       
            WHEN SE.BehaviorFileOpenPhysicalDrive = 1 THEN 'OpenPhysicalDrive'
            WHEN SE.BehaviorFileReadDocument = 1 THEN 'ReadDocument'
            WHEN SE.BehaviorFileWriteExecutable = 1 THEN 'WriteExecutable'
            WHEN SE.BehaviorFileRenameToExecutable = 1 THEN 'RenameExecutable'
            WHEN SE.BehaviorProcessCreateProcess = 1 THEN 'CreateProcess'
            WHEN SE.BehaviorProcessCreateRemoteThread = 1 THEN 'CreateRemoteThread'
            WHEN SE.BehaviorProcessOpenOSProcess = 1 THEN 'OpenOSProcess'
            WHEN SE.BehaviorProcessOpenProcess = 1 THEN 'OpenProcess'
            WHEN SE.BehaviorFileSelfDeleteExecutable = 1 THEN 'SelfDelete'
            WHEN SE.BehaviorFileDeleteExecutable = 1 THEN 'DeleteExecutable'
            WHEN SE.BehaviorRegistryModifyBadCertificateWarningSetting = 1 THEN 'ModifyBadCertificateWarningSetting'
            WHEN SE.BehaviorRegistryModifyFirewallPolicy = 1 THEN 'ModifyFirewallPolicy'
            WHEN SE.BehaviorRegistryModifyInternetZoneSettings = 1 THEN 'ModifyInternetZoneSettings'
            WHEN SE.BehaviorRegistryModifyIntranetZoneBrowsingNotificationSetting = 1 THEN 'ModifyIntranetZoneBrowsingNotificationSetting'
            WHEN SE.BehaviorRegistryModifyLUASetting = 1 THEN 'ModifyLUASetting'
            WHEN SE.BehaviorRegistryModifyRegistryEditorSetting = 1 THEN 'ModifyRegistryEditorSetting'
            WHEN SE.BehaviorRegistryModifyRunKey = 1 THEN 'ModifyRunKey '
            WHEN SE.BehaviorRegistryModifySecurityCenterConfiguration = 1 THEN 'ModifySecurityCenterConfiguration'
            WHEN SE.BehaviorRegistryModifyServicesImagePath = 1 THEN 'ModifyServicesImagePath'
            WHEN SE.BehaviorRegistryModifyTaskManagerSetting = 1 THEN 'ModifyTaskManagerSetting'
            WHEN SE.BehaviorRegistryModifyWindowsSystemPolicy = 1 THEN 'ModifyWindowsSystemPolicy'
            WHEN SE.BehaviorRegistryModifyZoneCrossingWarningSetting = 1 THEN 'ModifyZoneCrossingWarningSetting'
      END AS Action,
      LOWER(SE.Path_Target + SE.FileName_Target) AS Destination,
      SE.LaunchArguments_Target AS TLA,
      se.HashSHA256_Target
FROM 
      dbo.WinTrackingEvents_P0 AS SE WITH(NOLOCK)
      INNER JOIN dbo.Machines AS MA WITH(NOLOCK) ON MA.PK_Machines = SE.FK_Machines
      INNER JOIN dbo.MachineModulePaths AS MP WITH(NOLOCK) ON MP.PK_MachineModulePaths = SE.FK_MachineModulePaths
      INNER JOIN dbo.Modules AS MO WITH(NOLOCK) ON MO.PK_Modules = MP.FK_Modules
      INNER JOIN dbo.FileNames AS FN WITH(NOLOCK) ON FN.PK_FileNames = MP.FK_FileNames
      INNER JOIN dbo.Paths AS PA WITH(NOLOCK) ON PA.PK_Paths = MP.FK_Paths
      INNER JOIN dbo.LaunchArguments AS LA WITH(NOLOCK) ON LA.PK_LaunchArguments = SE.FK_LaunchArguments__SourceCommandLine) t
WHERE PK_WinTrackingEvents > ? ORDER By PK_WinTrackingEvents ASC

 

 

In this query the question mark “?” at the end of the last line needs to be automatically replaced by the previous highest entry already collected with the previous query execution. Each solution will have its own way of tracking and processing this query. In some solutions you may only need the portion between the main ()s group as they will build the rest automatically. Other solutions will probably require more work/tweaking.

 

For Netwitness for Logs, Chris Thomas created a post here with all the details needed to accomplish this integration. I'm sure the same can be done with Splunk, ArcSight, Elastic, <insert your favorite solution here> so please feel free to post your experience to the comments section of this post.

 

Happy Hunting,

 

Rui

Filter Blog

By date: By tag: