Skip to content

Latest commit

 

History

History
181 lines (135 loc) · 11.4 KB

File metadata and controls

181 lines (135 loc) · 11.4 KB

HTB — HackNet : Writeup 🚀

Author: Ahmed Amr Mohamed
Target: HackNet (HTB)
Date: 2025-09-17

TL;DR — Quick summary 🕵️‍♂️

I found a Server-Side Template Injection (SSTI) in the SocialNetwork app that leaked other users’ credentials. I used one of those accounts to SSH in, discovered a Django cache file write vector to get a reverse shell as sandy, recovered .gnupg keys and encrypted backups, cracked the GPG private key with john, decrypted backups, found credentials to escalate to root, and captured the root flag. 🎯

Tools used 🧰

  • nmap
  • Browser (web UI)
  • ssh, nc (listener)
  • tar, scp
  • gpg, gpg2john, john
  • Linux utilities: grep, su, etc.

Full step-by-step (images included) — copy/paste ready ✍️

1. Recon — nmap

Screenshot of the nmap output used to start enumeration:
nmap

2. Web App — register & explore

Registered a user and inspected the web app (Login / Signup / Edit Profile):
register/login

Edit profile page where username field is editable:
edit profile

3. SSTI discovery (template injection) 🔥

Test payload {{7*7}} reflected but initially filtered:
ssti test

Checked where the username is reflected on the site:
reflection

Likes UI — reflection point for usernames:
likes UI

Tried again — {{7*7}} reflected & executed but got blocked (blacklist evidence):
blocked

Switched to {{users.values}} — SSTI executed and returned user objects (leak):
users.values

Collected ~24 accounts by repeating this on multiple posts/pages. One user (id 18) was missing from like lists:
missing id

Profile/18 is private (no public likes):
private profile


4. Social flow to reach private user

Sent a contract request from our account to the private user, then used SSTI to extract the private user's credentials via a mutual connection/post:
contract request

SSTI leaked the user's email & password:
creds

Logged into the web app with recovered creds:
logged in

Accepted the contract request from the compromised user:
accepted

Can't edit that user's username because 2FA blocks it (screenshot):
2fa


5. Use mutual like to reach real target

From our main account we found a post liked by the target — used the SSTI there to leak the target's credentials:
target liked post

SSTI steps and successful leak:
ssti leak

Leak confirmation (credentials shown):
credentials

Tried SSH with the leaked credentials (failed), then tried mikey and succeeded:
ssh attempt

SSH success as mikey (we have a shell):
ssh success


6. Local enumeration — find web project & cache behavior

Found web project at /var/www/HackNet/SocialNetwork/ and saw a `sandy` file in home — target user is likely sandy:
web project

Observed Django cache behavior: visiting /explore?page=1 creates cache files (one looked empty initially):
empty cache

After refresh the cache files appear:
cache refresh

Django cache files visible on disk / app path:
cache files


7. Cache poisoning → remote code execution (reverse shell)

Created a cache-named file containing a reverse shell payload (placed in the web directory) to be executed when the cache is rendered:
reverse shell file

Ran the script to write the file on target:
wrote file

Confirmed file exists in target dir:
file exists

Refreshed the web page; reverse shell hit our listener — got a shell as sandy:
listener hit


8. Post-exploitation — collect GPG keys & backups 🗂️

As sandy found /home/sandy/.gnupg/ with private keys:
.gnupg

Found encrypted backup files (*.gpg etc.):
backups

Packed .gnupg and backups, exfiltrated to attacker for local cracking:
packed

Downloaded archive locally and tried to extract / decrypt: got prompt that passphrase is required:
decrypt prompt

GPG decryption requires passphrase (we'll crack the private key offline):
passphrase required


9. Crack the GPG key 🔐

Created a directory with the private key files and converted the private key to a john hash with gpg2john:
gpg files

gpg2john conversion to hash:
gpg2john

Cracked the hash with john (rockyou + rules) and obtained the passphrase:
john crack

Recovered passphrase visible in john output:
passphrase

Used passphrase to decrypt backups locally:
decrypting backups

Searched decrypted backup contents for secrets (grep):
grep results

Found a password inside the backups that allowed privilege escalation:
found password


10. Privilege escalation → root

Used the discovered password to su to root and captured the root flag:
root

Final notes & mitigations ✅

  • SSTI exposure — sanitize/escape user input, disable template evaluation of user-controlled fields, use template sandboxing.
  • Sensitive data in backups — never store plaintext credentials in backups; use proper key management and rotate keys.
  • Django cache file safety — store cache files in non-web-executable directories and apply strict file permissions.
  • 2FA & account protection — enforce 2FA for all high-privilege actions and monitor for suspicious activity.

If you want, I can:

  • Shrink this to a one-page summary with the key images only.
  • Output a README.md (GitHub-ready) with collapsible sections.
  • Export a downloadable PDF.