We covered a Docker container running a web server that is vulnerable to server side request forgery. We used that vulnerability to execute system commands and gain access to sensitive information stored inside git commits. We learned that a Docker daemon runs on port 2375 but in order to probe and access that container we need to perform port knocking to open the port 2375. Afterwards, we mounted the complete host file system.. This was part of TryHackMe The GreatEscape.

Initial Reconnaissance and Hidden Directories

I started by understanding the initial enumeration. An nmap scan would typically reveal ports 80 (HTTP) and 22 (SSH) open. I explored the web application, noting its “courses,” “admin” login form, “sign up,” and “login” functionalities. I tried basic credential stuffing, SQL injection, and brute-forcing the login form, but they were unsuccessful. The signup form was also disabled. I attempted directory brute-forcing, but it failed due to rate limiting on the web server.

Next, I checked robots.txt, which revealed disallowed entries: /api, /exif-utility, and files ending with .back.txt. The /api endpoint showed “nothing to see here,” but /exif-utility presented an interesting interface for uploading files or providing a URL to extract EXIF data from images.

Exploiting EXIF Utility – SSRF and Command Injection

I tested the EXIF utility by uploading a local image URL, and it successfully displayed EXIF data. However, trying a remote image URL failed, suggesting a firewall was blocking outbound connections. When I provided a local non-image URL (like the server’s own IP), it resulted in an error but also leaked the HTML source code of the page, indicating a Server-Side Request Forgery (SSRF) vulnerability.

My focus then shifted to finding files with the .backup.txt extension. I created a wordlist using cewl (cewl http://<target_ip>/ -m 4 -w GreatEscape.txt) and manually added terms from the website. I then used wfuzz (wfuzz -w GreatEscape.txt -u http://<target_ip>/FUZZ.back.txt) with my custom wordlist to find exif-utility.backup.txt.

This backup file was a goldmine! It revealed an internal API endpoint: api-dev-backup:8080/exif, which took a URL parameter. I leveraged the SSRF vulnerability to interact with this internal API. I discovered command injection by appending commands (e.g., id) after a semicolon in the URL parameter supplied to the EXIF utility. This confirmed code execution as the root user within the Docker container. Examples of commands I used via URL manipulation were:

  • http://<target_ip>/exif-utility/show.php?url=image.png;id
  • http://<target_ip>/exif-utility/show.php?url=image.png;ls+ -la
  • http://<target_ip>/exif-utility/show.php?url=image.png;pwd
  • http://<target_ip>/exif-utility/show.php?url=image.png;cd+ /root
  • http://<target_ip>/exif-utility/show.php?url=image.png;ls+ -la+ /root
  • http://<target_ip>/exif-utility/show.php?url=image.png;cat+ /root/Dev-note.txt

Enumerating Inside the Container and Git Repository Exploitation

Inside the container, I used commands like ls -la, pwd, and cat via the command injection to explore the file system. I found a note Dev-note.txt in /root, which contained a password for “Hydra” (though it didn’t work for SSH). More importantly, I found a .git directory in /root.

I exploited the Git repository by using git log (http://<target_ip>/exif-utility/show.php?url=image.png;git+--git-dir=/root/.git+log) to list commits. Then, I used git diff <commit_hash> (http://<target_ip>/exif-utility/show.php?url=image.png;git+--git-dir=/root/.git+diff+<commit_hash>) to view changes in a specific commit. This revealed a crucial note about setting up Docker for remote administration and mentioned port knocking to open port 2375 (the Docker daemon port). I also found a flag here!

Port Knocking and Docker Daemon Access

To open port 2375, I created a bash script using telnet to perform port knocking on a sequence of ports. The script looked something like this:

Bash

#!/bin/bash
telnet <target_ip> 42
telnet <target_ip> 1337
telnet <target_ip> 6969 
# ... (other ports from the git diff output)

After successful port knocking, an nmap scan confirmed that port 2375 was open. I then used the Docker CLI to interact with the exposed Docker daemon remotely. I listed running containers using docker -H tcp://<target_ip>:2375 ps, which identified the web server container and others.

Escaping the Container

The final step was escaping the container. I used a Docker command to run a new privileged container, mounting the host’s entire file system (/) to a directory (/mnt) inside this new container. Then, I changed the root to this mounted directory, effectively giving me root access to the host system. The command I used was: docker -H tcp://<target_ip>:2375 run --rm -it --privileged -v /:/mnt alpine chroot /mnt sh.

After escaping to the host, I retrieved the final root flag from the host’s /root directory using cat /root/flag.txt. I also explored other attempted escape methods like using capsh for SYS_ADMIN capabilities or namespace manipulation, but they weren’t successful in this scenario. I also found another flag by accessing /.well-known/security.txt, which pointed to an API endpoint, and I retrieved it using curl -I http://<target_ip>/api/flag.php.

This entire experience provided a comprehensive understanding of Docker container penetration testing, from initial enumeration and web application vulnerabilities to privilege escalation and container escape techniques.

TryHackMeThe Great Escape Room Answers

Find the flag hidden in the webapp
Find the root flag?
Find the real root flag

Video Walkthrough

About the Author

Mastermind Study Notes is a group of talented authors and writers who are experienced and well-versed across different fields. The group is led by, Motasem Hamdan, who is a Cybersecurity content creator and YouTuber.

View Articles