Umbrella
Breach Umbrella Corp's time-tracking server by exploiting misconfigurations around containerisation.
Recon
Let's start with a nmap scan.
Visiting Umbrella.thm:8080 gives us a login page. Defaut credentials such as admin:admin did not work. Gobuster and Dirbuster didn't reveal any other directories which can be exploited.

There is a docker registery that is exposed on port 5000.
Docker Registry is an official tool from the Docker project for storing and distributing container images. Docker Registry is open source, and anyone can download and run the software to set up their own container image registry.
Hacktricks has more details on how we can enumerate this.
We can use cURL to enumerate and find useful information. We can see it is configured for HTTP. Wee can display the available repositories via _catalog. The repository umbrella/timetracking is available to us.
With the tag and the repository, we can now pull the manifests.
The manifest contains the history and the blobs used by Docker. The history is self explanatory it contains the commands or instructions that were used to build the Docker image. The blobs refer to binary large objects, which are the individual layers that compose a Docker image.
The first history contains the databse of the password and we can answer the first question.

Let's login to the databse and see what we can find.

We can find credentials for claire-r, chirs-r, jill-r and barry-b. These are MD5 encoded and can easily be cracked via hashcat.
hashcat -a 0 -m 0 hashes /usr/share/wordlist/rockyou.txt
Cracking these hashes will give us passwords.
Initial Access
We can now login with the credentials we have.

We can also use the same credentials for SSH. This will give us a flag, which answers the 2nd question.
timeTracker-src contains the sources for the app on 8080. We can explore that further for any information.
Inside the Docker compose file, we see that the /logs folder is mounted. There could be about a misconfigured Docker Container running the application. The next steps could therefore be to get a foothold over 8080 and escalated our privileges from the vulnerable Docker container.
Back to the web app we can see a time entry tool with the option of using mathematical operations to update our tracked times. When we enter a numerical value, the time spent value increases.
But upon entering non numerical value it sends us to a page and gives syntax errors. Upon further inspection of the code of app.js. We can find
let timeCalc = parseInt(eval(request.body.time));
The entered time value is evaluated using eval(). Here we can try injecting different payloads.
After trying few payloads
arguments[1].end(require('child_process').execSync('cat /etc/passwd'))
We are able to retrieve /etc/passwd. But no other payloads yeilded good results.
After quite a few payloads. Perl seemed to work.
We can encode this as base64. Our payload will look like this.
With this we get a reverse shell on the Docker Container as root.


The main goal here is to escape from the container to a user on the host (not having the SSH access).
However not much could be done in the Container, usual binaries like were also not available.
Privilege Escalation
In the root directory, we find the folder /logs. This is interesting, even without the knowledge that claires-r's home directory belongs to UID 1001.
To confirm that this is the log directory from clair-r we look at the contents and could also create a file in there.
In both we can find tt.log.
We can use the following technique:
Privilege Escalation with 2 shells and host mount
If you have access as root inside a container that has some folder from the host mounted and you have escaped as a non privileged user to the host and have read access over the mounted folder. You can create a bash suid file in the mounted folder inside the container and execute it from the host to privesc.
We copy /bin/bash as claire-r into /logs.
We modify the permissions fom the container as root.
Now we run ./bash -p as claire-r. We get a root shell and have access to the root flag in /root, which answers the third and final question.
Last updated
Was this helpful?