[KongchangAI]
· 3 min read· 1,659 words

PHP Double Vulnerability Shakes the World: A Deep Dive into the Remote Code Execution Flaws

PHP Double Vulnerability Shakes the World: A Deep Dive into the Remote Code Execution Flaws

PHP exposed two RCE vulnerabilities affecting 14 years of versions, but the high exploitation barrier prevented a large-scale attack.

Based on a Computerphile video, this article reviews the mechanics, demo, and release chaos of two PHP RCE vulnerabilities. The flaws stem from worker-thread global state not being properly reset and from incorrect longjmp error-handling jump targets, affecting PHP 5 through 8.5—about 14 years of versions. The demo confirms remote command execution. The release was forced early due to a Hacker News leak and an exploit video, disrupting responsible disclosure. Exploitation requires binding to a specific worker and knowing target environment details, making it difficult—hence no large-scale attack. The PHP team discovered the flaw in 2024 but shelved the fix.

Title

PHP Double Vulnerability Shakes the World: A Deep Dive into the Remote Code Execution Flaws

Meta Description

Computerphile breaks down two recent PHP remote code execution vulnerabilities: versions spanning 14 years are affected, and attackers can run arbitrary code remotely. This article covers the vulnerability mechanics, a real-world demo, the chaotic release process, and why a large-scale attack never materialized.

Article Content

PHP, the backend language powering countless websites from WordPress to Wikipedia, has recently been thrust into the spotlight by two remote code execution vulnerabilities. In a video, Computerphile breaks down the vulnerability mechanics, a real-world demo, and the chaos surrounding the release. This article is based on that video and provides additional analysis.

What Exactly Are These Two Vulnerabilities?

According to Computerphile, PHP's working mechanism relies on a series of worker threads handling HTTP requests. Each worker holds global state that persists across requests, including error state, objects in use, and extension information; each request itself is ephemeral. When a request is processed or destroyed, references pointing to it should be properly cleaned up.

The key to the first vulnerability is that under certain exceptional paths, these references are not fully reset and still point to an already-destroyed old request. By carefully crafting multiple requests, an attacker may be able to make the server execute code they injected rather than the code the website author intended.

Vulnerability mechanics diagram

The second vulnerability is related to the longjmp mechanism in C. PHP uses longjmp for error handling in scenarios such as out-of-memory errors. If the jump lands in the wrong place and state is not properly reset, it too can be exploited to execute arbitrary code.

The common consequence of both vulnerabilities is that an attacker can send requests from their own computer to a target website and run code on its server. This means malicious operations such as data theft or using the server as a springboard to attack others become possible.

PHP's worker thread model is at the core of its efficient handling of concurrent requests: each PHP-FPM process maintains a group of workers, each independently handling requests and reusing global variables (such as PG(error_handling), EG(active_op_array), and resources registered by extensions) across requests to avoid repeated initialization. When a request ends, PHP executes php_request_shutdown to clean up this state, but the cleanup logic depends on precise reference counting and pointer resets. If some exceptional branch (such as an error thrown by an extension or a memory allocation failure) skips a step, it leaves behind a dangling pointer. Attackers using heap spraying and precise request timing control can cause subsequent requests to reconstruct controllable data in the freed memory region, thereby hijacking control flow. Similar vulnerabilities are not unprecedented in PHP's history, but this one spans as long as 14 years, highlighting the fragility of long-lived global state under complex error paths.

Demo: Actually Gaining Server Access

In the video, the presenter conducts a local demo using a publicly available Python exploit script. He first starts a minimal PHP server that only returns "ok," then runs the script. After the script finishes, it generates a file in the specified directory recording the result of executing the command id—the username is www-data, the typical web server runtime account.

Starting a simple PHP server

This demo makes one thing clear: the vulnerability is real, and the exploit script is indeed effective—it is by no means a gimmick.

Why Is the Impact So Broad?

The severity of the vulnerability lies not only in remote code execution but also in its time span. According to the video, the issue exists in PHP versions spanning roughly 14 years, from PHP 5 all the way to PHP 8.5. Given PHP's ubiquity in website backends worldwide, almost every site using WordPress is at risk.

This also explains why organizations such as the UK's NCSC issued strongly worded urgings: patching is mandatory, and if a timely fix is not possible, sites should be taken offline until remediation is complete. The presenter notes that official statements of this magnitude are uncommon.

Chaos in the Release Process and Responsible Disclosure

By convention, vulnerabilities should first be reported to developers through a responsible disclosure process, verified, and patched; then downstream distributions should be coordinated; and finally the vulnerability should be published together with a fix. But this time the process was unexpectedly disrupted: someone posted details to Hacker News without knowing, and an exploit video leaked ahead of time, forcing the entire release to be moved up.

Unexpected turns in the release process

The video also mentions a detail: the PHP team discovered one of the vulnerabilities back in 2024 and discussed whether to fix it, but at the time they could neither confirm the exploitation method nor find a fix that would not introduce other problems, so they shelved it. The presenter believes this may have been a wrong decision, but also emphasizes that the open-source team's achievements under limited manpower should be recognized.

As to whether the vulnerability was discovered with the help of large language models, the presenter offers a conjecture: the PHP team's public discussions from that year may have been absorbed into model training data, and some AI companies are investing substantial resources in using models to hunt for vulnerabilities. However, he explicitly states that it cannot currently be confirmed whether a model independently discovered the vulnerability, and further investigation is needed before drawing a conclusion.

Responsible Disclosure is a collaborative norm widely adopted by the security community, typically including: the discoverer privately contacting the vendor, granting a 90-day remediation window, and both parties coordinating the public disclosure time. Its core goal is to let users obtain patches before the vulnerability is made public, avoiding a "zero-day" attack window. In practice, however, this process is often disrupted by information leaks, difficulties in multi-party coordination, or slow vendor response. In this incident, the early exposure on Hacker News and the leaked exploit video directly compressed the time for the PHP team and downstream distributions (such as Debian, Ubuntu, and Red Hat) to synchronize patch releases. This "forced early disclosure" is known as premature disclosure and often leads to insufficient patch coverage and attackers getting a head start. Historically, OpenSSL's Heartbleed and Apache Log4j's Log4Shell faced similar dilemmas, showing that coordinated disclosure remains an incompletely solved challenge in highly centralized open-source ecosystems.

Why No Large-Scale Attack Occurred

Surprisingly, after the vulnerabilities were made public, the expected large-scale script-kiddie attacks did not materialize. The presenter analyzes that the reason is the exploitation barrier is not low.

Exploitation requires precise information

PHP has 150 worker threads by default, and requests are assigned randomly. An attacker must keep the other 149 threads busy with unrelated tasks in order to focus on attacking the remaining one. In addition, they need to know the PHP version running on the target, the operating system, and even the C compiler used at build time. If any external request reaches that idle thread first, the attack state is disrupted. Therefore, exploitation in a real production environment is far more difficult than in a local Docker container.

The presenter also raises an intriguing hypothesis: if a malicious actor first implanted backdoor code into PHP and then orchestrated a "global emergency patching" event like this, could they instead use the update as an opportunity to spread malicious code? He stresses that this is just a thought experiment and does not believe it actually happened, but it is worth being vigilant about.

PHP-FPM's default pm.max_children is 150, and requests are assigned to idle workers by the kernel or the FPM scheduler; the assignment strategy does not guarantee that a request lands on a specific worker. To exploit the vulnerability, an attacker needs to ensure the malicious request is handled by the worker holding the "dirty" global state while preventing other requests from preempting it. A common technique is to send a large number of slow requests (slowloris-style) to occupy the remaining workers, then precisely send the malicious request. But this process is extremely sensitive to network latency, server load, and timing, and different PHP versions, operating systems (glibc versions affect heap layout), and compilers (GCC and Clang differ in stack layout) all change the memory layout, making exploit scripts highly dependent on target environment information. In addition, modern web servers often deploy WAFs or reverse proxies at the front end, which may intercept abnormal request patterns in advance. Therefore, although the vulnerability is theoretically extremely dangerous, the actual weaponization barrier is much higher than in a local lab environment—this is the main reason no large-scale worm-like attack occurred.

A Reminder for Developers

This incident once again shows that once a remote code execution vulnerability appears in widely depended-upon open-source infrastructure, the impact can grow exponentially. For website administrators, promptly following up on patches and decisively taking sites offline when fixes are unavailable remain the most effective countermeasures. For open-source maintenance teams, how to balance vulnerability remediation and compatibility risks under limited resources will also remain a long-standing challenge.

One-line Summary

PHP exposed two remote code execution vulnerabilities affecting 14 years of versions, but the high exploitation barrier prevented a large-scale attack.

Paragraph Summary

Based on a Computerphile video, this article reviews the mechanics, demo, and release chaos of two PHP remote code execution vulnerabilities. The flaws stem from worker-thread global state not being properly reset and from incorrect longjmp error-handling jump targets, affecting PHP 5 through 8.5—about 14 years of versions. The demo confirms attackers can execute commands remotely. The release process was forced to move up due to a Hacker News leak and an early exploit video, disrupting the responsible disclosure rhythm. Actual exploitation requires binding to a specific worker thread and knowing target environment details, making it difficult—hence no large-scale attack occurred. The PHP team discovered the vulnerability in 2024 but shelved the fix, sparking discussion about open-source maintenance resources and decision-making.

#PHP vulnerability#remote code execution#RCE#Computerphile#responsible disclosure#PHP-FPM#longjmp#WordPress security
Share:

Related articles