Cheatsheet
The behavioural source of truth for this site. Every cell in the first table is checked against the payload builder at build time — if the table and the generator ever disagree about a verdict, the build fails.
Does the inclusion fire?
Rows are the wrapper and the sink it is aimed at. Columns are the target's php.ini. Depends means something outside the config decides it — read the note, and say which condition held in your finding.
The three things this table exists to settle
allow_url_fopenandallow_url_includeare not the same flag. Reading a remote URL needs the first, which is On by default. Executing one needs the second, which is not. That single distinction is whyfile_get_contents('http://…')is live SSRF on a stock host whileinclude('http://…')has been dead since 2006.php://filteris not governed byallow_url_include. It runs on the shipped default. This is the whole reason the modern escalation path goes through a filter chain rather than a remote fetch.- Whether the sink executes decides the severity, not the payload. The same traversal is disclosure through
readfile()and RCE throughinclude().
What this table does not cover
- Whether your input reaches the start of the string. Every wrapper row assumes it does.
include('pages/' . $page)defeats all of them at once, because a scheme only counts at position zero. - An appended extension. Assume none; see Extension Append Bypasses for what survives one.
- The last two rows are prose. Log poisoning and the temp-file race are not wrapper outcomes, so the build script counts them and skips them rather than pretending to derive a verdict.
The same bug in seven runtimes
PHP is the only column with a stream-wrapper layer, which is why it is the only one where a filename can become a URL. Everywhere else, file inclusion degrades to path traversal — still a finding, rarely code execution.