Get Started

          Detecting SUNBURST/Solarigate activity in retrospect with Zeek

          The threat actors who created SUNBURST went to extraordinary lengths to hide Command-and-Control (C2) traffic by mimicking the nature of communication patterns used by legitimate software within the SolarWinds package.

          The contents of the C2 communications are encrypted and obfuscated, but there are still ways to identify malicious traffic using out-of-the-box Zeek logs and a little “log craft”. This blog demonstrates these methods and shows how you can use Zeek to detect even this level of cunning evasion tactics in your own retrospective hunts and forensic investigations. You’ll also want to check our wider set of Zeek and Suricata IOCs, as described by fellow Corelighters Aaron Soto and Alex Kirk here

          Let’s now have a look at one of the C2 communications used by SUNBURST.

          The malicious software attempts to mimic legitimate communications associated with the “Orion Improvement Program (OIP)”. This software is part of the SolarWinds package and does things like check for updates and licensing and it normally reaches out to a set of SolarWinds domains. 

          In order to mimic this software’s behaviour over the network, the attacker uses User-Agents normally expected for OIP, for example:

          SolarWindsOrionImprovementClient/2.2.332.0
          SolarWindsOrionImprovementClient/3.0.0.382


          Figure 1: Broadly querying Zeek’s http.log in Splunk for OIP User-Agents using wildcard (*) search function.

          In an example of the lengths the attackers went to in order to hide in plain sight, they used a User-Agent that was correct in the exact context of the legitimate Orion deployment, even down to the correct version number. A decompiled version of the malicious code shows that it checks on the infected system for the version of the legitimate OIP binary, and then uses that version number to construct its own user agent which it then uses in its own C2 communications. If the binary can’t be found, then it defaults to: 

          SolarWindsOrionImprovementClient/3.0.0.382

          Here is a Wireshark view of a decrypted version of the HTTP request by the malicious binary:

          You’re probably thinking: “Yes yes, but it’s encrypted so you can’t see the User Agent!” While some orgs can and will decrypt, let’s assume here that decryption isn’t available as that will often be the case. This then brings us up to the part where Zeek shines: analysis around encrypted traffic.

          In many proxied networks, a host contacts a proxy server to create the encrypted channel to the C2. As an HTTP CONNECT method, Zeek sees this traffic and logs it in http.log. There are two key components to highlight:

          1. The “uid” field within Zeek’s logs is a unique identifier given to each connection based on its 5-tuple. If Zeek sees subsequent activity using this same tuple (such as ssl) it logs this activity to separate files, like conn.log, http.log, and ssl.log – all interlinked with the same uid.
          2. Research indicates that the User Agent of OIP is a) unique to OIP and b) contained in the client’s initial CONNECT request for the proxy to create the encrypted tunnel. Zeek sees this and logs the CONNECT to http.log. This is key, and obviously will only work if such a HTTP proxy exists in your environment, which is true for many organizations.

          The proxy then creates an encrypted connection on port 443, but there are still inspectable elements of this connection that Zeek can parse without breaking and inspecting it, logged in Zeek’s ssl.log and x509.log. The logs will all have the same uid, so we can programmatically cross-reference or “JOIN” various aspects of a connection together. This is one of the powers of Zeek that becomes clearer the longer you use it: it’s ability to help analysts make fast sense of connections across ports and protocols 

          One of the fields logged into ssl.log is server_name, which relates to the name of the server contained in the certificate. The User-Agent is no longer visible in ssl.log as it’s encrypted, but we can cross-reference the uid and match the user_agent in http.log with the server_name in ssl.log!

          With this new context let’s use a SIEM query to look at what server names are visited by the legitimate OIP. I’m using Splunk here, but you could use whatever SIEM you have. You’ll also need to change the sourcetype and other details to suit your own environment.

          sourcetype=http
          user_agent="SolarWindsOrionImprovementClient/*"
          | join type=inner uid
          [| search sourcetype=ssl | table uid,server_name]
          |dedup user_agent server_name
          | table user_agent server_name

          Now all we need to do is look for when the User Agent is SolarWindsOrionImprovementClient/* but the server isn’t a legit SSL server like api.solarwinds.com or downloads.solarwinds.com. Any such activity would then show the malicious C2 trying to hide by using the right User-Agent, but connecting to the wrong servers.

          sourcetype=http
          user_agent="SolarWindsOrionImprovementClient/"
          | join type=inner uid
          [| search sourcetype=ssl | table uid,server_name]
          | search server_name!=".solarwinds.com"

          Using this method, we now have access to the x509.log, and artifacts within ssl.log like the TLS fingerprints JA3 and JA3S that create new detection and hunting opportunities. If anyone reading this is doing research on JA3/JA3S/JARM artifacts in relation to SUNBURST, reach out on the Zeek slack and let’s chat.

          Lastly, keen observers may note that the requested domain is also contained directly within the proxy CONNECT request in http.log, and as such you can do a simpler search, which wouldn’t expose you to the richer details contained in other Zeek logs, but could also work for detection:

          sourcetype=http method=CONNECT
          user_agent="SolarWindsOrionImprovementClient/"
          uri!=".solarwinds.com:443”

          There are yet more complex ways to use Zeek to detect malicious activity, but this post shows some simple examples of how Zeek can be used to detect parts of SUNBURST traffic using out-of-the-box Zeek logs with no further enrichments or extensions.

          Hopefully this blog is helpful for organizations looking for ways to assist in detecting SUNBURST activity and shows how Zeek can be used in a practical setting to good effect.  

          #SUNBURST #SolarWinds #solarigate #zeek #DFIR 

          References:

           

          Ben Reardon – Corelight Labs Researcher

           

          Search

            Recent Posts