Skip to content

PHP2Shell: how to check which PHP version your site runs

On 21 October 2026 the PHP project released fixes for two critical remote code execution flaws, CVE-2026-109618 and CVE-2026-109619, now widely called PHP2Shell. Here is how to find the PHP version behind your site and what to do with the answer.

By ZNIMOK

What PHP2Shell is

PHP2Shell is an informal name that security vendors use for two vulnerabilities in PHP itself, not in a CMS or a plugin. The PHP project does not use the name. Its advisory calls the flaws “RCE via OOM corruption” and “RCE via stale global state”.

According to php.net, in CVE-2026-109618 out-of-memory handling can interrupt PHP while internal request data is only partly initialized, and request cleanup may then treat invalid data as valid. In CVE-2026-109619 request-owned internal state can survive after its memory has been freed, and a later request handled by the same worker may use it. Both can allow remote code execution without authentication. The PHP project rates both 9.2 (critical) on CVSS v4.0.

On 26 October 2026 CISA added both CVEs to its Known Exploited Vulnerabilities catalog, which means CISA has evidence of exploitation in the wild. That makes the update urgent. It is not a reason to panic: the steps below take minutes to start.

Affected and fixed versions

The fixed releases came out on 21 October 2026. php.net lists every earlier release of a supported branch as affected. Branch status as listed on php.net: supported versions.

PHP branch First fixed release Status
8.5 8.5.12 Supported
8.4 8.4.27 Supported
8.3 8.3.36 Security fixes until 31 December 2027
8.2 8.2.35 Security fixes until 31 December 2026
8.1 and older No official release End of life: vendor backport or upgrade

Linux distributions and LTS vendors received the patches in advance and ship them in their own packages. php.net also published minimal source backports for 7.4, 8.0 and 8.1 for people who build PHP from source.

Who is at risk

php.net names all PHP installations that serve web requests: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The PHP team considers the risk highest for mod_php, where a demonstrated exploit runs before any application code. In practice this means almost every PHP website: WordPress, Joomla, Drupal, Laravel, online shops and hand-written sites alike. Updating the CMS does not help here, because the flaw is in PHP.

How to check your PHP version

Use more than one method if you can. The version you see in one place is not always the one that serves your pages.

  • Hosting panel. In cPanel, Plesk or a similar panel, open the PHP settings for the domain. This shows the version the web server uses for that site, which is the one that matters.
  • A temporary phpinfo page. Create a file with a random name containing <?php phpinfo();, open it in the browser, note the “PHP Version” and “Server API” lines, then delete the file right away. A forgotten phpinfo page tells everyone your full configuration.
  • Response headers. Run curl -I https://your-site.example or open the Network tab in the browser developer tools and look for a line such as X-Powered-By: PHP/8.3.30. Many servers hide this header, so its absence tells you nothing.
  • Command line. php -v on the server shows the version of the command-line PHP. It can differ from the version PHP-FPM or mod_php uses for the site, so check the web version as well.
  • Package manager. If PHP comes from your Linux distribution, check the package release, for example rpm -q php-common on AlmaLinux or dpkg -l | grep php on Debian and Ubuntu, and compare it with your vendor’s security notice.

A hidden version is not proof of safety

If your site does not send X-Powered-By, an outside check cannot read the version. Hiding it is a sensible setting (expose_php = Off in php.ini), but it only hides the number. If PHP was not updated, the vulnerable code is still running. The PHP manual itself calls security by obscurity “one of the weakest forms of security”.

The same applies to a firewall or CDN in front of the site. It may block some attack requests, but php.net is clear that only the update is a complete fix.

A matching version is not proof of compromise

The opposite mistake is just as common. If a scanner sees PHP/8.3.30, that only says the reported version is older than the upstream fix. It does not show that anyone attacked the site, and it may not even mean the site is vulnerable:

  • Distributions often backport fixes without changing the version number. AlmaLinux, for example, tells users not to rely on php -v and to check the package release instead.
  • The header may come from a different server than the one that runs your pages, such as an old proxy.
  • The header may be stale or set by hand.

A version match means “may be affected, needs checking”, not “hacked”. If you do suspect an intrusion, treat it as a separate job: check logs, look for unknown files and admin accounts, and involve your hosting provider.

What to do now

  • Find the exact PHP version and package that serve your site, using the methods above.
  • On 8.2 to 8.5, update to 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer, or to your distribution’s patched package. On shared hosting, ask support whether the fix for CVE-2026-109618 and CVE-2026-109619 is installed and keep the answer.
  • Restart every PHP worker after the update (PHP-FPM, Apache), so no process keeps running the old code.
  • On 8.1 or older, plan the move to a supported branch. Until then, ask your vendor whether it ships a backported fix.
  • If you cannot update today, php.net lists temporary measures, such as session.upload_progress.enabled=0 for CVE-2026-109619. In its own words they reduce exposure to specific attack paths but do not make an installation safe.
  • After updating, hide the version with expose_php = Off. That is tidying up, not protection.

What the ZNIMOK check shows

The outdated software check reads only what your site already sends to any visitor. If a response header reveals an exact PHP version, the report compares it with the latest security release of the same branch and with end-of-life data, and marks a gap as something to check, not as a confirmed vulnerability. If only the branch is visible, the report says the patch level is unknown. The check never sends exploit requests.

It is a quick way to see what an outsider can learn about your PHP version. Your hosting panel or server remains the authoritative source.

Questions

Is my WordPress site affected by PHP2Shell?

Potentially, if WordPress runs on an affected PHP version: the flaws are in PHP, not in WordPress. Updating WordPress does not fix them; updating PHP does.

My host says PHP is patched, but a scanner still shows an old version. Who is right?

Most likely your host, if it uses a distribution package with a backported fix. Ask which package release contains the fix for CVE-2026-109618 and CVE-2026-109619, and keep that answer with your records.

Should I just hide the X-Powered-By header?

Hide it, but only after updating. Hiding the number does not remove the vulnerability.

Sources

  1. php.net: news archive 2026 (security advisory of 21 October 2026) php.net
  2. NVD: CVE-2026-109618 nvd.nist.gov
  3. NVD: CVE-2026-109619 nvd.nist.gov
  4. CISA: Known Exploited Vulnerabilities catalog (JSON feed) cisa.gov
  5. AlmaLinux: patched PHP packages for CVE-2026-109618 and CVE-2026-109619 almalinux.org
  6. PHP manual: Hiding PHP php.net

See what your site reveals about its PHP version

Run the free external check: read-only requests, no sign-up.

Only check sites you own or are allowed to test. How our scanner works