Guide · 7 min read

How to prove your server is patched for PHP2Shell, when the version number can’t

The short answer

You can’t prove a PHP patch from the version number. Many hosts and Linux distributions ship the fix as a backport that keeps the old version number. The command-line php -v may not be the PHP that serves your website. And a patched package isn’t actually running until PHP’s worker processes restart (source: AlmaLinux).

Proof is evidence, gathered for every PHP runtime that serves web traffic:

Write the result down per CVE, with a timestamp and a list of what’s still open.

Why the version number misleads

There are three separate reasons, and each one is enough on its own.

  1. Backports keep old numbers. When a host or distribution fixes a flaw in the PHP version it already ships, it usually patches that version in place. The fix is in, but the number doesn’t change. AlmaLinux put it simply: “Don’t rely on php -v: our fixes are backported, so the upstream PHP version number doesn’t change.” (source: AlmaLinux) Xserver, a Japanese host, patched PHP 5.6 to 8.1 without changing version numbers (source: AlmaLinux).
  2. The command line may not be your website’s PHP. php -v reports the command-line PHP. The PHP serving your website may be a different build, running through PHP-FPM, Apache’s module or LiteSpeed (source: AlmaLinux).
  3. A patched package isn’t a patched process. Updating the package changes files on disk. Worker processes that were already running keep the old code until they restart (source: AlmaLinux).

The same logic cuts both ways. A tool that reads version numbers can report a patched server as unpatched, and an unpatched one as fine. A version string is an indicator, not a verdict (source: AlmaLinux).

What counts as evidence

Evidence isn’t all equal. We grade it on four levels, and we suggest you do the same.

Level What it is Example Use it for
1 · Runtime-verified Checked inside the running PHP that serves the site The live web PHP reports the patched build and the right setting, and its workers started after the update The strongest record you can give management, customers or an insurer
2 · Package-verified The installed package’s changelog or vendor advisory names both CVEs Changelog lists CVE-2026-109618 and CVE-2026-109619 Strong, once paired with a restart record
3 · Host-attested Your host confirms it in writing A dated ticket reply covering your account Shared hosting, where you can’t look inside
4 · External indicator only What the site shows the internet A version header; an online scanner result Triage. Never proof

The five checks

Run them for every PHP runtime that serves web requests: production, staging, old copies of the site, and any PHP bundled with a control panel or application on the same server. Cyber insurer Coalition gave its policyholders the same first step: find every PHP system (source: Coalition).

1. Identify the PHP that actually serves the site

Check what the web server runs, not the command line (source: AlmaLinux). Your control panel’s per-site PHP setting is a starting point. For certainty, a developer can read the version and settings from inside the web PHP itself, for example with a temporary diagnostic page that is deleted straight afterwards and never left public. Note how PHP runs too (PHP-FPM, Apache mod_php, LiteSpeed). Researchers rate Apache with mod_php as the highest-risk setup (source: Beazley Security Labs).

2. Match the build to a fix

3. Confirm the restart

Find when the PHP worker processes last started (the PHP-FPM pool, Apache or LiteSpeed), and compare that with when the package was installed. The workers must have started after the update (source: AlmaLinux). If the site runs in containers, the running containers must come from a rebuilt image.

4. Check the CVE-2026-115560 setting

As of October 23, 2026, no PHP release fixes CVE-2026-115560. PHP recommends turning off session upload progress (session.upload_progress.enabled=0) in php.ini, the PHP-FPM pool or the server configuration, then restarting PHP. Setting it with ini_set() or a per-directory .user.ini file doesn’t count (source: php.net advisory on CVE-2026-115560, October 23, 2026). Read the value from the web PHP, not the command line, for the same reason as check 1 (source: AlmaLinux). PHP says exploitation needs an unusual configuration and is unlikely (source: php.net advisory on CVE-2026-115560, October 23, 2026). Until a fix ships, though, it’s an open issue, so it belongs on every status record.

5. Write it down

A status that will stand up later has four parts: the CVE, the status, the evidence level, and the time it was true. Then list what’s still open. An illustrative record for one server:

Server: web-01 (PHP-FPM, PHP 8.3 branch)             As of: 2026-10-23 14:20 UTC
CVE-2026-109618  Patched  Package changelog names the CVE; workers restarted 13:55 UTC  Level 2
CVE-2026-109619  Patched  Same package and restart                                      Level 2
CVE-2026-115560  No upstream fix yet. Recommended setting in pool, read from web PHP  Level 1
Open issues:     CVE-2026-115560 awaiting a PHP release; PHP 8.3 security fixes end 31 Dec 2027

Notice what the record doesn’t say: “done” or “patched, full stop”. It says what was true, when, and how you know. That’s the version that still holds up a month later.

Shared hosting: what proof can you get?

On shared or managed hosting you can’t inspect the server, so the strongest evidence is your host’s written confirmation (level 3). As of October 23, 2026, many hosts had reported patching their managed plans (source: GoDaddy). But a general status page isn’t specific to your site, and status pages change. Ask for a dated reply that covers your account; the questions to ask are here. Save a dated copy of the reply and of any status page you rely on.

What doesn’t count as proof

Often offered as proof Why it falls short
php -v output Backports keep the old number, and the command line may not be the web PHP (source: AlmaLinux).
A version header or an online scanner result External indicator only (level 4), with the same backport problem (source: AlmaLinux).
“We updated WordPress and all the plugins” The flaw is in the PHP engine, and WordPress updates don’t change PHP (source: php.net security advisory, October 21, 2026; WordPress.org version statistics).
“We’re behind a firewall” Firewalls help, but they don’t replace the patch (source: Beazley Security Labs). Cloudflare’s rules only cover traffic that passes through Cloudflare (source: Cloudflare).
“We patched it”, with no date or restart A package on disk isn’t a running process (source: AlmaLinux).
An empty error log PHP’s advisory warns that “absence of an error in logs is not proof of safety.” (source: GHSA-6wmf-4rv5-p3rp (CVE-2026-109619))
A public exploit that “didn’t work” Researchers say many published proof-of-concept versions don’t work (as of October 23, 2026), so a failed attempt proves nothing (source: CERT-EU). Running exploits against production is a risk of its own.

Why it’s worth doing properly

Because people outside your company will ask. Coalition alerted all its policyholders with internet-exposed PHP on October 21. It told them to find every PHP system, update or get a vendor backport, and check for compromise (source: Coalition). Customers and partners send security questionnaires. A dated, per-CVE record answers them once. What evidence to keep for your insurer.

The method also outlasts this incident. Backports and restarts will matter for every future PHP fix. And PHP 8.2 reaches end of life on December 31, 2026, which is the next date your records need to cover (source: php.net supported versions). Plan for it here.

Managing many sites? The same evidence levels drive the go/no-go calls in our agency triage guide.

Sourced facts

Full wording, primary sources and dates: /sources.

ID Fact Primary source Date
S-09 · Q-12 Version numbers can’t prove a patch; backports keep old numbers AlmaLinux · CloudLinux · Red Hat · Xserver Oct 21–23, 2026
S-01 Two CVEs with different root causes php.net Oct 21, 2026
S-02 Fixed releases php.net Oct 21, 2026
S-02b CVE-2026-115560 unfixed; server-level setting + restart php.net Oct 23, 2026 · LIVE
S-03 No official fix for 8.1 and older Beazley Oct 21–23, 2026
S-04 mod_php rated highest risk Beazley Oct 21–23, 2026
S-05b Managed hosts reported patching managed plans Hostinger · WP Engine Oct 21–23, 2026 · LIVE
S-06c PoCs circulating; researchers say many don’t work CERT-EU · The Record Oct 23, 2026
S-10 / S-10c Firewalls don’t replace the patch; Cloudflare scope Beazley · Cloudflare Oct 21–23, 2026
S-32 / S-32b 8.2 ends Dec 31, 2026; 8.3 ends Dec 31, 2027 php.net Checked Oct 23, 2026
S-36 WordPress updates don’t change PHP WordPress.org Oct 23, 2026
S-48 Coalition alerted all policyholders with exposed PHP Coalition Oct 21, 2026
Q-11 PHP advisory: “absence of an error in logs is not proof of safety.” GHSA-6wmf-4rv5-p3rp Oct 21, 2026

Frequently asked questions

Is php -i more reliable than php -v?

No. Both commands run the command-line PHP, which may not be the PHP that serves your website (source: AlmaLinux). Read the version and settings from the web PHP itself.

My scanner says I’m unpatched, but my host says I’m patched. Who’s right?

You can’t tell from the version number, which is all most external scanners can see (source: AlmaLinux). Treat the scanner as a level 4 indicator. Ask your host for a dated written confirmation (level 3), or collect package and restart evidence (levels 1–2) if it’s your server.

Should I run a public exploit to check whether I’m still exposed?

No. Researchers say many published proof-of-concept versions don’t work, so a failed attempt tells you nothing (source: CERT-EU). Running exploit code against a production site carries its own risk. Verify from the inside instead.

How often should I re-check?

Re-check after every PHP update, restart or redeploy, and whenever a fix for CVE-2026-115560 ships, because that changes the status line (source: php.net advisory on CVE-2026-115560, October 23, 2026). Keep each dated record rather than overwriting it.

Want us to collect the evidence?

  • Patch Verification & Compromise Review. Your developer or host gives us read-only access: a dedicated login that can look but not change anything, shared through a secure link, never by email. We change nothing on your server. We run the five checks above and give you the per-CVE record in a plain-English report, plus a check for signs of compromise since October 17. We never run exploits to “prove” a site is vulnerable or fixed. Ask for it

Your website, accounted for.

Want a signed answer instead?

A Patch Verification gives you per-CVE status for every PHP runtime on the server, and a compromise review, in 1 business day.

$590 per server, includes 1 site.

See all services and prices

Sources

Every figure and quotation on this guide links to its primary source. All of them, with the date we last checked each: full wording and methods.

Primary sources for this guide