home/blog/lfi-to-rce-php-filters
Pentest

From Read-Only LFI to RCE via PHP Filters

R
Muhammad Rajib Hawlader
-Mar 11, 2026-9 min read

Chaining filter wrappers into a working payload when nothing else is writable.

From Read-Only LFI to RCE via PHP Filters
Advertisement
after intro - 728x90 desktop / fluid mobile

Local file inclusion is often dismissed as read-only impact, but PHP stream wrappers can change the shape of the bug. Under the right constraints, filters become a payload construction tool.

Confirm the primitive

First prove what the include can read, whether null bytes matter, whether suffixes are appended, and whether wrappers are allowed.

lfi-request.http
GET /view.php?page=php://filter/convert.base64-encode/resource=index HTTP/1.1
Host: target.example

Understand filter chains

Filter chains can transform bytes before PHP interprets them. The exploitability depends on PHP version, allowed wrappers, memory limits, and how the vulnerable include is called.

WARNING

Use this technique only in authorized testing. It can move quickly from proof of concept to code execution.

Advertisement
mid article - 300x250 responsive

Fix the root cause

Never include files from user input. Map user-facing names to server-side templates and reject anything outside the allowlist.

Exploitability conditions

Not every LFI becomes code execution. The important work is identifying constraints: whether wrappers are enabled, whether PHP will execute the included stream, whether a suffix is appended, and whether the application exposes useful error messages.

Key questions:

  • Can you include php://filter?
  • Does the application append .php or another suffix?
  • Is the target running a PHP version affected by known filter-chain techniques?
  • Are memory limits low enough to break payload construction?
  • Can logs, sessions, uploads, or temporary files be influenced?

Defensive logging

Path traversal and wrapper probes are easy to log. Watch for ../, encoded traversal, php://, data://, zip://, and unusually long include parameters. These probes often happen before successful exploitation.

lfi-detection-patterns.txt
../
..%2f
php://filter
convert.base64-encode
data://text/plain

Engineering fix

Replace dynamic include paths with an allowlisted map. User input should select a logical page key, not a filesystem path. Keep templates outside writable directories and disable dangerous wrappers when possible.

TIP

The cleanest LFI fix is architectural: users choose content IDs, the server chooses files.

Safe reproduction for reports

When reporting LFI, show the lowest-impact proof first. Reading a harmless local file or base64-encoding the application's own source is usually enough to prove impact. Avoid dumping secrets unless the rules of engagement explicitly allow it.

Report elements:

  • Vulnerable parameter and endpoint.
  • Exact payload used.
  • Evidence of file read.
  • Scope of accessible paths.
  • Why the issue could escalate.
  • Concrete allowlist-based fix.

Why developers miss it

LFI often enters through convenience features: language selection, theme selection, documentation pages, invoice templates, or debug views. The code may look safe because it appends a suffix, but wrappers and encodings can bypass naive assumptions.

Defense in depth

Use allowlists, but also harden the runtime. Disable unnecessary wrappers, keep sensitive files outside the web user's access, run PHP with least privilege, restrict open_basedir when appropriate, and remove verbose error output in production.

Detection playbook

When LFI probes appear, check whether the same source touched upload, session, or log endpoints. Attackers may first confirm read access, then look for a write primitive to turn inclusion into execution.

Remediation checklist

Fixing one payload is not enough. Developers should remove the file path primitive entirely and add tests that prove traversal, wrapper, and encoded variants fail. A regression test should cover normal page selection and malicious values so a future refactor does not bring the bug back.

Checklist for the fix:

  • Replace raw paths with a server-side allowlist.
  • Normalize and reject unexpected input before lookup.
  • Keep templates outside user-writable directories.
  • Disable unused stream wrappers when the platform allows it.
  • Remove verbose PHP errors from production.
  • Add detection for traversal and wrapper probes.

Business impact explanation

LFI findings are sometimes underrated because the first proof reads a file instead of executing code. Explain the impact in stages: source disclosure can reveal credentials or internal logic, sensitive file reads can expose secrets, and certain PHP configurations can escalate to code execution. That framing helps engineering and leadership understand why the architectural fix matters.

Good reports also include restraint. Showing a safe file read, explaining the escalation path, and providing concrete remediation usually gets faster approval than dumping production secrets.

Advertisement
end of article - 728x90 desktop / fluid mobile