On October 21, PHP released emergency fixes for PHP2Shell (CVE-2026-109618 and CVE-2026-109619), two critical flaws in the PHP engine rated CVSS 9.2. Our team at Arc Technologies upgraded every PHP workload we host that same day. Two days later, the first PHP2Shell attack reached us. It failed, but the patch is not what stopped it.
What PHP2Shell is
PHP2Shell abuses the code PHP uses to track file upload progress in a user’s session. That code runs before any application code. As a result, a single unauthenticated upload request can reach it on almost any PHP site, including pages that never handle uploads. The setting it depends on is on by default.
What we saw in the first week
219 PHP2Shell-related requests from 2 IP addresses against 2 hosts
The first request arrived about two days after the fix was released
6 distinct payload families once every request was decoded
0 successful executions
The patch only covers one layer
This is the finding we most want people to take away. Only 5 of the 219 requests went after the new memory corruption bug. The other 214 ran an older file inclusion chain that comes bundled with the public PHP2Shell tools. It plants PHP code in a session file through the upload progress feature, then tries to get a vulnerable script to load that file. It also tries stream wrappers and a filter chain that builds code from nothing but character-set conversions.
None of that depends on the PHP version. A fully patched server is still exposed if its application has a file inclusion flaw.
There is no warning shot
Most React2Shell traffic starts with a harmless “are you vulnerable?” check. This tooling skips that step. Every payload that carries code proves it ran and collects secrets in the same request: environment variables, .env files, framework configuration, AWS credentials, SSH keys and git credentials. On a vulnerable host, the first successful response would already contain the site’s secrets.
A familiar operator
The largest attempt came from 193.47.62.167. In our React2Shell study, we documented an IP in the same range running a secret-file sweep and a Kubernetes harvester against us on October 12. On October 23 it sent 214 PHP2Shell requests in 23 minutes, hunting for the same files. The exploit changed, the shopping list did not.
What would have happened?
We modelled each request as if it had succeeded. If the targeted non-profit dashboard had an inclusion flaw, the attacker would have had its full environment and every configuration file and credential within reach in under 23 minutes. That includes database credentials to records about the people the organization serves.
Why we weren’t affected
Two independent controls stopped this traffic, and neither alone would have been enough. The same-day patch removed the memory corruption path. The inclusion chain failed because a code review found no include or require statement fed by request input, and allow_url_include is disabled.
Lessons for defenders:
1. A patched runtime is not a safe application. Patch, and also remove file inclusion flaws.
2. Expect secrets to be taken on the first successful request. There is no reconnaissance phase to catch.
3. Plan for days, not weeks. Attack traffic reached us just days after the fix shipped.
4. Harden around the flaw and keep cloud and SSH credentials out of the web user’s reach.
The full anonymized field note is attached HERE including indicators of compromise and detection patterns.
