Command & Control (C2) frameworks are a very sensitive component of Red Team operations. Often, a Red Team will be in a highly privileged position on a target’s network, and a compromise of the C2 framework could lead to a compromise of both the red team operator’s system and control over beacons established on a target’s systems. As such, vulnerabilities in C2 frameworks are high priority targets for threat actors and Counterintelligence (CI) operations. On September 20, 2022, HelpSystems published an out-of-band patch for Cobalt Strike which stated that there was potential for Remote Code Execution (RCE).
Cobalt Strike is one of several third-party C2 frameworks IBM Security X-Force Red leverages to simulate different threat actors when delivering adversary services for clients. The Adversary Simulation team at IBM Security X-Force Red performed a diligent review of the patch to ensure that there was no impact to our clients networks, data, and systems.
Our analysis proved that RCE was indeed possible and that the update in version 4.7.1 was insufficient to mitigate the impact of the vulnerability. We discovered that creating Swing components from user input allows users to create arbitrary Java objects in the class path and invoke their setter methods, which can lead to remote code execution in specific cases. X-Force requested a new CVE (CVE-2022-42948) and provided the technical details of the vulnerability to HelpSystems to aid in the development of a new patch. This post outlines the analysis process conducted to make this evaluation: patch analysis, root cause review and vulnerability weaponization.
On September 20, 2022, HelpSystems published an out-of-band update for Cobalt Strike to fix an issue discovered in Cobalt Strike version 4.7. The vulnerability was marked as Cross-Site Scripting (XSS) and was identified with the number CVE-2022-39197. Analysis revealed that the XSS vulnerability could be triggered by manipulating some client-side UI input fields, by simulating a Cobalt Strike implant check-in or by hooking a Cobalt Strike implant running on a host. It was stated in the release notes that this vulnerability could lead to RCE which was the impetus for performing this research.
CVE-2022-39197 Patch Analysis
As a first step in the analysis process, we decompiled the Cobalt Strike Java client application. This allowed us to develop an understanding of where the vulnerability had been identified and how it had been mitigated.
As stated within the out-of-band patch notes, X-Force identified a function within BeaconC2.class that checks if the XSS mitigation flag has been set within the TeamServer properties file.
Further analysis of how new Cobalt Strike implants are registered within the UI, X-Force identified the XSS mitigation validation was implemented within BeaconEntry.class.
Analysis of how the Cobalt Strike implant list is validated before they are presented to the user, X-Force was able to identify the specific parameters the XSS validator function leverages and the class (CommonHTMLUtils.class) storing the validation functions.
X-Force’s analysis of the CommonHTMLUtils class, revealed two validator functions (potentialXSS and potentialUserNameXSS). It is not clear why HelpSystems implemented two separate validators, one would suffice to perform input sanitization. Additionally, it should be noted that, while these checks function correctly they are unnecessarily complex. To successfully render HTML within Java Swing components, the component text has to start with <html>. Any other text will cause the element to render as plain-text. A universal validator could simply check if a string starts with < and return true if it does. Additionally, it would be possible to insert a whitespace as the beginning of the text to render those inputs inert instead of dropping them completely.
Initial analysis of the validator functions immediately raised some concerns that the Cobalt Strike RCE vulnerability was still exploitable after the patch was applied. X-Force Red identified the note field was not subject to the input validation which was leveraged to develop a remote code execution (RCE) payload. Additionally, any other UI components that could receive data directly from a Cobalt Strike implant would also be vulnerable to this attack. Such components would include the process list and the file explorer dialog.
Swing Components and HTML support
The Cobalt Strike interface is built on top of the Java Swing framework. This framework provides developers with a graphical user interface for Java programs. The image below shows the hierarchy of Java Swing components.
X-Force discovered that it was possible to include HTML code inside a Swing component. If a string’s contents started with the keyword <, the library would parse the content as HTML. The Java code snippet below demonstrates this concept.
Running the code snippet above will create a new JFrame, which contains a JLabel that uses HTML to style the label body. In this case, part of the text is rendered as an HTML heading.
While the content is successfully parsed as HTML, the impact in this case is minimal. After testing a variety of XSS techniques, X-Force noted a unique behavior in the interface after injecting an HTML <object> tag. The two red question marks, in the image below, indicated that the label attempted to render the <object> tag unsuccessfully.
Further research revealed that Java components could be included in the malformed string through the use of an HTML <object> tag, which could potentially allow for the creation of any Java Swing object. We tested and confirmed this by adding a Swing JButton Object which was successfully parsed and rendered, as shown in the image below.
A review of the Java SDK showed that the handler for any given HTML.Tag.OBJECT exists within the ObjectView class, which can be found within the HTMLFactory class creation method.
A snippet of the processing logic for the HTML.Tag instance is shown in the image below:
The function in the ObjectView class responsible for loading the element is called create Compoment(), as shown in the image below.
The createCompoment() function will initialize an instance of the specified class and then check if the initialized object is an instance of Component. If it is, it will return the object. If it is not, it will call getUnloadableRepresentation(). The screenshot below shows this function and explains why X-Force saw two red question marks in our previous test case.
A key component of the ObjectView class is the setParameters() function, which checks whether any parameters were specified on the attributes of an HTML element. Next, setParameters() checks whether the class that was loaded contains any write methods for the HTML element’s parameter and calls the appropriate method within the class with the specified value. The full view of setParameters() is shown in the image below.
As an example of calling a function within a subclass of java.awt.component with just one string parameter, consider the following HTML content being sent to the parser.
<html> <object classid=“HelloByName”> <param name=”my_name” value=”Rio”></object>
The parser will try to create an instance of the class HelloByName, check if the class is a subclass of java.awt.Component, and call the setter method for the my_name parameter. This example demonstrates how the sett functions can be called with one string parameter in classes that are a subclass of java.awt.Component. Manually searching for a method and class that meets these criteria is non-trivial, but several code analysis tools offer capabilities to solve this problem in a largely automated manner. For this phase of research, X-Force chose to use an open-source code analysis tool called Tabby.
Tabby’s main use case is to discover Java deserialization gadgets. It supports several input formats, including Java JAR files, and can export its analysis to a Neo4j database. Within Neo4j graph database it is possible to use the Cypher query language to identify elements that match specific criteria. This can greatly reduce the search-space when performing code analysis.
X-Force discovered forty-eight functions that met the criteria mentioned earlier. These functions were limited in complexity which allowed X-Force to manually review each of them. Most of these functions were part of the Swing framework and did not provide anything that could leverage to trigger RCE. However, X-Force eventually found the setURI() function within the JSVGCanvas class, the logic of which is shown in the image below.
To test the potential XSS resulting from processing an SVG file, X-Force inserted the HTML listed below in the note field on a Cobalt Strike UI.
<html><object classid="org.apache.batik.swing.JSVGCanvas"><param name="URI" value="http://127.0.0.1:8000/1.svg"></object>
Unfortunately, this test yielded the exception shown below, which indicates that the SVG parser tries to load a new class: org.mozilla.java.script.Scriptable. This meant that the XML parser had it is own set of handlers for different types of tags inside SVG XML file.
This reference to the Batik library in the exception handler led X-Force to Batik’s official documentation, which explained how Apache Batik allows developers to call Java code by including a Java JAR file reference within a SVG script element.
With the information gained from Batik’s documentation, X-Force built and injected a SVG file containing a custom Java code within the note field in the Cobalt strike UI.
Figure 1: Creation of SVG file
Figure 2: Creating a directory to make the directory structure required to initialize
Figure 3: PwnME Java code
Figure 4: Custom Java Manifest file
Figure 5: Compilation of Java code
Figure 6: Injection of SVG file into Cobalt Strike note field
As shown in the image below, this test successfully triggered the vulnerability and executed /usr/bin/xcalc, which is a common way to demonstrate a proof-of-concept exploit.
It should be noted here that this is a very powerful exploitation primitive. Since we can write a payload in Java, this means that we can construct a fully featured cross-platform payload that would be able to execute code on the user’s machine regardless of the operating system flavor or architecture.
Triggering RCE Through the Beacon
Although X-Force could trigger this vulnerability from the perspective of an operator with authenticated access in the Cobalt Strike UI, a malicious actor would most likely seek to trigger this vulnerability remotely by manipulating a real beacon in memory or simulating such a beacon. As shown in the patch analysis, HelpSystems introduced some string-based filters for fields that could be easily tampered by a remote attacker. Public tooling already exists to perform such tests, for example CobaltStrikeParser created by Sentinel One.
However, as explained in the patch analysis, X-Force realized that the patch was incomplete. A number of areas within the Cobalt Strike UI were not being validated and would thus still allow an attacker to achieve RCE. For example, an attacker would still be able to achieve RCE by hooking an implant process and injecting HTML into the process name portion of the data structure returned by calls to Process32Next. This data is rendered in the Cobalt Strike UI when an operator requests a graphical process listing. Typically, however, operators tend to favor running the ps command in the Cobalt Strike console in place of opening the graphical menu interface.
Another area that remained vulnerable was the graphical file explorer menu. This presented a much greater threat since it is a common workflow for operators to use this feature to explore the operating system or some universal naming convention (UNC) based paths. By hooking calls to FindNextFileA within the implant, we were able to manipulate the output in a similar fashion to achieve RCE on the Cobalt Strike UI.
To trigger the exploit, X-Force used Fermion. Fermion is a cross-platform Electron application that leverages Frida-Node to ease the development of Frida based instrumentation functions.
The image below shows Fermion injecting the Cobalt Strike implant process and loading the function instrumentation logic.
When the operator opens the File Browser of the affected implant, the vulnerability triggers, resulting in the execution of arbitrary code as shown in the following image.