Safeguard
Industry Analysis

PHP Security Explained

PHP still runs ~74% of the web. From the 2024 PHP-CGI RCE to WordPress plugin flaws, here's what actually breaks PHP apps in production.

Bob
Application Security Engineer
Updated 8 min read

PHP runs an estimated 74% of the web's server-side code, according to W3Techs, and WordPress alone accounts for roughly 43% of all websites — nearly all of it PHP under the hood. That footprint is why PHP security incidents rarely stay theoretical for long, and why php security issues and php security vulnerabilities show up disproportionately often in vulnerability databases relative to PHP's real share of new code being written — which is also why a dedicated php security scanner is standard tooling in most PHP shops rather than an optional extra. On June 6, 2024, the PHP team shipped 8.1.29, 8.2.20, and 8.3.8 to fix CVE-2024-4577, a PHP-CGI argument injection flaw on Windows disclosed by researcher Orange Tsai; within days, honeypots were logging active exploitation, and by mid-July it had been tied to ransomware intrusions. PHP itself has matured a lot since the PHP 5 era, but the ecosystem around it — legacy extensions, Composer dependencies, misconfigured php.ini files, and unsupported point releases — still produces a steady stream of high-severity CVEs. This post walks through what actually breaks in production PHP applications, the vulnerability classes attackers reach for first, and where the gap sits between "patched" and "actually secure."

Why does PHP still matter for security teams in 2026?

Because PHP still runs the majority of the dynamic web, and most of it is running dependency trees nobody has fully inventoried. For php cyber security teams tracking exposure across a fleet of services, that dependency sprawl is the bigger risk multiplier, not the language runtime itself. W3Techs has tracked PHP's share of sites with a known server-side language at roughly 74% for years, and Packagist, the primary Composer registry, has grown past 450,000 packages. Every one of those packages can pull in transitive dependencies that a security team never explicitly chose. On top of that, PHP's own release cadence creates exposure windows: PHP 8.0 reached end-of-life on November 26, 2023, PHP 8.1's security support ended November 25, 2024, and PHP 8.2 moves to security-only support in December 2025. Teams running any of these past their support dates are, by definition, running unpatched software for known CVEs — a fact scanners pick up on immediately, and one that's easy to lose track of when an application spans a dozen microservices built at different times.

What vulnerability classes actually get PHP applications compromised?

The recurring php security issues are SQL injection, insecure deserialization via unserialize(), local/remote file inclusion, and type-juggling authentication bypasses — not exotic zero-days. SQL injection persists because string-concatenated queries still show up in legacy codebases and quick internal tools, even though PDO prepared statements have been standard practice for over a decade. Insecure deserialization is PHP-specific and dangerous: passing untrusted input to unserialize() lets an attacker instantiate arbitrary objects and trigger "magic methods" like __wakeup() or __destruct(), chaining them into remote code execution — the same class of bug behind CVE-2016-10033 in PHPMailer, which allowed RCE through a crafted "From" address. File inclusion bugs (include()/require() fed by user input) turn a simple path traversal into full server compromise. And type juggling — where PHP's loose == comparison treats a hashed password or token as equal to 0 or false under the wrong conditions — has produced real authentication bypasses in production frameworks. A fifth, quieter offender: CVE-2017-9841, an RCE in PHPUnit's eval-stdin.php test utility left exposed in vendor/ directories, is still hit by automated botnet scans in 2025, seven years after disclosure, because so many deployments never remove test tooling from production.

What does the CVE-2024-4577 PHP-CGI RCE actually teach us?

It shows that patch velocity for PHP is often measured in hours, not weeks, once a working exploit is public. The vulnerability stemmed from how Windows converts certain Unicode characters during locale-based "best-fit" encoding, which let an attacker smuggle a PHP command-line argument through a URL when PHP ran in CGI mode behind Apache or IIS on XAMPP-style setups. DEVCORE reported it in May 2024, the PHP project patched it on June 6, 2024, and public proof-of-concept code followed almost immediately. Within roughly 48 hours, security vendors observed internet-wide scanning, and by July 2024 the flaw had been linked to Akira and Lockbit ransomware affiliates using it as an initial-access vector against unpatched Windows/Apache/PHP stacks — a combination still common in shared hosting and legacy internal tools. The lesson isn't "patch faster" in the abstract; it's that any PHP CGI deployment on Windows was a ticking clock the moment the CVE was public, and organizations without automated dependency and runtime inventories had no fast way to know which of their assets were even affected.

Why do WordPress and other CMS platforms dominate PHP breach reports?

Because plugins, not WordPress core, are where almost all the exploitable bugs live, and WordPress's massive install base makes those bugs worth scanning for at internet scale. WordPress core itself has a reasonably strong security track record and an automatic-update mechanism for minor releases, but the plugin ecosystem is enormous and unevenly maintained — tens of thousands of plugins in the official repository alone, many written by small teams without a security review process. Wordfence's threat intelligence team has tracked tens of thousands of vulnerability disclosures across WordPress plugins and themes over the years, the large majority rated as cross-site scripting or SQL injection, and a meaningful share never get patched because the plugin is abandoned. Most of these php security vulnerabilities are found by researchers long before a botnet weaponizes them, but plugin maintainers frequently ship the fix late or not at all. A single popular plugin vulnerability, once weaponized, gets scanned for across millions of sites within hours, because attackers already know the exact request pattern that triggers it. This is the pattern behind most mass PHP compromise waves: not a novel zero-day, but a known CVE in a widely installed plugin that a site owner never updated.

How much of PHP's real-world risk comes from Composer dependencies rather than PHP core?

A large and growing share, because most PHP applications are built on frameworks like Laravel and Symfony plus dozens of third-party packages, and vulnerabilities in that supply chain are far more common than vulnerabilities in the PHP interpreter itself. A typical mid-sized Laravel application easily pulls in 100-plus transitive Composer dependencies through packages like guzzlehttp/guzzle, symfony/* components, and testing libraries that sometimes ship to production by mistake. Packagist has also seen typosquatting attempts — malicious packages published under names that closely mimic popular ones, banking on a developer's composer require typo. Because composer.lock pins exact versions but rarely gets revisited, a project can carry a vulnerable transitive dependency for years without anyone noticing, since the top-level composer.json never changes even as CVEs accumulate underneath it. This is precisely the blind spot that traditional CVE scanning misses: a scanner can tell you guzzlehttp/psr7 has a known advisory, but it can't tell you whether your application's actual code path ever calls the vulnerable function.

What does a hardened PHP production configuration actually look like?

It starts with disabling the functions that turn an injection bug into full remote code execution, and it goes well beyond php.ini defaults. Set disable_functions to block exec, shell_exec, system, passthru, and popen unless a specific application genuinely needs them. Turn allow_url_include and allow_url_fopen-driven includes off to kill remote file inclusion outright. Set expose_php = Off so response headers stop advertising your exact PHP version to attackers running mass scans for version-specific CVEs. Disable display_errors in production and log to a file instead, since verbose PHP error output routinely leaks file paths and stack traces useful for reconnaissance. Set session.cookie_httponly and session.cookie_secure to protect session tokens, and run OPcache with opcache.validate_timestamps tuned deliberately rather than left on defaults. Finally, run a currently supported PHP version — 8.3 or 8.4 as of early 2026 — since anything on 8.1 or earlier is accumulating unpatched CVEs by design, not by accident. Treat this checklist as the baseline any php cyber security program should enforce before code reaches production, not an optional hardening step reserved for post-incident cleanup.

How Safeguard Helps

Safeguard closes the gap between knowing a PHP CVE exists and knowing it actually matters to your application. Any php security scanner can flag that a package carries a CVE; the harder job — and the one that actually cuts triage time — is proving whether your application calls the vulnerable function at all. Reachability analysis traces whether the vulnerable function in a flagged Composer package — say, a deserialization sink or a vulnerable Guzzle method — sits on a code path your application actually executes, so security teams stop triaging thousands of theoretically-vulnerable dependencies and start fixing the ones that are exploitable. Griffin AI, Safeguard's remediation agent, reads the advisory, checks it against your call graph, and drafts context-aware guidance instead of a generic "upgrade to latest" ticket. Safeguard generates SBOMs directly from composer.lock and can ingest SBOMs from CI pipelines, giving you a live inventory of every PHP package and its transitive dependencies across every repo. When a fix is available, Safeguard opens an auto-fix pull request with the minimal version bump needed to resolve the CVE, so the fix ships without a developer having to hunt down the right patched version by hand.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.