In this post i want to talk about the SolarWinds breach occurred in 2020 giving the
emphasis to the backdoor inside SolarWinds.Orion.Core.BusinessLayer.dll.
This is not about threat intelligence but more to understand from a technical
perspective how an APT is able to evade detection for such a long time and maintain
persistence. At the end i will share some links if you are interested and want to
explore more.
Sunburst is a trojanized version of a signed plugin named SolarWinds.Orion.Core.BusinessLayer.dll. It was inserted into the software build of SolarWinds Orion products using another malware named SUNSPOT (more here). The backdoor was then distributed through software updates and installers to all of the customers.
The backdoor is a 32 bit signed dll written in .NET.
The fact that is signed by SolarWinds private key makes this malware extremely more evasive and difficult to detect. Sunburst code begins at OrionImprovementBusinessLayer.Initialize().
Here the hash of the string solarwinds.businesslayerhost.exe is being calculated and compared to the current process hash. This ensures that the program is running in the right context. After that the method makes a time check ensuring that sunburst is inside the system for at least 2 weeks, making the malware even more evasive under the radars of sandboxes trying to run it.
This method is called by a legitimate method in the program called RefreshInternal()
So basically whenever the dll will execute this normal routine the backdoor will be executed too in the background by another thread.
This is the hashing algorithm that will be always present from now on
Doing a research online about the constants in the algorithm we can see its using FNV hash function. All the reverse-engineered hashes are available here.
The program then continues calling OrionImprovementBusinessLayer.GetOrCreateUserID
This method has the purpose of creating an Unique ID of the machine. The UID is composed of:
- MAC address of the first network interface
- Domain name
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid
All of that is then passed to a MD5 hashing function. This function will be crucial for the DGA implemented inside the malware.
At the end of the method another method OrionImprovementBusinessLayer.Update is called, this method contains all the logic of sunburst.
ENVIRONMENT CHECK // 00
At execution Sunburst goes through an extensive list of known security process, drivers and services to ensure its not being executed inside a machine dedicated for analysis. The method responsible for this is OrionImprovementBusinessLayer.TrackProcess
OrionImprovementBusinessLayer.ProcessTracker.SearchAssemblies compares all the running processes to a hardcoded list of hashes of security related processes
Then Sunburst before initializing the connection with the C2 checks if the host
api.solarwinds.com resolves to an expected IP address
The above encoded string is passed as the parameter hostName and decoded gave: api.solarwinds.com
DOMAIN GENERATION ALGORITHM // 01
A Domain Algorithm Generator is the capability for a malware to dynamically generate domain hostname on the fly. DGA has a lot of benefits, the major one is probably the capacity to evade domain blacklisting
Talking about sunburst we can say that is not a real DGA because the top level domain always remains the same (avsvmcloud.com), this has a big downside, it's possible to make detection rule by simply doing something like: *.avsvmcloud.com
What stands out with sunburst is how the domain prefixes were generated in an unique way.
This is an example of URL generated by sunburst and used for C2 communications:
04jrge684mgk4eq8m8adfg7.appsync-api.us-east-2.avsvmcloud.com
You can find a list here
Starting with appsync-api.us-east-2.avsvmcloud.com
OrionImprovementBusinessLayer.GetStatus is responsible for concatenating the strings in the domain
domain1, domain2 and domain3 are hardcoded and defined as follows
domain3 can vary between the four different strings
The backdoor has also the capability to generate a pseudo-random URI
Here a little snippet not the full method
As you can see all the URIs are hardcoded inside the code. Other generated URIs are:
- fonts/woff/
- swipt/upd/
- swip/Events/
- swip/Upload.ashx/
A new thread will be spawned and will run httpHelper.Initialize method used to communicate with the C2
After this sunburst composes a JSON payload with information about the infected host and sends it to the C2 server. The payload contains data such as UID and session ID
Another way used by Sunburst to blend itself inside the traffic is to modify the User-Agent of the requests. Depending on situation and the use case the user agent could have taken two different values:
- Microsoft-CryptoAPI/
- SolarWindsOrionImprovementClient/
This is especially useful to mimic legitimate traffic, Microsoft-CryptoAPI was used at early stage of the attack inside the DNS queries. Starting the HTTP communications the backdoor switches user-agent and starts using SolarWindsOrionImprovementClient masquerading as OIP (Orion Improvement Program) protocol.
The anatomy of the operations was basically to use DNS at the early stage for listening and information gathering, once all the checks were done the communications switched to HTTP and the backdoor started executing commands
Sunburst capabilities as a backdoor are very basic, inside the program are defined as jobs
Everything a normal backdoor would do like modify files, kill/run processes, upload stuff...
DNS HOSTNAME ENCODING // 02
Inside 04jrge684mgk4eq8m8adfg7.appsync-api.us-east-2.avsvmcloud.com we have seen how sunburst concatenates .appsync-api and .us-east-2 subdomains but not how the random 04jrge684mgk4eq8m8adfg7 is generated
This is how the random string subdomain can be divided
One of the first methods encountered was OrionImprovementBusinessLayer.GetOrCreateUserID, as we have seen it basically gets a UID using current system configurations (domain name, reg key and MAC address of first available network interface). The UID returned from this function is encoded using CreateSecureString method through OrionImprovementBusinessLayer.CryptoHelper.Base64Encode
The encoded string: K8gwSs1MyzfOMy0tSTfMskixNCksKkvKzTYoTswxN0sGAA= resolves to ph2eifo3n5utg1j8d94qrvbmk0sal76c
This value is then concatenated with a character generated by OrionImprovementBusinessLayer.CryptoHelper.CreateString.
Other methods responsible for the random subdomain generation are GetPreviousString, GetNextString, GetNextStringEx
The last part of the generated subdomain is the encoded domain name of the machine defined in OrionImprovementBusinessLayer.CryptoHelper.dnStrLower
The value of OrionImprovementBusinessLayer.CryptoHelper.dnStr is passed in the constructor of CryptoHelper class using OrionImprovementBusinessLayer.CryptoHelper.DecryptShort method
CryptoHelper class is then initialized as this
UserID is the previously generated ID and domain4 is the domain of the compromised machine
DecryptShort method first checks if all the characters of the domain are part of this string: 0123456789abcdefghijklmnopqrstuvwxyz-_. If it is the case the domain will be encoded using OrionImprovementBusinessLayer.CryptoHelper.Base64Decode. Otherwise it will be prepended with "00" and encoded using OrionImprovementBusinessLayer.CryptoHelper.base64Encode
CONCLUSION // 03
That's all, you can find a python script for decoding the domain names generated with the DGA algorithm here
Links i used for researching
- https://vx-underground.org/Samples/Families/SolarwindsBreach --> samples
- https://www.techtarget.com/whatis/feature/SolarWinds-hack-explained-Everything-you-need-to-know
- https://www.cisa.gov/news-events/analysis-reports/ar21-105a
- https://cloud.google.com/blog/topics/threat-intelligence/evasive-attacker-leverages-solarwinds-supply-chain-compromises-with-sunburst-backdoor
- https://www.microsoft.com/en-us/security/blog/2020/12/18/analyzing-solorigate-the-compromised-dll-file-that-started-a-sophisticated-cyberattack-and-how-microsoft-defender-helps-protect/
- https://cloud.google.com/blog/topics/threat-intelligence/sunburst-additional-technical-details
- https://securelist.com/sunburst-connecting-the-dots-in-the-dns-requests/99862/
- https://mp.weixin.qq.com/s/v-ekPFtVNZG1W7vWjcuVug