Detect-PHP2ShellVulnerability
What It Does
Finds every PHP installation on a Windows device and reports whether it is affected by PHP2Shell, two critical PHP vulnerabilities (CVE-2026-109618 and CVE-2026-109619). It can also update vulnerable installs to a patched PHP release.
PHP2Shell lets an attacker take control of a web server that runs an affected PHP version, without signing in. The website itself does not matter; the PHP version does. PHP fixed both vulnerabilities in versions 8.5.12, 8.4.27, 8.3.36, and 8.2.35. PHP 8.1 and older no longer receive fixes.
By default, the script only reports and changes nothing. Each PHP installation it finds is listed with its location, its owner, its version, and whether it is vulnerable.
When to Use It
- You need to know which devices have PHP installed and whether it is vulnerable to PHP2Shell.
- You need to find PHP that is bundled inside other products, not only PHP that was installed on purpose.
- You want vulnerable standalone PHP installs patched automatically from NinjaOne, Datto RMM, ConnectWise RMM, or another RMM platform.
What You Need
- Windows 10, Windows 11, or Windows Server 2016 or later, 64-bit
- The script running as SYSTEM or a local administrator through your RMM platform
- Internet access to download the search tool and, when updating, the patched PHP release from PHP's official download site
PHP stored on network drives or on drives not formatted as NTFS is not found.
How It Works
- Searches the device. Uses the Everything search tool to find every PHP program file on the device's NTFS drives in seconds. The tool is removed again afterwards, unless it was already installed.
- Identifies each installation. Reads the PHP version and build type, and works out who owns the installation:
- Standalone: PHP installed on its own, for example from PHP's website, winget, or Chocolatey.
- Stack: PHP that is part of a bundle such as XAMPP, WampServer, or Laragon.
- Vendor: PHP that ships inside another company's product.
- Checks each version. Marks each installation as patched, vulnerable, end-of-life, or unknown.
- Updates vulnerable installs (optional). With
FixLocalInstall, each vulnerable standalone install is updated to the latest patched release of its own PHP version line, for example from 8.3.30 to 8.3.36:- The patched release is downloaded from PHP's official site and checked for tampering before use.
- IIS, services, and PHP processes that use the installation are stopped, and the installation is backed up.
- PHP installed with winget for all users is updated through winget. If winget does not have the patched release yet, the script updates the files directly.
- Your PHP settings (
php.ini) and add-on extensions are kept. - The script confirms the updated PHP starts correctly. If it does not, the backup is restored.
- IIS and the stopped services are started again.
Stack and vendor installations are reported but never changed, since replacing PHP inside another product can break it. End-of-life versions are also left unchanged, since moving to a newer PHP version line needs application testing first.
You'll know it worked when the installation's status shows Patched and its version matches or is newer than the fixed release for its version line.
Updates Cause Brief Downtime
When FixLocalInstall updates a PHP installation that IIS uses, IIS restarts. Every website on that server is unavailable for a short time, not only the PHP sites. Services that use the installation also stop and start again.
Run FixLocalInstall on servers inside a maintenance window. Running the script without FixLocalInstall causes no downtime.
Parameters
| Parameter | Default | Type | Description |
|---|---|---|---|
FixLocalInstall | False | Switch | Updates every vulnerable standalone PHP installation to the latest patched release of its version line. Restarts IIS when IIS uses the installation. |
With no parameters, the script reports every PHP installation and changes nothing.
Results by Installation
| Installation | Status | Result with FixLocalInstall |
|---|---|---|
| PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12, or newer | Patched | No changes. |
| Standalone PHP 8.2 to 8.5, below the fixed release | Vulnerable | Updated to the latest patched release. |
| Stack or vendor PHP 8.2 to 8.5, below the fixed release | Vulnerable | No changes. Update it through the owning product. |
| PHP 8.1 or older | End-of-life | No changes. Upgrade to PHP 8.2 or later after testing the application. |
| Version could not be read | Unknown | No changes. Check the installation manually. |
If an update fails, the run is reported as failed in your RMM platform, and the result shows the reason for each installation that failed.
What Each Result Shows
| Field | Meaning |
|---|---|
| Path | Folder where PHP is installed. |
| Name | The owning product: PHP, the bundle name (such as XAMPP), or the vendor product. |
| Publisher | The company behind the owning product, when known. |
| IsNative | True for a standalone PHP installation, False when PHP belongs to another product. |
| InstallType | Standalone, Stack, or Vendor. |
| ManagedBy | Winget when winget installed PHP, otherwise None. |
| Version | The installed PHP version. After an update, the new version. |
| InIis | True when IIS uses this installation. |
| Running | True when PHP from this folder is running. |
| Status | Patched, Vulnerable, EndOfLife, or Unknown. |
| RequiredVersion | The first patched release for this version line. |
| Action | What the script did: nothing, updated, skipped with the reason, or failed with the reason. |
Usage Examples
Example 1: Report every PHP installation
.\Detect-PHP2ShellVulnerability.ps1
What happens:
- Every PHP installation on the device is listed with its status.
- Nothing is changed.
Example 2: Report only installations that need attention
.\Detect-PHP2ShellVulnerability.ps1 | Where-Object -FilterScript { $_.Status -ne 'Patched' }
What happens:
- Only vulnerable, end-of-life, and unknown installations are listed.
- Nothing is changed.
Example 3: Report and update vulnerable installations
.\Detect-PHP2ShellVulnerability.ps1 -FixLocalInstall
What happens:
- Every PHP installation is listed.
- Vulnerable standalone installations are updated, with a backup taken first.
- IIS restarts if it uses an updated installation.
Note: Run this inside a maintenance window on servers that host websites.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
| No PHP is reported, but PHP is installed | PHP is on a network drive or a drive that is not formatted as NTFS. | Check that drive manually. |
| The search tool did not finish loading | The device was too busy to build its file index within 60 seconds. | Run the script again. |
| An installation is skipped as Stack or Vendor | PHP belongs to XAMPP, WampServer, or another product. | Update the owning product, or take the system offline until its vendor releases a fix. |
| An installation is skipped as end-of-life | PHP 8.1 or older has no fix. | Upgrade to PHP 8.2 or later after testing the application. |
| The update fails to download | The device cannot reach PHP's download site. | Allow HTTPS to downloads.php.net and run again. |
| The update fails and the backup is restored | The updated PHP did not start correctly. | Check the error log for the reason. The original installation is back in place. |
| Winget still shows the old PHP version | PHP was installed with winget for one user only and was updated directly. | No action needed. PHP itself is patched. |
| Chocolatey still shows the old PHP version | The installation was updated directly. | Run choco upgrade for the PHP package when convenient. PHP itself is patched. |
Files and Logs
| File | Location |
|---|---|
| Script log | .\Detect-PHP2ShellVulnerability-log.txt |
| Error log | .\Detect-PHP2ShellVulnerability-error.txt |
| Backups of updated installations | C:\ProgramData\_Automation\Script\Detect-PHP2ShellVulnerability\Backup\ (kept for manual rollback) |
Learn More
- PHP security advisory
- NSA advisory: Critical Patches Recommended for PHP Vulnerabilities
- CVE-2026-109618
- CVE-2026-109619
Changelog
2026-10-22
- Initial version of the document.