PHP2Shell · CVE-2026-109618 · CVE-2026-109619 · CVSS 9.2

Find every PHP build on a server and prove which ones are patched.

Bastion is an open-source command-line tool that runs on your own machine. It inventories PHP from system packages, hosting panels, containers and images, decides whether each build carries the fix (including distribution backports that keep the old version number), and looks for signs of an intrusion that happened before you patched.

$curl -fsSL https://larptard.github.io/bastion/install.sh | sh
  • Read-only
  • No network calls
  • Single static binary
  • Linux and macOS, amd64 and arm64
  • MIT
Command-line preview Sample report
sudo bastion scanrecorded output
$ sudo bastion scan

  ▲ BASTION  v0.1.0-dev · PHP exposure scan
  host web-01  ·  os Ubuntu 24.04.5 LTS  ·  kernel 6.18.44-fc-v140  ·  at 2026-10-22 09:03 UTC

   CRITICAL   PHP2Shell  CVE-2026-109618 · CVE-2026-109619  CVSS 4.0 9.2 · published 2026-10-21

  PHP INSTANCES ──────────────────────────────────────────────────────────────────────────────────────

  STATUS        TARGET       PATH                              SAPI     VERSION  SOURCE               
  ● VULNERABLE  shop-legacy  /usr/local/bin/php                cli      8.3.35   Docker official image
  ● VULNERABLE  shop-legacy  /usr/local/sbin/php-fpm           fpm      8.3.35   Docker official image
  ● VULNERABLE  host         /usr/bin/php8.3                   cli      8.3.6    System package (apt)
  ◐ LIKELY      worker-74    /usr/local/bin/php                cli      7.4.33   Docker official image
  ◐ LIKELY      worker-74    /usr/local/bin/php-cgi            cgi      7.4.33   Docker official image
  ● FIXED       api          /usr/local/bin/php                cli      8.4.27   Docker official image
  ● FIXED       api          /usr/local/bin/php-cgi            cgi      8.4.27   Docker official image
  ● FIXED       blog         /usr/lib/apac…/modules/libphp.so  mod_php  8.3.36   Docker official image
  ● FIXED       blog         /usr/local/bin/php                cli      8.3.36   Docker official image

  DETAILS ────────────────────────────────────────────────────────────────────────────────────────────

   VULNERABLE   /usr/local/bin/php @ container:shop-legacy
     sapi cli · version 8.3.35 (binary)
     ┌ PHP2Shell — PHP 8.3.35 is below 8.3.36 · confidence high
     │ ✗ version     PHP 8.3.35 is below the fixed release 8.3.36
     │ → fix         Rebuild on a patched base image: docker pull php:8.3-fpm (needs 8.3.36 or
     │               later), then rebuild and redeploy. Running containers keep the old binary until
     │               they are replaced.
     └
     ┌ interim mitigations — reduce exposure until the update; not a fix
     │ ✗ php.ini     session.upload_progress.enabled = 1          want 0 / Off · PHP default
     │ ✗ php.ini     memory_limit = 128M                          want -1 · PHP default
     │ ✓ php.ini     post_max_size = 8M                           want ≤ 32M · PHP default
     └

   VULNERABLE   /usr/local/sbin/php-fpm @ container:shop-legacy
     sapi fpm · version 8.3.35 (binary) · running pid 10344,10392,10393
     ┌ PHP2Shell — PHP 8.3.35 is below 8.3.36 · confidence high
     │ ✗ version     PHP 8.3.35 is below the fixed release 8.3.36
     │ → fix         Rebuild on a patched base image: docker pull php:8.3-fpm (needs 8.3.36 or
     │               later), then rebuild and redeploy. Running containers keep the old binary until
     │               they are replaced.
     └
     ┌ interim mitigations — reduce exposure until the update; not a fix
     │ ✗ php.ini     session.upload_progress.enabled = 1          want 0 / Off · PHP default
     │ ✗ php.ini     memory_limit = 128M                          want -1 · PHP default
     │ ✓ php.ini     post_max_size = 8M                           want ≤ 32M · PHP default
     └

   VULNERABLE   /usr/bin/php8.3 @ web-01
     sapi cli · version 8.3.6 (binary) · package php8.3-cli 8.3.6-0ubuntu0.24.04.12
     also reachable as /bin/php, /bin/php8.3, /usr/bin/php
     ┌ PHP2Shell — package 8.3.6-0ubuntu0.24.04.12 is older than the vendor fix 8.3.6-0ubuntu0.24.04.13 · confidence high
     │ · version     PHP 8.3.6 is below the fixed release 8.3.36, but distribution packages often
     │               carry backports
     │ ✗ vendor      php8.3-cli 8.3.6-0ubuntu0.24.04.12 < 8.3.6-0ubuntu0.24.04.13 (USN-8948-1, ubuntu
     │               24.04)
     │ → fix         sudo apt update && sudo apt install --only-upgrade 'php8.3*'
     │ →             Confirm: dpkg-query -W php8.3-cli → expect 8.3.6-0ubuntu0.24.04.13 or later.
     └
     ┌ interim mitigations — reduce exposure until the update; not a fix
     │ ✗ php.ini     session.upload_progress.enabled = 1          want 0 / Off · PHP default
     │ ✓ php.ini     memory_limit = -1                            want -1 · /etc/php/8.3/cli/php.ini:445
     │ ✓ php.ini     post_max_size = 8M                           want ≤ 32M · /etc/php/8.3/cli/php.ini:713
     └

   LIKELY VULNERABLE   /usr/local/bin/php @ container:worker-74
     sapi cli · version 7.4.33 (binary)
     ┌ PHP2Shell — end-of-life branch; only a source backport exists · confidence medium
     │ ✗ version     PHP 7.4 has no fixed upstream release (branch status: eol)
     │ · note        upstream published a source-only backport branch
     │               (https://github.com/php/php-src/tree/PHP-7.4-CVE-2026-109618-109619); builds
     │               from it keep the version string, so Bastion cannot tell them apart
     │ → fix         Rebuild on a patched base image: docker pull php:8.4-cli (needs 8.4.27 or
     │               later), then rebuild and redeploy. Running containers keep the old binary until
     │               they are replaced.
     └
     ┌ interim mitigations — reduce exposure until the update; not a fix
     │ ✗ php.ini     session.upload_progress.enabled = 1          want 0 / Off · PHP default
     │ ✗ php.ini     memory_limit = 128M                          want -1 · PHP default
     │ ✓ php.ini     post_max_size = 8M                           want ≤ 32M · PHP default
     └

   LIKELY VULNERABLE   /usr/local/bin/php-cgi @ container:worker-74
     sapi cgi · version 7.4.33 (binary)
     ┌ PHP2Shell — end-of-life branch; only a source backport exists · confidence medium
     │ ✗ version     PHP 7.4 has no fixed upstream release (branch status: eol)
     │ · note        upstream published a source-only backport branch
     │               (https://github.com/php/php-src/tree/PHP-7.4-CVE-2026-109618-109619); builds
     │               from it keep the version string, so Bastion cannot tell them apart
     │ → fix         Rebuild on a patched base image: docker pull php:8.4-cli (needs 8.4.27 or
     │               later), then rebuild and redeploy. Running containers keep the old binary until
     │               they are replaced.
     └
     ┌ interim mitigations — reduce exposure until the update; not a fix
     │ ✗ php.ini     session.upload_progress.enabled = 1          want 0 / Off · PHP default
     │ ✗ php.ini     memory_limit = 128M                          want -1 · PHP default
     │ ✓ php.ini     post_max_size = 8M                           want ≤ 32M · PHP default
     └

  SUMMARY  3 vulnerable  2 likely vulnerable  0 unknown  4 fixed
  9 instances across 5 targets in 14.626s · next: bastion trace · bastion report

web-01 — Ubuntu 24.04.5 LTS / 6.18.44-fc-v140 · containers: php:7.4-cli php:8.3-apache php:8.3.35-fpm php:8.4-cli · bastion v0.1.0-dev · 2026-10-22T09:03:48Z

The advisory

Two memory-safety bugs in the PHP engine, fixed upstream on 21 October 2026. Bastion's data is taken from php.net, the GitHub advisories and the vendors' own trackers.

How the bugs work
critical

PHP2Shell

Identifiers
CVE-2026-109618GHSA-w8hw-w9fx-j79wCVE-2026-109619GHSA-6wmf-4rv5-p3rp
Weakness
CVE-2026-109618 RCE via OOM corruption
CVE-2026-109619 RCE via stale global state (CWE-416, CWE-755, CWE-824, CWE-1325, CWE-1419)
Severity
CVSS 4.0 base score 9.2
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Exposure
Unauthenticated remote code execution as the web server account. Demonstrated against Apache mod_php before application code runs; PHP-FPM, FrankenPHP and LiteSpeed considered likely susceptible.
Affected
Every release below 8.5.12, 8.4.27, 8.3.36, 8.2.35. Branches 8.1, 8.0, 7.4 and older receive no upstream release.
Timeline
  • Advance notice of a security release.
  • PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 released with source backport branches for 7.4, 8.0 and 8.1; vendor updates follow the same day.
Upstream branches
BranchFixed inStatus
8.6≥ 8.6.0RC4pre-release
8.5≥ 8.5.12supported
8.4≥ 8.4.27supported
8.3≥ 8.3.36supported
8.2≥ 8.2.35supported
8.1no releasesource backport
8.0no releasesource backport
7.4no releasesource backport
Vendor backports in Bastion's data17
ReleasePackageFixed versionAdvisory
Ubuntu 26.10php8.58.5.9-0ubuntu2.1USN-8948-1
Ubuntu 26.04php8.58.5.4-0ubuntu1.5USN-8948-1
Ubuntu 24.04php8.38.3.6-0ubuntu0.24.04.13USN-8948-1
Ubuntu 22.04php8.18.1.2-1ubuntu2.28USN-8948-1
Ubuntu 20.04php7.4 Ubuntu Pro (ESM)7.4.3-4ubuntu2.29+esm5USN-8948-2
Ubuntu 18.04php7.2 Ubuntu Pro (ESM)7.2.24-0ubuntu0.18.04.17+esm14USN-8948-2
Ubuntu 16.04php7.0 Ubuntu Pro Legacy7.0.33-0ubuntu0.16.04.16+esm22USN-8948-2
Ubuntu 14.04php5 Ubuntu Pro Legacy5.5.9+dfsg-1ubuntu4.29+esm18USN-8948-2
Debian 13php8.48.4.27-1~deb13u1DSA-6574-1
Debian 12php8.28.2.35-1~deb12u1DLA-4848-1
RHEL 10php PHP 8.38.3.36-1.el10_2RHSA-2026:87070
RHEL 10php8.4 PHP 8.48.4.27-1.el10_2RHSA-2026:87071
RHEL 9php PHP 8.08.0.30-8.el9_8.1RHSA-2026:87151
RHEL 9php php:8.2 module8.2.35-1.module+el9.8.0+25111+a1450321RHSA-2026:87072
RHEL 9php php:8.3 module8.3.36-1.module+el9.8.0+25109+6886e21aRHSA-2026:87079
RHEL 8php php:7.4 module7.4.33-8.module+el8.10.0+25117+30337ccaRHSA-2026:87080
RHEL 8php php:8.2 module8.2.35-1.module+el8.10.0+25110+f67151d2RHSA-2026:87073

Coverage

Where scan looks for PHP, and what evidence it can use to tell a patched build from a vulnerable one in each environment.

scan reference
EnvironmentFound atEvidence beyond the version stringFix guidance
Debian, Ubuntu/usr/bin, /usr/sbin, Apache modulesVendor fix table (Ubuntu 14.04–26.10, Debian 12–13), changelog.Debian.gz, fix fingerprintapt
RHEL, AlmaLinux, Rocky/usr/bin, php-fpm, httpd modulesVendor fix table (RHEL 8, 9, 10 errata), rpm changelog, fix fingerprintdnf
Alpine/usr/bin/phpNNsecdb policy: stable branches carry no backportapk
Docker official images/usr/local/bin, /usr/local/sbinUpstream versionRebuild on a patched tag
Running containers, pods/proc/<pid>/root of each containerSame evidence as the base distributionPer base image
Container imagesdocker / podman save, never runSame evidence as the base distributionRebuild
BaoTa / aaPanel/www/server/php/*Upstream versionApp Store → Installed
cPanel EasyApache 4/opt/cpanel/ea-php*rpm changelogdnf ea-php*
CloudLinux alt-php/opt/alt/php*rpm changelogyum alt-php*
Plesk/opt/plesk/php/*Build date for the 7.4–8.1 rebuildsplesk installer
Remi, LiteSpeed, Homebrew, XAMPP, Bitnami, source buildsStandard prefixes, $PATHUpstream version, changelog where packagedPer environment
Workers running replaced code/proc/<pid>/exe, Apache memory mapsVersion and fingerprint of the old imageRestart the service

For builds that are not fixed, scan also reads the php.ini, scan-dir and PHP-FPM pool files that apply to them and reports which official interim mitigations are in place: session.upload_progress.enabled, memory_limit, post_max_size and, on 8.5, fatal_error_backtraces.

How a verdict is reached

The version string alone is not evidence for a distribution package. Bastion works down this list and stops at the first proof. If nothing proves the build either way, it says so.

Annotated source
  1. Read the binaryVersion and build date from the file itself; nothing is executed.
  2. Upstream releaseAt or above the branch's fixed release.
  3. Vendor fix tableExact fixed package versions from Ubuntu, Debian and Red Hat.
  4. Package changelogThe vendor recorded the CVE in the installed package.
  5. Fix fingerprintCode only the patch adds, or a vendor's dated rebuild.
  6. Verdictfixedvulnerablelikelyunknown

Ubuntu 24.04 reports PHP 8.3.6 both before and after its fix; only the package revision (…24.04.12 → …24.04.13) changes. Comparing against upstream 8.3.36 gets both builds wrong.

Intrusion trace

A patch does not remove a webshell, a cron job or an SSH key planted before it was applied. trace checks web roots, persistence points and logs, and builds a timeline.

trace reference
RuleAreaSeverityIndicator
file.php-in-imagefilemedium–highPHP code inside an image file
file.php-in-uploadsfilemediumPHP file in wp-content/uploads
file.double-extensionfilemediumPHP code in a double-extension file (x.php.jpg)
file.webshell-namefilelowFile name of a public webshell kit
file.hidden-phpfilelowHidden PHP file
config.auto-prependconfighighauto_prepend_file / auto_append_file in .user.ini, .htaccess or php.ini
config.htaccess-php-handlerconfighigh.htaccess makes non-PHP files execute as PHP
config.extension-from-tmpconfighighPHP extension loaded from a temp directory
persist.cronpersistencemedium–highCron entries that download-and-run, open shells, mine or run from /tmp
persist.systemdpersistencemedium–highsystemd units with the same patterns
persist.profilepersistencemedium–highShell start-up scripts and rc.local with the same patterns
persist.ld-preloadpersistencehighNon-empty /etc/ld.so.preload
persist.uid0persistencehighExtra account with UID 0
persist.web-ssh-keypersistencemediumSSH key for the web server account
persist.web-shell-loginpersistencelowWeb server account with a login shell
persist.tmp-elfpersistencemedium–highExecutable in /tmp, /var/tmp or /dev/shm
log.flagged-file-accessloghighHTTP requests to a file flagged by the file scan
log.post-upload-phploghighSuccessful POST to PHP in an upload directory
log.command-paramlogmediumShell commands in request parameters
log.code-in-requestlogmediumPHP code or stream wrappers in request URLs
log.php-cgi-arg-injectionlogmediumphp-cgi argument injection probes
log.worker-crashlogmediumPHP worker segfaults and heap corruption
log.early-oomlogmediumOut-of-memory during request start-up (the CVE-2026-109618 trigger)
log.hard-oomloglowPatched hard memory limit reached
log.multipart-limitsloglowRequest parsing limits hit
log.webshell-nameloglow–mediumRequests for webshell file names

Signatures are tested against about 33,000 legitimate PHP files from WordPress, Drupal, phpMyAdmin, Laravel, Symfony, phpseclib and PHPMailer with no high or medium matches, and CI repeats the check on every change.

Output and integration

Readable in a terminal, parseable in a pipeline, importable into a security dashboard.

FormatUseFlag
TerminalStatus colours, aligned tables, evidence and fix steps per build, timelinedefault
JSONVersioned documents bastion.scan/v1, bastion.trace/v1 for fleets and scripts--format json
SARIF 2.1.0GitHub code scanning and other security dashboards, with security-severity--format sarif
HTML reportOne self-contained file, works offline, both scan and trace, printable · samplebastion report
Exit codeMeaning
0No affected builds, no indicators
1A vulnerable or likely vulnerable build, or high-severity indicators
2Some builds could not be verified, or only medium indicators

Modules

Bastion ships as five modules. Everything stays read-only by default; anything that changes a system will be a separate, explicit command.

ModuleScopeStatus
SenseInventory and exposure: scan, check, report, mitigation audit, image scanningshipped
TraceIndicators of compromise and a timeline: traceshipped
ForgeReproducible patched packages for end-of-life PHP from the official backport branchesshipped
ShiftCompatibility checks and rehearsed upgrades to a supported branchshipped
GuardRuntime detection of exploitation attemptsshipped

Install

The installer verifies the SHA-256 checksum of the download and, when cosign is available, the Sigstore signature of the release.

Read install.sh
curl -fsSL https://larptard.github.io/bastion/install.sh | sh
sudo bastion scan
sudo bastion trace
sudo bastion report