Hacktricks-skills lfi2rce-phpinfo
How to exploit Local File Inclusion (LFI) to Remote Code Execution (RCE) using PHPInfo() output. Use this skill whenever you need to escalate LFI vulnerabilities to RCE, especially when phpinfo() pages are accessible, or when you're testing for file inclusion vulnerabilities that could lead to code execution. Make sure to use this skill when you find LFI sinks combined with phpinfo() endpoints, or when you need to convert file inclusion into command execution on PHP applications.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/file-inclusion/lfi2rce-via-phpinfo/SKILL.MDLFI to RCE via PHPInfo
This skill teaches you how to escalate Local File Inclusion (LFI) vulnerabilities to Remote Code Execution (RCE) by leveraging PHP's
phpinfo() output to discover temporary file paths created during file uploads.
When to Use This Technique
Use this approach when you have:
- A reachable page that outputs
(e.g.,phpinfo()
,/phpinfo.php
,/info.php
)/debug.php - An LFI primitive you control (user-controlled
,include
,require
, etc.)file_get_contents - PHP file uploads enabled (
)file_uploads = On - The ability to include files from the upload temp directory
Theory
When PHP receives a
multipart/form-data POST with a file field, it:
- Writes the content to a temporary file in
(or system temp directory)upload_tmp_dir - Exposes the path in
$_FILES['<field>']['tmp_name'] - Automatically removes the file at the end of the request unless moved/renamed
The trick:
phpinfo() prints $_FILES, including tmp_name. By inflating request headers/parameters (padding), you can cause early chunks of phpinfo() output to flush to the client before the request finishes. This lets you read tmp_name while the temp file still exists, then immediately hit the LFI with that path to execute the payload.
Common temp paths:
- Linux/Unix:
or configured/tmp/php*.tmpupload_tmp_dir - Windows:
C:\Windows\Temp\php*.tmp
Attack Workflow
Step 1: Prepare Your Payload
Create a PHP payload that persists a shell quickly (writing a file is faster than waiting for a reverse shell):
<?php file_put_contents('/tmp/.p.php', '<?php system($_GET["x"]); ?>');
Step 2: Send Large Multipart POST to phpinfo()
Send a large
multipart/form-data POST directly to the phpinfo() page. Inflate headers/cookies/params with ~5–10KB of padding to encourage early output flushing.
Step 3: Race Condition - Parse and Include
While the
phpinfo() response is still streaming:
- Parse the partial body to extract
(HTML-encoded)$_FILES['<field>']['tmp_name'] - As soon as you have the full absolute path (e.g.,
), fire your LFI to include that path/tmp/php3Fz9aB - If
executes the temp file before deletion, your payload runs and dropsinclude()/tmp/.p.php
Step 4: Use the Dropped Shell
Access the persistent shell:
GET /vuln.php?include=/tmp/.p.php&x=id
Using the PoC Script
The bundled script
scripts/lfi2rce-phpinfo.py automates this attack. Configure these variables:
| Variable | Description | Example |
|---|---|---|
| Target hostname | |
| Target port | |
| Path to phpinfo() endpoint | |
| LFI sink path (sprintf-style, = tmp path) | |
| Concurrent workers | |
| PHP code to execute | See defaults |
Running the Script
python3 scripts/lfi2rce-phpinfo.py
Customizing for Your Target
If the LFI sink appends
: Remove null byte handling; .php
include() will execute PHP regardless of temp file extension.
If you need null bytes (older PHP): Add
%00 to the LFI path to cut off unwanted extensions.
Adjust padding: If output doesn't flush early, increase
PADDING size or add more large headers.
Troubleshooting
| Problem | Solution |
|---|---|
Never see | Ensure you're POSTing to . only appears with upload fields. |
| Output doesn't flush early | Increase padding, add more large headers (Cookie, User-Agent, Accept-Language, Pragma), or send concurrent requests. |
| LFI path blocked | Check or restrictions. Point LFI to an allowed path or try a different LFI→RCE vector. |
Temp directory not | prints the full absolute path; use that exact path in the LFI. |
HTML-encoded arrow | The script handles both and encodings automatically. |
Defensive Notes
- Never expose
in production. If needed, restrict by IP/auth and remove after use.phpinfo() - Keep
disabled if not required. Otherwise, restrictfile_uploads
to a path not reachable byupload_tmp_dir
in the application.include() - Treat any LFI as critical; even without
, other LFI→RCE paths exist.phpinfo() - Validate and sanitize all
/include
paths with strict allowlists.require
References
- LFI With PHPInfo() Assistance whitepaper (2011) – Packet Storm
- PHP Manual – POST method uploads: php.net
- Original PoC:
(see whitepaper)phpinfolfi.py