The name Chaos is being used for a ransomware strain, a remote access trojan (RAT), and now a DDoS malware variant too. Talk about chaos! In this case, Sysdig’s Threat Research Team captured attacks using the Chaos variant of the Kaiji botnet malware. There is very little reported information on this malware since September 2022, perhaps because of the unfortunately chaotic naming, or simply because it is relatively new. Kaiji malware was of Chinese origin in 2020 and is written in Golang. Similarly, Chaos is a Chinese Golang malware developed for both Windows and Linux operating systems, and other multiple hardware architectures too.
Chaos made a lot of noise in our honeypot in mid-January when we directly observed this malware attacking a misconfigured Apache Tomcat environment. We saw it again at the end of February with some evolutions. Previous iterations of this malware were sourced from a publicly available malware repository and analyzed by Lumen’s Black Lotus Labs.
We will go through the analysis of our captured attacks with an emphasis on persistence techniques in this blog, and share our Indicators of Compromise (IOCs) at the end.
Kaiji malware
As far as behavioral attributes, we concur with previous reporting that this Chaos malware is an evolution of the Kaiji botnet, with much of the same previously reported functionality. To summarize, Kaiji was a DDoS botnet that mainly attacked IoT devices via SSH brute-forcing, hence the source language being Go and easy cross-compilation to common IoT architectures like PowerPC and SPARC. The Chaos variant we captured shows all of the same DDoS functionality as the previously reported-on version, and rather than build a Chaos emulator, we identified that the code supporting this functionality was still present in this new version.
Technical analysis
After being installed via the exploitation of a misconfigured Apache Tomcat environment, Chaos malware pivoted to install ALL the persistence mechanisms. We will explain in greater detail below, but the actors behind this attack really wanted to ensure their attack would survive a reboot, which begs the question of whether or not they considered that the world has moved on to containerized workloads – none of these persistence mechanisms would survive a container restart.
We started our analysis using the tool ssdeep for fuzzy hashing, or comparing similar but not identical files. This allowed us to cluster the files we captured based on similarity. The invocation in the screenshot is telling ssdeep to group the files by similarity (-g
), and to hash all of the files in the directory (-d
). First, we found 10 files that were all the same binary. Turns out, they are copies of the malware itself. The remaining files were scripts used to execute the malware via different persistence mechanisms.
T1053.003 – scheduled task/job: cron
First of all, we saw that persistence was achieved by copying itself to the file path /etc/id.services.conf
and creating the file /etc/32678
. This action remains unchanged from previous reporting and for this reason, we knew we were likely looking at Chaos. The /etc/32678
file contains the following shell script:
#!/bin/sh
while [ 1 ]; do
sleep 60
/etc/id.services.conf
Done
Code language: Perl (perl)
The /etc/32678
file was then executed by adding an entry to crontab
and executing cron -f
, which makes cron run in the foreground instead of background. The script will attempt to execute the malware while the cron program continues to run. This can be considered the malware’s initial startup. Since running cron like this isn’t persistent, the attacker resorts to a number of additional methods to ensure their malware comes back after a reboot or if it dies.
T1554: compromise client software binary
Chaos attempts to use the user and automated scripts as a persistence mechanism by trojaning common user binaries. When these binaries are executed, the main Chaos payload will be run. The original program is not called, so the expected behavior of the command would not occur. This tactic also has the side effect of making it difficult for a user to see what is happening on the system.
The files replaced are:
/usr/bin/find |
/usr/bin/dir |
/usr/bin/ls |
/usr/bin/ps |
The Chaos malware does attempt to hide its presence in a rather uncommon way. Shell functions in the gateway.sh
script, when placed in /etc/profile.d/
, will run the users’ shell commands and filter out any sign of the malwares’ presence. The example below replaces the find
command and uses sed
to strip out its own filenames.
function find {
proc_name=$(/usr/bin/find $@) # run the backdoored find with the original arguments specified by the user
proc_name=$(echo "$proc_name" | sed -e '/32676/d')
proc_name=$(echo "$proc_name" | sed -e '/dns-tcp4/d')
proc_name=$(echo "$proc_name" | sed -e '/quotaoff.service/d')
proc_name=$(echo "$proc_name" | sed -e '/System.mod/d')
proc_name=$(echo "$proc_name" | sed -e '/gateway.sh/d')
proc_name=$(echo "$proc_name" | sed -e '/32676/d')
. . . <other IoCs here>
echo "$proc_name"
}
Code language: Perl (perl)
T1546.004 – event triggered execution: unix shell configuration modification
Files in /etc/profile/
set the environment variables at startup of the bash shell. The /etc/profile.d/
directory contains other scripts that contain application-specific startup files, which are also executed at startup time by the shell. This is a common place attackers can place their own files in order to gain execution. In this case, it occurs when a shell is launched, such as when a user logs in to the system.
The attacker placed the /etc/profile.d/bash_config.sh
file which contains:
#!/bin/sh
/etc/profile.d/bash_config
Code language: Perl (perl)
This invokes the specified malware each time a new bash shell is spawned. Note that this is the ELF version of the malware, not another script.
T1053.003 – scheduled task/job: cron
Cron is a system binary that is analogous to scheduled tasks for those coming from the Windows world. Cron allows attackers to ensure that their malware will be restarted after a certain time interval, increasing the persistence of the attack. The crontab
file invokes the hidden file .img
, which is a shell script that then calls the libdlrpcld.so
file, which is yet another copy of the malware. The following cron entry will execute .img
every minute.
*/1 * * * * root /.img
Code language: Perl (perl)
The .img
file is a shell script which calls a copy of the malware, named libdlrpcld.so
like so:
#!/bin/sh\n/usr/lib/libdlrpcld.so
Code language: Perl (perl)
T1543.002 – create or modify system process: systemd service
Systemd’s primary component is a “system and service manager” – an init system used to bootstrap user space and manage user processes. It also provides replacements for various daemons and utilities, including device management, login management, network connection management, and event logging. In this case, the attackers wrote a systemd service that will run the malware (here named System.img.config
) on system init.
The file /usr/lib/systemd/linux.service
was created by the attacker as a systemd service that executes the malware on boot:
$ cat linux.service
[Unit]
Description=linux
After=network.target
[Service]
Type=forking
ExecStart=/boot/System.img.config
ExecReload=/boot/System.img.config
ExecStop=/boot/System.img.config
[Install]
WantedBy=multi-user.target
Code language: Perl (perl)
T1037 – boot or logon initialization scripts
In Unix-based computer operating systems, init (short for initialization) is the first process started during booting of the operating system. Init is a daemon process that continues running until the system is shut down. It is the direct or indirect ancestor of all other processes and automatically adopts all orphaned processes. Init is started by the kernel during the booting process; a kernel panic will occur if the kernel is unable to start it. Init is typically assigned PID 1. Init scripts placed in the /etc/init.d/
directory allow for users to write their own startup scripts or programs.
Below, you can see the threat actors behind Chaos leverage init scripts to ensure that their malware (here named System.img.config
) will run on system startup. They used both init.d and systemd to better their chances of retaining persistence, presumably because they don’t know in advance which system their target uses. The file used was: /etc/init.d/linux_kill
. On boot, it will execute the /boot/System.img.config
file, which is the Chaos malware.
cat linux_kill
#!/bin/sh
### BEGIN INIT INFO
#chkconfig: 2345 10 90
#description:System.img.config
# Default-Start: 2 3 4 5
# Default-Stop:
### END INIT INFO
/boot/System.img.config
exit 0
Code language: Perl (perl)
Binary analysis
During our investigation, we observed two versions of the Chaos malware which we will call 32678 and 32676. While the surrounding shell scripts were different and showed an evolution of tactics, the malware itself seems to have remained very similar. First, we used ssdeep to compare them, but as the results show below, they were not the same.
$ ssdeep ./files/System.mod ../chaos/files/System.img.config
ssdeep,1.1--blocksize:hash:hash,filename
24576:ae9ufJvk4gQjMNRfktnsIXvZFyD9i+MPCIxyuzNqssZXJjZbdYVVMtIwWz1v:WYMnwRO4ssPJd5Wz1,"/Users/nicholaslang/chaos_new/files/System.mod"
49152:E33d0lGt6UHcFL7Rn2o03wiEhiDmzzd/9sARlBs/00Cpfx9a9uNYp9hW16klbU6V:E33GlbU8FwmzzRDZ9mjqRV,"/Users/nicholaslang/chaos/files/System.img.config"
Code language: Perl (perl)
Next, we measured the entropy, or randomness, of each binary and plotted them on a graph. Different types of data tend to have different levels of entropy; normal x64 code is less random than an encrypted executable. In order to obfuscate an executable, threat actors will often employ various methods to change the binary so the hashes no longer match, which we saw in this case.
The two versions of the Chaos malware (32676 and 32678, respectively) are extremely different when fuzzy-hashed with ssdeep, but the entropy graphs reveal very similar (near-identical) binary layouts. This suggests that the threat actor did attempt to obfuscate the binary between attacks, but their methods did not significantly alter the binary’s structure. There are likely no major changes to its functionality either. This investigative technique makes it easier to identify additional Chaos variants.
Conclusion
Chaos is either not being deployed very frequently, being miscategorized as its former Kaiji parent version and therefore ignored, or is not being found. Regardless, we were surprised to find so little information on what seems to be a fairly capable piece of malware. The authors of the malware have put more effort than most in trying to persist the malware across reboots and hide its presence.
Our analysis showed that there were several copies of the malware being used in the wild. There are also multiple persistence mechanisms for malware execution, an indication that the actor is thorough but not necessarily competent with containers. While a simple reboot in a containerized environment will rid you of this botnet, you should patch the initial access vector (likely a CVE) to truly rid yourself of this infection.
IOCs
IP Addresses:
98.159.98[.]203
107.189.7[.]51
Filename | MD5 Hash |
Attack 1 | |
linux_386 | 14be5f004bc5e7a33c3057df92ad9a16 |
bash_config | 14be5f004bc5e7a33c3057df92ad9a16 |
find | 14be5f004bc5e7a33c3057df92ad9a16 |
dir | 14be5f004bc5e7a33c3057df92ad9a16 |
id.services.conf | 14be5f004bc5e7a33c3057df92ad9a16 |
ls | 14be5f004bc5e7a33c3057df92ad9a16 |
System.img.confg | 14be5f004bc5e7a33c3057df92ad9a16 |
ps | 14be5f004bc5e7a33c3057df92ad9a16 |
system-monitor | 14be5f004bc5e7a33c3057df92ad9a16 |
libdlrpcld.so | 14be5f004bc5e7a33c3057df92ad9a16 |
32678 | 768eaf287796da19e1cf5e0b2fb1b161 |
bash_config.sh | cfb4e51061485fe91169381fbdc1538e |
crontab | 360878ce5edb3684950ebb0c138298f8 |
linux.service | d80ccc7ced99538f22336f2ec0249087 |
linux_kill | 3909975f7cc0d1121c1819b800069f31 |
.img | d73d3376908ea075a939e3871ad0fabe |
Attack 2 | |
32676 | 47684525bfdf26f49fd1cf742b17c015 |
bash_cfg | 0db80699dcdf8372e0f813eaea8b5782 |
bash_cfg.sh | 3e32bcdce50da6c05127094b32e5401a |
cron | 0e0a4a7372459b9c2d8f45baa40a64b3 |
crontab | a60806d9e03c42cd3bd740cbfb6d4375 |
dir | 079b45463b8b7f66d9ec2c24b2853fbe |
find | b68ef002f84cc54dd472238ba7df80ab |
gateway.sh | b10f8b371ee7559987c4b29a4ac85e42 |
hashes.txt | d12d6a5241cf180734dbe0b928c97798 |
hwclock.sh | 40e4f04e723fb5bee6df2327ea35254d |
libgdi.so.0.8.1 | 0db80699dcdf8372e0f813eaea8b5782 |
linux_386 | 0db80699dcdf8372e0f813eaea8b5782 |
ls | 0db80699dcdf8372e0f813eaea8b5782 |
opt.services.cfg | 0db80699dcdf8372e0f813eaea8b5782 |
procps | bea2bdfd5f7688d4f6e313dc63ca499d |
ps | 0db80699dcdf8372e0f813eaea8b5782 |
quotaoff.service | b02de6cd28cd922b18d9d93375a70d8b |
system-mark | 0db80699dcdf8372e0f813eaea8b5782 |
System.mod | 0db80699dcdf8372e0f813eaea8b5782 |
For additional IoCs associated with this campaign, please visit our GitHub page.