PHP Security
PHP is still everywhere. The CMS the marketing team set up four years ago is
PHP. The legacy admin panel behind a /wp-admin/ alias is PHP. The internal
ticketing system “we’re going to rewrite” is PHP.
Most of the time, the bug is not a creative new exploitation technique — it is one of the same patterns the language quietly encourages. This section is a code-review catalog: each page lists the grep patterns, the test inputs that trip the bug, what to verify when reviewing each hit, and the fix.
How to use this catalog
Pick one bug class per pass. For each, run the grep against the codebase, triage the hits using the “Audit focus” section, and confirm exploitability on the running app with the test inputs.
Going through all ~20 in sequence on a single codebase is a solid day-or-two security review and tends to surface more findings than chasing “interesting” exotic bugs first.
These pages assume source access. Without source, work backwards from the Bug Bounty and Web Security sections — same bug classes, different angle.
Type confusion
PHP’s == and a handful of std-lib functions do silent type coercion.
Almost always not what the developer meant.
- Type Juggling — the
==family - Magic Hash Bypass —
0e…hash collisions in_arrayStrict Mode — the missing third argstrcmp()Array Injection —NULL == 0intval()Bypass — silent tail-dropstrpos() == falseBug — match-at-0 footgun
Variables & scope
Functions that write to the local scope from untrusted input.
Deserialization
Magic-method gadget chains via unserialize and the PHAR stream wrapper.
Injection
Untrusted strings reaching a sink that interprets them as code, SQL, filesystem paths, or remote URLs.
- SQL Injection — PHP code review angle
- Command Injection — including argument injection
- Local File Inclusion (LFI)
- Remote File Inclusion (RFI)
- Path Traversal
- File Upload — extension, MIME, storage, execution
HTTP & network
$_SERVER values and outbound HTTP that escape the app’s perimeter.
Auth logic
The meta-checklist that sits on top of every other page. Most of the bugs above graduate to “privilege escalation” when this is missing.
Quick grep cheatsheet
For when you just want one big rg to dump every interesting hit and
triage from there:
rg -n --type=php \
'== |!= |switch\(|in_array\(|array_search\(|strcmp\(|strcasecmp\(|intval\(|\(int\)|strpos\(|!strpos\(|extract\(|parse_str\(|\$\$\w+|unserialize\(|file_exists\(|file_get_contents\(|fopen\(|copy\(|unlink\(|rename\(|getimagesize\(|move_uploaded_file\(|\$_FILES|system\(|exec\(|shell_exec\(|passthru\(|popen\(|proc_open\(|query\(|mysqli_query\(|->query\(|->exec\(|prepare\(.*\$|HTTP_HOST|SERVER_NAME|header\(.*Location:|\binclude\b|\brequire\b|file_put_contents\(|fwrite\(|readfile\(|curl_exec\(|fsockopen\('Then run the page-specific greps for follow-up. The pages above each have narrower regexes that produce fewer false positives.
Related sections
- Web Security — black-box exploitation perspective
- Bug Bounty — finding these in scope you don’t have source for
- Payloads — quick payload reference
- Methodology — review workflow this catalog plugs into