PHP security explainer · defensive
PHP file inclusion (LFI/RFI): what it is and how to fix it
include and require execute whatever file they are given. When part of that path comes from the request, the visitor decides what runs.
Last updated
What it is
Local file inclusion (LFI) lets a request point include or require at files already on the server, such as configuration files or logs; combined with an upload or log entry it can become code execution. Remote file inclusion (RFI) loads code from another server and only works when allow_url_include is enabled, which php.net documents as off by default. MITRE classifies it as CWE-98.
How to detect it
- Search for
include,require,include_onceandrequire_oncewhose argument contains a variable, and trace that variable back to request data. - Run
php -iand confirmallow_url_includeis Off and whetheropen_basediris set. - Review web server logs for requests with
../sequences orphp://anddata:wrappers in parameters; they show someone probing, not proof of compromise.
How to fix it
- Never build an include path from input. Map an allowed key to a fixed file name, as in the example below.
- Keep
allow_url_include = Off; considerallow_url_fopen = Offif the app does not need remote reads. - Set
open_basedirto the site directory so PHP cannot open files elsewhere. - Store uploads outside the web root and never include them.
Read-only checks and safe patterns
# Find include/require with a variable path (read-only)
grep -rnE "(include|require)(_once)?\s*\(?\s*\$" --include=*.php . | grep -v /vendor/
php -i | grep -E "allow_url_include|allow_url_fopen|open_basedir"
; php.ini hardening
allow_url_include = Off
open_basedir = /var/www/example:/tmp
// Map user choices to fixed files instead of building paths
$pages = ['home' => 'home.php', 'about' => 'about.php'];
require __DIR__ . '/pages/' . ($pages[$_GET['p'] ?? 'home'] ?? 'home.php');Does basename() make an include safe?
It removes directory parts but still lets a visitor pick any file in that directory. An explicit allowlist is safer.
Is RFI still a risk in modern PHP?
Only if allow_url_include has been turned on. LFI remains common because it needs no special setting.
Other PHP vulnerability classes
- PHP object injection: what it is and how to fix itPHP object injection happens when user-controlled input reaches unserialize(), which can instantiate objects whose magic methods run attacker-chosen logic.
- SSRF in PHP: what it is and how to fix itServer-side request forgery (SSRF) happens when a PHP app fetches a URL the user controls, letting an attacker reach internal services or cloud metadata endpoints through your server.
- XSS in PHP: what it is and how to prevent itCross-site scripting (XSS) happens when a PHP page outputs user-controlled data into HTML without escaping, so an attacker’s script runs in other visitors’ browsers.
- phpinfo() exposure: why it matters and how to fix itA public phpinfo() page reveals the exact PHP version, loaded modules, file paths and often environment variables or secrets, which helps attackers target bugs such as PHP2Shell.
Sources
Outbound links leave this site. We do not host exploit code.
- CWE-98: PHP Remote File Inclusion — MITRE CWE
- Testing for Local File Inclusion — OWASP Web Security Testing Guide
- Filesystem runtime configuration (allow_url_fopen, allow_url_include) — PHP Manual
- Core php.ini directives (open_basedir, expose_php) — PHP Manual