Myles Nieman
← All writeups

Resource

Overview

Resource is a hard Linux box built around an SSH key management portal (itrc / ssg.htb). The web application accepts zip uploads, which are vulnerable to path traversal. A PHP pearcmd trick turns an LFI into code execution, landing a webshell as www-data. Inside the upload directory, previously submitted zips contain a HAR file leaking credentials for msainristil. A SSH certificate signing API (signserv.ssg.htb/v1/sign) is then abused to sign attacker-controlled keys for trusted principals, enabling SSH access as additional users — including a privileged path to root via a key-signing script accessible through sudo.

Path: zip path-traversal LFI → pearcmd webshell → www-data → HAR creds (msainristil) → SSH cert signing API abuse → zzinter → sudo key-signing script → root.

Enumeration

The initial scan reveals an unusual service layout — two SSH ports and a web server, with a third port visible when switching to the release arena.

Nmap scan showing multiple SSH ports and the web server

Both exposed SSH banners are captured:

SSH banner on the first SSH port

SSH banner on the second SSH port

Adding the hostnames to /etc/hosts and visiting the site presents an SSH key management portal:

SSH key management web application landing page

The site is described as a tool for managing SSH access — tickets can be submitted to request key access. Browsing the application surfaces a zip upload feature:

Ticket submission and zip upload feature in the web app

Zip upload accepted — path traversal potential noted

Foothold — Pearcmd LFI to Webshell

The slip tool generates malicious archives with path traversal payloads:

slip tool — CLI for generating path traversal archives

Setting up a Python virtual environment to install and run it:

slip installed in a venv

$ python3 slip.py --archive-type zip --compression deflate \
    --paths "../etc/hosts" \
    --symlinks "../etc/shadows" \
    --file-content "foo" archive

Initial path-traversal attempts confirm the feature is vulnerable but the direct symlink approach is blocked. Attempting to read tickets by fuzzing the ticket ID parameter does not yield results; fuzzing the page parameter does:

ID fuzzing — no results; switching to page parameter

Archive uploaded and processed

Path traversal response — file content returned

Fuzzing the page parameter reveals an admin endpoint:

Page parameter fuzzing finds the admin endpoint

Admin page accessible

The page parameter is confirmed vulnerable to LFI — both admin and ./admin return identical results (path normalization is applied but traversal works):

LFI confirmation — admin and ./admin return the same page

Pinging back to the attacker confirms outbound connectivity from the server:

Ping test showing the server can reach the attacker

Ping response confirmed

The server runs as www-data, with read/execute access to PHP files. A Chinese-web-CTF technique abuses pearcmd — a PHP PEAR tool that is sometimes included in PHP installations and can be invoked through LFI to write arbitrary files:

Pearcmd invocation research / reference

Listener set up to catch the webshell callback

Testing the pearcmd page parameter path

Pearcmd invocation being tested

Subdomain fuzzing while exploring other vectors

Additional LFI path traversal attempts

LFI behavior under various path conditions

Page parameter confirmed LFI-vulnerable

LFI response detail

Burp confirming path normalization and LFI behavior

The pearcmd payload that writes a webshell:

../../../../../../../../usr/local/lib/php/pearcmd&+config-create+/&/<?=`$_GET[0]`?>+/var/www/itrc/YOUROUTPUTFILE.php

Pearcmd config-create payload sent via Burp

Pearcmd payload accepted — PHP file written

The webshell is now accessible:

Webshell response confirming code execution as www-data

User — Extracting Credentials from Uploaded Zips

As www-data the working directory reveals multiple running PHP debug server processes and an uploads directory:

Directory listing showing the PHP debug server layout and uploads

Identifying the uploads directory path

Exploring the uploads folder via the webshell shows previously submitted zip files. Pulling them down reveals public SSH keys and a HAR file containing credentials in cleartext:

Webshell output — exploring directory structure

Uploads directory listing via webshell

Zip archive contents — public keys and HAR file visible

www-data shell confirmed via webshell

Upload directory structure detail

Burp output from the webshell — navigating the filesystem

Interesting files discovered in the upload area

Zip files containing public keys and HAR data

Extracting the HAR file content:

HAR file contents showing stored credentials

Additional HAR / zip content

HAR file credential detail

The HAR file leaks:

msainristil : 82yards2closeit

Credential confirmed: msainristil:82yards2closeit

Privilege Escalation — SSH Certificate Signing API Abuse

Logging in as msainristil via SSH is possible with the recovered password, but the real path forward is a certificate-signing API. The site exposes a signing service at signserv.ssg.htb/v1/sign:

msainristil SSH session established

Exploring the signserv endpoint

Signserv API documentation or source reference

Rather than using msainristil’s existing private key to authenticate as zzinter, the correct approach is to sign a newly generated key for the zzinter principal using the signing API:

$ ssh -o CertificateFile=ha1ks-cert.pub -i ha1ks zzinter@ssg.htb

Setting the SSH key permissions:

chmod 600 applied to the generated private key

Signing the key through the API for the desired user principal:

Signing API request for zzinter principal

Signed certificate returned by the API

SSH login as zzinter using the signed certificate:

SSH login as zzinter with the signed certificate

Exploring zzinter’s environment reveals a key-signing script:

zzinter home directory and environment exploration

The signing service accepts additional trusted principals. Checking the SSH server configuration and available principals:

Additional SSH authorized principals or CA configuration

Signing API call details from the script source

Reading the signing script to understand the signing logic:

Key signing script source — understanding how principals are authorized

Iterating through signing API calls to identify valid principals

Successful signing response for a privileged principal

Gaining access to a privileged shell:

Shell as a more privileged user via signed certificate

Checking sudo permissions:

sudo -l output for the current user

Sudo rule allowing access to the key signing script

Looking at other authorized principals that can be signed:

Reviewing other trusted SSH principals

Signing a key for the root principal or a privileged CA target

Signed certificate for the elevated principal

Root

With a certificate signed for the correct privileged principal (reachable via the sudo-allowed signing script), SSH authenticates as root:

Root-level shell obtained via SSH certificate

Exploring the final environment:

Exploring /opt or root home for flags

Root flag or final confirmation

Takeaways

  • PHP pearcmd turns read-only LFI into arbitrary file write. Any PHP installation with pearcmd in the include path and a page parameter passing user input to include() is vulnerable to this trick — the config-create subcommand writes attacker-supplied content to a caller-controlled path.
  • HAR files stored inside uploaded zips are a credential goldmine. Browser HAR captures include all request headers and bodies, often with session tokens and plaintext passwords.
  • An SSH Certificate Authority signing API with insufficient principal validation is equivalent to arbitrary authentication. If an attacker can request certificates for arbitrary principals, they can authenticate as any user the CA trusts — including root.