Recently Sophos X-Ops investigated a new series of limited attacks with malware that had unique characteristics that indicate its creators and operators spent considerable time and effort to create covert methods of communicating with, and issuing commands to, the impacted devices.
While performing our investigation, we found that the threat actor(s) had installed at least eight different types of malicious files inside of impacted devices.
As we saw in a previous incident, these attackers created some of these malicious files by modifying a few of the files that are used in the SFOS operating system, while others appeared to be close copies of “commodity” Linux malware, such as Gh0st RAT.
What follows is a defender’s analysis of the malware and its covert communications methods.
Hands in the cookies JAR
These attacks began with exploitation of CVE-2022-3236 which is detailed in Sophos Security Advisory sophos-sa-20220923-sfos-rce.
Parts of SFOS employ Java applications that run under the Jetty web server on the device, itself. The threat actors modified a small number of Java files that make up parts of the device’s internal functionality, adding additional code into the files. This method preserves the device’s own functions, so it remained operational despite the modifications after they overwrote the original files with their modified versions.
Java JAR files typically contain one or more of what are known as .class files; these .class files contain the functional programming of the Java application.
One of the files we discovered the attackers modified is a Java application named servlet-api-3.1.jar. The threat actors changed HttpServlet.class stored in this JAR to add some of their own code, recompiled the JAR with the modified .class file, and uploaded the JAR into the affected devices.
This JAR checks the validity of HTTP methods that the server might encounter in a web request header (such as a POST or a GET request). As such, it sits in a critical position where it can inspect characteristics of inbound web traffic.
The added code gave the JAR file the ability to serve as a backdoor for the threat actors. It also lay in wait for a user or administrator to attempt to log in to the device, captured the logins and passwords in real time, then encrypted the stolen credential data using a custom algorithm and wrote it out to a file in the /tmp/ directory on the device.
The backdoor functionality was quite sophisticated. The threat actor(s) responsible for this code built a few safeguards into the process to ensure that nobody but the threat actor(s) could use the backdoor code. For instance, the code added to this file parses the header contents of the inbound requests and checks for the presence of a “JSESSIONID” key in the Cookies header.
Content under this header value gets processed by the new code, which decrypts the contents of this JSESSIONID value using a method that uses the numeric values for the month and the day of the month to calculate the key, which means that the key used to decrypt the data changes every day, but is predictable by the algorithm.
The decrypted first byte of the web requests data stream contains a short value that points to one of seven different types of commands they can execute. In brief, the Trojanized code can list directories; read, write to, copy, delete, or rename individual files; or execute commands in the native shell on the device.
Figure 2 The command “cases” used by the modified httpservlet
There’s nothing unusual about this type of data; JSESSIONID is a normal, legitimate type of information that can be passed via a cookie to a Java servlet. The use of this method to instruct the malware to do this is incredibly subtle and very covert, and highly unusual in more conventional malware.
The attackers receive feedback telemetry from the trojanized file about both successful and unsuccessful attempts to use the trojan code functions.
Attackers drop a bad ELF shell stager
During the exploit process, the attackers Trojanized legitimate files normally present on the device (named screenmgr.pl and WebsocketServer.pm). The attackers modified the screenmgr file such that, when the attackers killed and restarted the process, it had (and could keep) ‘root’ level permissions. This file then sets up WebsocketListener, which then works with the trojanized version of WebsocketServer to provide Perl-based eval as a root user. Along with these modifications, we also saw it deliver a small ELF executable, in the form of a small blob of base64-encoded data.
The general purpose of this ELF binary (Linux/Loit-X) is to set the mount namespace of the process to the same as /proc/1/ns/mnt and call a shell. This binary provides a mount namespace breakout as long as the native procfs is not isolated from the context of the exploited process and as long as the process hasn’t been hardened by seccomp to restrict system calls to “setns”. Given services are leveraging seccomp to prevent calls to “setns”, amongst other hardening measures, and the exploit code does not appear to call this file it would seem this is a remnant from when the attackers were developing and testing their exploit and they may have been unsuccessfully targeting services directly at an early stage before pivoting their target to another process structure.
Custom Metasploit module
During the attacks on some devices, the threat actor(s) delivered a customized JAR Metasploit module based on an existing payload named Payload.java. On affected systems, we found that this file was written to the device’s file storage as a file named syslog-ng.cfg.
The Metasploit module was as close to “stock” from the company’s Github as possible, with the only changes being the configuration data used by the Metasploit module to define its command-and-control server address, and the port number it will connect to.
We were able to determine that, when this file was running, it would create a copy of itself named /tmp/~spawn[randomChars].tmp.dir. After each execution, the file tries to delete itself.
Malicious backdoor functionality in SessionAgent
We found at least six different variants of an ELF binary malware we refer to as Linux/Backdr-NQ. The malware named its main class CResoule and contained a configuration file encrypted using the RC4 algorithm.
It establishes persistence by appending its execution path to a file named /etc/rc.d/S00null that executes at bootup.
The malware contained several command-and-control addresses. The bot appears to use a time-based seed that randomizes a new AES key for each active connection session. The malware first sends this key to the C2 server then uses the key to encrypt outbound communication with the C2 while the connection is active. Its embedded config includes a path for an external AES-encrypted config file to be loaded as an override of its embedded config, such as /var/cache/update.log.
The malware has a feature that checks inbound traffic for a specific byte and executes various types of backdoor functions based on that value. The bot can be instructed to upload files to the C2 (or download file from there), modify its own configuration, execute a command on the device, or close the connection to the C2.
Termite malware delivered via Clientless VPN
Digging further into the impacted devices, we found data on some devices that pointed to yet another remote access trojan in use. The malware (which we now detect as Linux/Gognt-O) is a UPX-packed ELF binary, roughly 2.3MB in size. During its connection, the malware writes out a log line that includes the string “Termite (v [number]) starting…” with a very, very specific version number of 2.0200204206304400404
The malware is a typical backdoor with the added functionality of being able to serve as a SOCKS proxy, which would allow it to intercept the contents of some kinds of web traffic.
Another Gh0st RAT strikes
Some machines were the recipients of one of at least three variations on the Gh0st RAT ELF binary (detected as Linux/Rekoobe-A). As in the CVE-2022-1040 attack, the attackers built a malware that inspects all ping packets, waiting for a specially crafted ping packet that would not, otherwise, occur “in nature.”
The ping packet, if validated correctly, can be used to trigger the device into either opening a reverse shell back to the address provided by the attacker (that address being delivered within the ping packet’s “data” section), or it will bind and listen on port 31234 to accept a connection from a C2. The bot makes an additional validation check once a connection is established. This technique is known as Traffic Signalling, and is detailed as technique T1205 in the MITRE ATT&CK framework.
As we see, these targeted attacks mixed both custom and commodity malware seeking to create cover channels to control the devices. In addition, the attackers took steps to hide their tracks. Combined, these actions created a hard-to-detect attack the demonstrates a sophisticated threat actor seeking to maximize their control of the device while minimizing the risks of detection.
Indicators of Compromise (IoCs)
We are making IoCs available on our GitHub here.