#Solorigate : SUPERNOVA forensics using Code Property Graph

#Solorigate : SUPERNOVA forensics using Code Property Graph

The fallout of SolarWinds compromise has resulted in a bevy of new malware families, each with different characteristics and behaviors.

SolarWinds advisory : https://www.solarwinds.com/securityadvisory#anchor2

In this post, we will focus on the SUPERNOVA trojan, describing how this weaponized DLL was patched into Solarwinds SDLC (Software Development Life Cycle) post infiltration. Further, we will discuss anti evasion techniques employed by the APT actor.

The SUPERNOVA web shell implant is a trojanized copy of a legitimate ‘app_web_logoimagehandler.ashx.b6031896.dll’ library used by SolarWinds Orion web application.The purpose of the original DLL is to serve up a user-configured logo to web pages in the Orion web application. Let’s visually illustrate this benign functionality that serves a legitimate workflow in the Orion web application

Normal functionality of benign, unaltered DLL (app_web_logoimagehandler)

Web form of Orion with Logo rebranding workflow
The original ProcessRequest()

This module is purposed to return the logo image (white label based rebranding feature) configured by the user to various web pages of the SolarWinds Orion web application.

This is done through the ProcessRequest() method of the LogoImageHandler class.

Altered app_web_logoimagehandler DLL with backdoor to C2 server

Trojanized workflow during rebranding
Trojanized ProcessRequest that accepts the attacker controlled input

The DynamicRun() method is heart of the SUPERNOVA webshell.

This method accepts

  • C# source code blob,
  • the class to instantiate,
  • the associated method to invoke,
  • and the method’s arguments.

These parameters will be used to compile and execute an in-memory .NET assembly sent by the attacker over HTTP channel and after invoking successfully the response is packaged and returned to the attacker.

This functionality allows the attackers to compile and execute .NET payloads as and when needed, within the context of SolarWinds Orion Web Application. This mechanism does not leverage any exploit, but simply abuses weaponizes a fundamental .NET feature called MetaProgramming. This is powerful, as it allows the malware to execute robust compiled code on the fly, without dropping any additional files to the file system or running any obvious commands being monitored over the wire.

Hacking the SDLC to weaponize C# MetaProgramming

Writing new programs at runtime and manipulating programs at runtime aren’t mutually exclusive concepts.The classic definition for a metaprogram is “a computer program that writes new computer programs.” This sounds a lot like the definition of a compiler. A compiler for a programming language like C# could be thought of as the ultimate metaprogram, because its only job is to produce other programs from source code.

The .NET framework provides compilers for C#, VB and JScript. These are the classes

  • Microsoft.CSharp.CSharpCodeProvider,
  • Microsoft.VisualBasic.VBCodeProvider and
  • Microsoft.JScript.JScriptCodeProvider

These classes are thin wrappers around the native compilers csc.exe, vbc.exe and jsc.exe. Since theses compilers operate on files on the file system, the wrapper classes need to save the source files into temporary files to be able to pass them to the compilers.

Likewise, the compiled assemblies are (temporarily) saved to disk and then loaded by the wrappers. Because of that, true in-memory assembly generation is not possible with these classes. Also, these classes need full-trust permissions. The compiler option can be set with the class CompilerParameters. Among others, there is a property called GenerateInMemory. If this is set to true, the compiled assemblies get deleted after being loaded into memory. Using this setting, an in-memory generation can be mimicked. On the other hand, assemblies that are loaded into memory but deleted from disk cannot be referenced by newer compilations. So if for instance different assemblies must be generated that reference each other, the property GenerateInMemory must be set to false.

Examples of compiling metaprograms based on CodeDom (predates Roslyn) and Roslyn are presented here

CodeDom based: https://gist.github.com/conikeec/59d5c2e3652dd49cf5fefd38113f4b31

Roslyn based : https://gist.github.com/conikeec/6e13e0d558cc244689a44c9a4f0ff938

SUPERNOVA Evasion techniques

  • Not the same actor as #SUNBURST (UNC2452) as trojanized DLL is not digitally signed
  • The try { … } catch(Exception) { } block sinkholes any exception generated leading to no log being created which further on does not trigger rules. How did this change request pass simple code review?
  • GenerateInMemory is set to true leading to source code blob not leave any traces of persisting source files to disk prior to passing them of to the compiler
  • The APT (advanced persistent threat) actor possibly infiltrated the SDLC process of SolarWinds Orion in order to study version compatibility as well (needed some formal knowledge to understand whether he/she should use a CodeDom or Roslyn based meta program — refer section above)

Using Code Property graph to detect webshell/backdoor patterns

What is Code Property Graph uniquely position to detect complex backdoor patterns?

The code property graph is a concept based on a simple observation: there are many different graph representations of code (abstract syntax tree, control flow graph and data flow graph), and patterns in code can often be expressed as patterns in these graphs. While these graph representations all represent the same code, some properties may be easier to express in one representation over another. So, why not merge representations to gain their joint power, and, while we are at it, express the resulting representation as a property graph, the native storage format of graph databases, enabling us to express patterns via graph-database queries.

Creating policy using NGSAST to detect SUPERNOVA

  1. Autodetect SOURCE (EntryPoints) — functions that are public and accept HTTPContext from external calls (via API/Web from)
  2. Autodetect SINKS (ExitPoints) — sys-call, compiler assembly call, network, memory based, etc
  3. Search graph for empty catch block associated with a try block and get encapsulating block to determine if it contains any SINKS from (2)
  4. Determine taint reachability from SOURCE to SINK that passes through compiler assembly function(s)

I use Address space layout randomization (ASLR) as an exploit protection technique, so am I immune to web-shells based backdoors?

Address Space Layout Randomization (ASLR) is a computer security technique which involves randomly positioning the base address of an executable and the position of libraries, heap, and stack, in a process’s address space. The random mixing of memory addresses performed by ASLR means that an attack no longer knows at what address the required code (such as functions or ROP gadgets) is actually located. That way, rather than removing vulnerabilities from the system, ASLR attempts to make it more challenging to exploit existing vulnerabilities..

ASLR was introduced in Windows Vista and is in all newer versions. To make use of it, the executable needs to be compiled with /DYNAMICBASE option as well. OS based DLLs have it by default.

ASLR is not supported when the executable or DLLs are not built with ASLR support. Although Windows 8 and Windows 10 try to overcome this limitation (e.g., force ASLR in Windows 8), there are still exceptions that many times render the ASLR protection ineffective. Older version of Windows and legacy programs are particularly prone to this limitation. In addition, ASLR on 32-bit systems suffers from low entropy, making it vulnerable to brute force and similar attacks.

ASLR aims to prevent an attack from reliably reaching its target memory address. ASLR does not focus on trapping the attack, rather on making the attack unlikely to work. Once the shellcode jumps to the wrong address during the exploit (due to the memory randomization), the program behavior is undefined. The process might receive an exception, crash, get stuck or simply continue with inconsistent behavior as a result.

ASLR does not give any alerts about attack attempts. When a vulnerability is exploited and fails (due to ASLR’s memory randomization), no alert or attack indication is received. Essentially ASLR doesn’t ‘know’ when an attack happened.

Forensic information about an attack, exploitation and shellcode is crucial for any serious forensic investigation. Exploited processes, memory dumps and call stacks can be used to identify, fingerprint and tag exploits. ASLR cannot provide this information because it doesn’t actually know if an attack happens or at which point it was stopped.

Since Address Space Layout Randomization was introduced in Windows OS, it has been bypassed many times by real-world exploits and attacks. Attackers continuously develop new techniques to defeat ASLR defense. Bypass techniques include

  • using ROP chain in non-ASLR modules (e.g., CVE 2013–1347),
  • JIT/NOP spraying (e.g., CVE-2013–3346),
  • as well as memory disclosure vulnerabilities and other techniques (e.g., CVE-2015–1685, CVE-2015–2449, CVE-2013–2556, CVE-2013–0640, CVE-2013–0634).


We at ShiftLeft have been studying and provisioning backdoor/insider detection policies using code property graph since mid 2019. Speak to us and we can help assess and recommend more efficient processes and procedures.

#Solorigate : SUPERNOVA forensics using Code Property Graph was originally published in ShiftLeft Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

*** This is a Security Bloggers Network syndicated blog from ShiftLeft Blog – Medium authored by Chetan Conikee. Read the original post at: https://blog.shiftleft.io/solorigate-supernova-forensics-using-code-property-graph-b92b56e48bb0?source=rss—-86a4f941c7da—4