PHP2Shell: two critical PHP flaws, and what they mean for your Microsoft 365 tenant
Published 23 October 2026
What happened
Section titled “What happened”On 21 October 2026 the PHP project released fixes for two critical vulnerabilities, both rated CVSS 9.2:
| CVE | What goes wrong |
|---|---|
| CVE-2026-109618 | Memory corruption when a request hits the memory limit, leading to remote code execution |
| CVE-2026-109619 | Leftover state from an earlier request is reused by the next one, leading to remote code execution |
Details leaked a day before the release, proof-of-concept exploits are public, and researchers report exploitation attempts against internet-facing servers. CERT-EU considers exploitation likely. Treat this as urgent.
Who is affected
Section titled “Who is affected”Any PHP installation that serves web requests: PHP-FPM, Apache mod_php (highest risk, according to the PHP team), php-cgi, FrankenPHP and LiteSpeed. The attack works before any application code runs, so a well-written app does not protect you.
| PHP branch | Fixed in |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
| 8.1 and older | No official release. Upgrade, use a vendor backport, or build from the PHP team’s source patches (7.4, 8.0, 8.1) |
PHP is often inside products that don’t advertise it: CMS platforms such as WordPress, intranet portals, help desks, monitoring tools and appliances. The Dutch NCSC keeps a list of products known to embed PHP (see Sources).
What to do now
Section titled “What to do now”- Update PHP to a fixed version on every server, starting with internet-facing ones. Linux distributions received the patches in advance; install your vendor’s updated package.
- Azure App Service on Linux: Microsoft has rolled out the fixed built-in PHP images. The Latest channel gets fixes first, Standard soon after, and Extended last. For internet-facing apps, move to Latest or Standard (Configuration → Stack settings → Platform Release Channel). Confirm with
php --versionin the app’s SSH console. - Azure App Service on Windows: the built-in PHP runtimes are end-of-life and won’t be patched. Move the app to Linux, or bring your own supported PHP runtime.
- Containers and custom runtimes: rebuild your images with a fixed PHP version. Updating the host doesn’t patch PHP inside a container.
- Can’t patch today? Put a web application firewall in front and reduce exposure. Microsoft is adding a managed rule to Azure Front Door WAF (rollout expected to finish by 28 October 2026) and has published an interim rule for Application Gateway. CERT-EU also lists PHP settings that lower the risk, such as turning off
session.upload_progress.enabledand loweringpost_max_size. These measures help, but only the update fixes the flaws.
Why this matters for Microsoft 365
Section titled “Why this matters for Microsoft 365”PHP2Shell is not a Microsoft 365 vulnerability. Entra ID and Exchange Online are not affected. The risk is indirect, and it’s the part that is easy to miss.
Many PHP apps connect to your tenant: a website that sends mail through Microsoft Graph, a portal with “Sign in with Microsoft”, or a tool that reads users from Entra ID. These apps usually keep an Entra app client secret or certificate in a config file on the server. Once an attacker controls the server, they can read that secret and use the app’s permissions from anywhere, with no MFA or Conditional Access prompt in their way.
If you ran an affected PHP app that connects to Microsoft 365:
- Find the app registrations it uses. Search the server’s config for the app (client) ID, then open it in Entra admin center → App registrations.
- Rotate its credentials. Create a new client secret or certificate, deploy it to the patched server, then delete the old one. Do the same for any other passwords or API keys stored on the server.
- Review what it did. In Entra admin center → Sign-in logs → Service principal sign-ins, look for that app signing in from unexpected IP addresses since mid-October. Check the audit logs for changes it made.
- Trim its permissions. An app that only sends mail doesn’t need
Mail.ReadWritefor every mailbox orDirectory.ReadWrite.All. Remove what it doesn’t use, and limit mail access to specific mailboxes where possible.
Find PHP on your devices with Microsoft Defender. If your servers are onboarded to Microsoft Defender for Endpoint, run this query in Advanced hunting. It was checked by Griffin31’s security experts and lists every device with any sign of PHP in the last 30 days: installed software, running processes, PHP loaded inside a web server, and PHP files on disk. Compare the versions it finds with the fixed versions above.
// PHP in use: any device with ANY sign of PHP, last 30 dayslet lookback = 30d;let PhpExe = @"(?i)^php[\w.\-]*(\.exe)?$"; // php, php8.2, php-fpm8.3, php-cgi.exe, phpdbglet PhpLib = @"(?i)^(libphp[\w.\-]*\.so|php\d*(ts)?\.dll|php\d*apache[\w.\-]*\.dll)$"; // PHP inside Apache/IISlet Installed = DeviceTvmSoftwareInventory | where SoftwareName has "php" | project DeviceName, Signal = "Installed (inventory)", Detail = strcat(SoftwareName, " ", SoftwareVersion), Timestamp = datetime(null);let Running = DeviceProcessEvents | where Timestamp > ago(lookback) | where FileName matches regex PhpExe or InitiatingProcessFileName matches regex PhpExe | project DeviceName, Signal = "Running process", Detail = coalesce(FolderPath, FileName), Timestamp;let Loaded = DeviceImageLoadEvents | where Timestamp > ago(lookback) | where FileName matches regex PhpLib | project DeviceName, Signal = "Loaded in web server", Detail = strcat(InitiatingProcessFileName, " loads ", FileName), Timestamp;let OnDisk = DeviceFileEvents | where Timestamp > ago(lookback) | where FileName =~ "php.ini" or FileName matches regex PhpExe or FileName matches regex PhpLib | project DeviceName, Signal = "PHP files on disk", Detail = FolderPath, Timestamp;union Installed, Running, Loaded, OnDisk| summarize Signals = make_set(Signal), Details = make_set(Detail, 10), LastSeen = max(Timestamp) by DeviceName| extend SignalCount = array_length(Signals)| sort by SignalCount desc, LastSeen descHow Griffin31 helps
Section titled “How Griffin31 helps”Griffin31 checks your Microsoft 365 configuration, not your web servers, so it won’t report a PHP version. It covers the identity side of this incident. These recommendations are the ones to check:
- Review unfamiliar or unneeded App Registrations: find the apps your PHP servers sign in with, and remove the ones nobody uses.
- Application secrets approaching expiration: shows which apps hold a client secret, the credential an attacker can read from a breached server.
- Application certificate maximum lifetime (180 days): short-lived certificates limit how long a stolen credential keeps working.
- Email notifications for vulnerabilities: Microsoft Defender emails you when it finds a critical flaw like this one on your devices.
Free assessment
Section titled “Free assessment”Sources
Section titled “Sources”- CERT-EU Security Advisory 2026-018: Critical vulnerabilities in PHP
- PHP project security announcement
- PHP advisory GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
- PHP advisory GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- Microsoft: PHP critical security release on App Service for Linux
- Microsoft: PHP2Shell upgrade guidance and Azure WAF mitigations
- Microsoft: Azure WAF custom rules for PHP2Shell mitigation
- Canadian Centre for Cyber Security alert AL26-026
- NCSC-NL php2shell: products that embed PHP
