- We discovered a new sophisticated backdoor targeting Linux endpoints and servers
- Based on Tactics, Techniques, and Procedures (TTPs) the backdoor is believed to be developed by Chinese nation-state actors
- The backdoor masquerades itself as polkit daemon. We named it RedXOR for its network data encoding scheme based on XOR. The malware was compiled on Red Hat Enterprise Linux
- We provide recommendations for detecting and responding to this threat below
Monitor your cloud environments for RedXOR and other Linux malware. Protect 10 servers for free with the Intezer Protect community edition.
Intro2020 set a record for new Linux malware families. New malware families targeting Linux systems are being discovered on a regular basis. Backdoors attributed to advanced threat actors are disclosed less frequently. We have discovered an undocumented backdoor targeting Linux systems, masqueraded as polkit daemon. We named it RedXOR for its network data encoding scheme based on XOR. Based on victimology, as well as similar components and Tactics, Techniques, and Procedures (TTPs), we believe RedXOR was developed by high profile Chinese threat actors. The samples, which have low detection rates in VirusTotal, were uploaded from Indonesia and Taiwan, countries known to be targeted by Chinese threat actors. The samples are compiled with a legacy GCC compiler on an old release of Red Hat Enterprise Linux, hinting that RedXOR is used in targeted attacks against legacy Linux systems. During our investigation we experienced an “on and off” availability of the Command and Control (C2) server indicating that the operation is still active.
Connections to Chinese Threat ActorsWe uncovered key similarities between RedXOR and previously reported malware associated with Winnti umbrella threat group. These malware are PWNLNX backdoor and XOR.DDOS and Groundhog, two botnets attributed to Winnti by BlackBerry. The below samples can be used for reference:
- Use of old open-source kernel rootkits: RedXOR uses an open-source LKM rootkit called “Adore-ng” to hide its process. Based on a FireEye report Winnti used this rootkit in their “ADORE.XSE” Linux backdoor. Embedding open-source LKM rootkits is a common Winnti technique. The group has been documented using Azazel and Suterusu.
- The CheckLKM function name used by RedXOR has also been used in PWNLNX and XOR.DDOS.
- Provides the operator with a pseudo-terminal: RedXOR uses Python pty shell by importing the python pty library. PWNLNX implements the pty shell function in c.
- Encoding network with XOR: The backdoor encodes its network data with a scheme based on XOR. Encoding network data with XOR has been used in previous Winnti malware including PWNLNX.
- Persistence service name: As part of its persistence methods, RedXOR attempts to create a service under rc.d. The developer added “S99” before the name of the service to lower its priority and make it run last on system initiation. This technique was used in XOR.DDOS and Groundhog samples where the malware developer added “S90” to the service name.
- Main functions flow: PWNLX and RedXOR have a main function which is in charge of initialization. In both backdoors, the main function calls another function which is in charge of the main logic. The main logic function names are main_process in RedXOR and MainThread in PWLNX. Both main functions daemonize the process to detach from the terminal and run in the background.
- XML for file listing: RedXOR’s directory function and PWNLNX’s getfiles function are both in charge of directory listing. Their code flow implementation is different, however, as both malware send the directory listing as an XML file to the C2 server. Figure 2 shows the XML structure used in PWNLNX and RedXOR. The file’s data used in both functions are: path, name, type, user, permission, size, time.
- Legacy Red Hat compilers: RedXOR and PWNLNX were both compiled with a Red Hat 4.4.7 compiler. This compiler is the default GCC compiler on RHEL6.
- Chown similarity: Both PWNLNX and RedXOR change the file’s user and group owner to a large ID. The same technique has been used by the XOR.DDoS malware as referenced in the analysis by MalwareMustDie.
Figure 3: Similarity between PWNLNX and RedXOR of the UID and GID used with “lchown” function call
- Overall flow and functionalities: The overall code flow, behavior, and capabilities of RedXOR are very similar to PWNLNX. Both have file uploading and downloading functionalities together with a running shell. The network tunneling functionality in both families is called “PortMap”.
- Unstripped ELF binaries: Malware developers will often tamper with a file’s symbols and/or sections, making it harder for researchers to analyze them. However, RedXOR and various Winnti malware, including PWNLNX and XOR.DDOS, are unstripped.
Technical AnalysisThe samples are both unstripped 64-bit ELF files called po1kitd-update-k. Uploaded to VirusTotal from Taiwan and Indonesia, they are low detected at the time of this writing.
Malware InstallationUpon execution RedXOR forks off a child process allowing the parent process to exit. The purpose is to detach the process from the shell. The new child determines if it has been executed as the root user or as another user on the system. It does this to create a hidden folder, called “.po1kitd.thumb”, inside the user’s home folder which is used to store files related to the malware. The malware creates a hidden file called “.po1kitd-2a4D53” inside the folder. The file is locked to the current running process, seen in Figure 5, essentially creating a mutex. If another instance of the malware is executed, it also tries to obtain the lock but ultimately fails. Upon this failure the process exits.
ConfigurationThe malware stores the configuration encrypted within the binary. In addition to the Command and control (C2) IP address and port it can also be configured to use a proxy. The configuration includes a password, as can be seen in Figure 9. This password is used by the malware to authenticate to the C2 server.
Communication with the C2The malware communicates with the C2 server over a TCP socket. The traffic is made to look like HTTP traffic. Figure 11 shows a pseudo-code representation of the function used by the malware to prepare data that is to be sent to the C2 server. First, it fills the buffer with null bytes. The request body is XORed against a key. The malware uses the buffer length as the key. This value is also passed into the function as the “total_length” argument.
0x0 JSESSIONID as int
0x8 Content-Length as long
0x10 Total-Length as long
0x18 Response bodyThe content length is the length of the response body but also used as the key. The total length value is used as a constant which is added to the key in each iteration. The JSESSIONID value holds the command ID for the job the C2 wants the malware to perform.
CommandsThe C2 server tells the malware to execute different commands via a command code that is returned in the “JSESSIONID” cookie. The codes are encoded as decimal integers. A full list of commands supported by the analyzed malware sample are shown in the table below. They can be grouped into command types. Commands in the 2000 range provide “filesystem” interaction, 3000 handle “shell” commands, and 4000 handle network tunneling. Table 1: List of commands supported by the malware
|2056||Execute with system|
|2062||Create new folder|
|2066||Write content to file|
|3058||Exec shell command|
System InformationWhen the malware first contacts the C2 server it sends a password encoded in the request body. The C2 server responds with the command code 0 to collect system information. The data collected about the system by the malware is listed in the table below. The data is serialized into a URL query-like string, encrypted and then sent as the request body. Table 2: Data collected by the malware and sent back to the C2 server
|hostip||IP||Hardcoded to 127.0.0.1|
|softtype||Hardcoded to “Linux”|
|hosttar||Username||Possibly “host target”|
|hostos||Distribution||Extracted from /etc/issue or /etc/redhat-release|
|hostmem||Amount of memory||/proc/meminfo|
|hostpack||Hardcoded to “Linux”|
|lkmtag||Is rootkit enabled|
|kernel||Kernel version||Extracted from uname|
Update FunctionalityThe malware can be updated by the threat actor. This is performed by sending command code 8 to the malware. When the malware receives this code the following actions are taken:
- The malware opens the mutex file for writing.
- It sends a request with the command code 8 and an empty request body to the C2 server.
- The response body from the server is written to the mutex file. The response body is not encrypted.
- The lock is released on the mutex file.
- The malware executes “chmod” to set the execution flag on the file via the libc system function.
- The malware sleeps and tries to obtain the lock on the file again when it wakes up. If it fails, it assumes the update was successful, closes the connection to the C2 server and exits.
Shell FunctionalityThe malware has the ability to provide its operator with a “tty” shell. If a shell is requested via the command code 3000, the malware creates a new thread executing “/bin/sh”. In the new spawned shell, the malware executes python -c “import pty;pty.spawn(‘/bin/sh’)” to get a pseudo-terminal (pty) interface. Any shell commands sent to the malware with the command code of 3058 are executed in the pty and the response is returned to the operator.
Network TunnelingNetwork tunneling is enabled by sending the command code 4001 to the malware. As part of the request, a “configuration” is sent as part of the response body. The configuration consists of three items separated by a “#” character. The items are: a port to bind to, the IP to connect to, and a port to connect to. The malware uses a modified version of the open-source project Rinetd for the tunneling logic. Rinetd is designed to use a configuration file stored on the machine. To get around this, the malware author has modified the function that parses the configuration in order to directly take the required values normally found in the configuration file.
Detection & Response
Detect if a Machine in Your Network Has Been CompromisedUse a Cloud Workload Protection Platform like Intezer Protect to gain full runtime visibility over the code in your Linux-based systems and get alerted on any malicious or unauthorized code or commands. Try our free community edition Figure 13 emphasizes an Intezer Protect alert on a compromised machine. The alert provides additional context about the malicious code including threat classification (RedXOR), binary’s path on the disk, process tree, command, and hash.
Intezer Protect defends all types of compute resources—including VMs, containers and Kubernetes—against the latest Linux threats in runtime. Try our free community edition
ResponseIf you are a victim of this operation, take the following steps:
- Kill the process and delete all files related to the malware.
- Make sure your machine is clean and running only trusted code using a Cloud Workload Protection Platform like Intezer Protect.