banner

SQLi Detection in PHP with Static Analysis

Most people find SQL injection the same way: point a tool at a running web page and start throwing payloads at every input field. sqlmap, Burp Suite, Nessus – all of them work by poking the rendered application from the outside and watching how it responds. That approach works, but it has a structural problem: you’re testing behaviour, not code. A page has to be deployed and reachable before you can test it, and a payload has to happen to trigger the vulnerable path before you find it.

Static analysis takes a different route to SQLi detection in PHP: read the source code itself and trace whether untrusted input can reach a database query without being sanitised. Done well, it catches bugs before the code is ever deployed, and it can be wired straight into a build pipeline or pre-commit hook. Done badly, it drowns you in false positives. Here’s how it actually works for PHP, and what’s out there if you want to try it yourself.

Blackbox vs Whitebox: Two Different Problems

Security scanners split roughly into two camps:

  • Blackbox tools – sqlmap, Vega, Nessus, Metasploit – run against the live, rendered output of an application. They don’t see the source; they infer vulnerabilities from how responses change under crafted input. They’re accurate about what’s actually exploitable, but slow, and they can only find what they think to try.
  • Whitebox tools read the source code directly and trace data flow through it. They can find vulnerable code paths that were never triggered in testing, but historically they’ve had a rougher time with PHP than with statically typed languages, because PHP’s dynamic typing and permissive syntax make it genuinely hard to trace a variable’s origin with certainty.

Blackbox tools tend to have a much nicer end-user experience – a dashboard, a history, a clear “here’s what we found” report. Whitebox tools have historically been console-first, aimed at researchers rather than teams who want to bolt a check into CI.

The Core Technique: Taint Analysis

Nearly every whitebox SQLi detector is built around taint analysis: mark data coming from an untrusted source ($_GET, $_POST, $_COOKIE, request headers) as “tainted”, then trace whether that tainted value can reach a “sink” – typically a database query function – without passing through a sanitisation step first. If tainted data reaches a sink unsanitised, that’s a candidate vulnerability.

The academic literature on this goes back further than you’d think. Two projects worth knowing about:

  • Pixy – one of the earliest static analysis tools purpose-built for detecting web application vulnerabilities in PHP, using flow-sensitive, interprocedural data flow analysis. It only ever supported PHP 4, which limits its usefulness today, but the underlying technique it popularised is still how most modern tools work.
  • Ardilla – a research tool that took a more aggressive approach, modifying the Zend Engine itself (PHP’s runtime) to perform taint analysis at the interpreter level rather than by parsing source statically. It combined this with automatic generation of concrete SQLi and XSS attack strings to confirm exploitability, rather than just flagging a suspicious code path.

Both are research projects rather than tools you’d install today, but they establish the pattern every practical tool follows: taint tracking plus optional confirmation via generated exploit strings.

Tools You Can Actually Use

RIPS is the most complete answer to “is there a modern PHP static analyser for this.” It started life as a research project with a web-based interface and statistics dashboard, and has since been rewritten into a commercial product with proper CI integration, historical tracking, and support for modern PHP versions and frameworks. If you want whitebox SQLi and XSS detection with the reporting polish of a blackbox tool, this is the closest thing.

More generally, PHPStan and Psalm – primarily static type checkers rather than security tools – can be configured with security-focused rule sets that catch some of the same unsanitised-input patterns, though they’re not purpose-built for it the way RIPS is. For a lighter check that fits naturally into a code review workflow rather than a dedicated scanner, PHP_CodeSniffer with a security ruleset (like the WordPress Coding Standards’ security sniffs) will flag obviously unescaped variables in query strings, though it works on surface patterns rather than true data-flow tracing.

Why This Is Still Worth Doing

The case for static analysis hasn’t really changed since the research above was written: it’s cheaper to catch a vulnerable query at commit time than after deployment, it doesn’t depend on a tester happening to hit the vulnerable code path, and a good implementation can maintain a history of what’s been found and fixed, tied directly to the line of code and the commit that introduced it – something a one-off blackbox scan can’t give you.

The honest limitation is the same one PHP’s dynamic typing has always created for whitebox analysis: it’s genuinely hard to be certain a variable’s origin and sanitisation state without running the code, which is exactly why static tools still generate false positives and why blackbox confirmation (sqlmap against a staging environment, for instance) remains a useful second pass rather than a replacement.

A Practical Combination

For a real project, the two approaches work best stacked rather than chosen between:

  1. Run a static analyser (RIPS, or a security-focused PHPStan/Psalm ruleset) as part of CI, on every pull request, so unsanitised query construction gets flagged before merge.
  2. Use parameterised queries (PDO prepared statements, or your ORM’s query builder) everywhere as the actual fix – static analysis finds the problem, it doesn’t solve it.
  3. Periodically confirm with a blackbox tool like sqlmap against a staging environment, to catch anything the static pass missed and confirm real exploitability of anything it flagged.

If you’re setting up automated SQLi testing on a target you’re authorised to test, our SQLmap guide on Kali Linux covers the blackbox side of this in detail – database enumeration, blind injection, and WAF evasion.


Leave a Reply