php2shell: what it is, and how to protect your PHP site today
Two critical flaws in PHP itself let an attacker run code on your server without logging in. They're being exploited right now. Here's a plain-English checklist to check, patch and verify your sites, and what to do if you can't patch yet.
The short version. Update PHP to 8.2.35, 8.3.36, 8.4.27 or 8.5.12 (or your distribution's patched package), then restart every PHP worker. If you can't patch today, apply the temporary settings in step 4, and check your servers for signs of compromise.
01What happened
On October 21, 2026, PHP released fixes for two vulnerabilities in its request-handling core, nicknamed php2shell:
- CVE-2026-109618: when PHP runs out of memory while reading a request, it can leave internal data half-built, and the clean-up code then treats it as valid. Crafted multipart requests can trigger this even when they look like they respect your size limits.
- CVE-2026-109619: internal state from one request can survive after its memory is freed, so a later request handled by the same worker can reuse it.
Both can lead to remote code execution without authentication, with the privileges of your web server's PHP user. Exploitation attempts were seen before disclosure, and on October 26 both CVEs were added to the US government's catalog of known exploited vulnerabilities.
02Am I affected?
Almost certainly, if you run PHP on the web and haven't updated since October 21. Every way of serving PHP is affected: Apache with mod_php, PHP-FPM, php-cgi and LiteSpeed. Apache with mod_php is considered the highest-risk setup.
| Your branch | Vulnerable | Fixed in |
|---|---|---|
| PHP 8.5 | before 8.5.12 | 8.5.12 |
| PHP 8.4 | before 8.4.27 | 8.4.27 |
| PHP 8.3 | before 8.3.36 | 8.3.36 |
| PHP 8.2 | before 8.2.35 | 8.2.35 |
| PHP 8.1 and older | yes | No official release. Some distributions backport fixes; otherwise, upgrade. |
Check the version your website actually runs. It's often different from the one you get with php -v on the command line. Put this in a temporary file, open it in your browser, then delete the file immediately:
<?php echo PHP_VERSION, ' · ', PHP_SAPI;
Using a Linux distribution's packages? The version number may look old even when the fix has been backported. Check your distribution's security notice for these two CVEs instead of relying on the number alone.
03Patch, then restart
Updating the package is not enough on its own: running PHP processes keep the old, vulnerable code in memory until they restart. On a typical Debian/Ubuntu server the sequence looks like this (adjust the version and service names to yours):
# 1. Update PHP packages sudo apt update && sudo apt upgrade # 2. Restart PHP-FPM (if you use it) sudo systemctl restart php8.3-fpm # 3. Restart Apache (always, if you use mod_php) sudo systemctl restart apache2
Then repeat the version check from step 2. On shared hosting, you can't do this yourself: choose the newest PHP version in your control panel, and ask your host to confirm they've patched and restarted PHP.
04Can't patch yet? Temporary mitigations
These reduce your exposure while you schedule the update. They don't fix the flaws, so patching is still required.
- Turn off session upload progress:
session.upload_progress.enabled = 0. This closes the session-based attack path. It also covers a related flaw, CVE-2026-115560, which the October 21 releases don't fix. - Take memory exhaustion off the table: set
memory_limit = -1at the server level so scripts can't lower it. This is a trade-off: a runaway script can now use more memory, so treat it as temporary. - On PHP 8.5: also set
fatal_error_backtraces = 0. - Restart all PHP workers after changing any of these.
Where you set these matters. They must go in php.ini, your PHP-FPM pool file (php_admin_value), or your web server config. Setting them from application code with ini_set(), or in a .user.ini file, happens too late: PHP has already read the request by then.
session.upload_progress.enabled = 0 memory_limit = -1 ; PHP 8.5 only: fatal_error_backtraces = 0
Shrink what attackers can send
The memory bug is reached through large or complex form uploads. Keep request sizes realistic: post_max_size = 8M if your site doesn't take uploads (around 32M if it does), with upload_max_filesize below it. If your site never accepts file uploads, you can refuse multipart requests at the web server, before they ever reach PHP:
if ($content_type ~* "multipart/form-data") { return 415; }
<If "%{CONTENT_TYPE} =~ m#multipart/form-data#i"> Require all denied </If>
Test your contact forms and login pages afterwards. Only do this where nothing on the site needs uploads.
05Use the layer in front of your server
If your site sits behind an edge network or web application firewall run by your hosting or DNS provider, check whether it has published rules for php2shell and make sure they're switched on. Then make sure attackers can't simply go around it: your server should only accept web traffic from that provider, not from the whole internet. Edge rules are a stopgap, not a substitute for patching.
If you can't patch or mitigate quickly, the official advice is blunt: consider taking the site offline until you can.
06Check whether you were already hit
Attacks started before the patch existed, so patching now doesn't prove nobody got in earlier. Look for:
- PHP files changed recently that you didn't change, especially in upload folders:
find /var/www -type f -name '*.php' -newermt 2026-10-15 -ls
- Unexpected processes running as your web user (
www-data,apache,nginx) and outbound connections you can't explain. - New cron jobs, SSH keys or admin accounts on the server or inside your CMS.
- PHP worker crashes (segmentation faults, out-of-memory errors) in your logs since mid-October. Missing log entries don't prove you're safe.
If you find something, don't just delete it. Isolate the server, keep a copy of the evidence, rotate every password, key and database credential the site uses, and get help from an incident response professional.
Finally, remember PHP that hides inside other things: Docker images (rebuild them, since restarting a container keeps the old image), appliances, control panels and bundled apps. Check each vendor's updates.
07Where SmartKiller fits, honestly
We want to be clear about this, because the wrong expectation is dangerous: SmartKiller cannot block php2shell, and neither can any firewall written in PHP. SmartKiller runs as the first PHP code on each page, but this attack happens earlier, while PHP itself is still reading the request. By the time any PHP code runs, the vulnerable step has already happened.
What SmartKiller keeps doing is everything it was built for: stopping floods, scanners, bad bots and attack patterns at the application level. It catches the noisy reconnaissance that usually comes before an attack (bursts of 404s, known hacking tools) and gives you a record of who's probing your site in the Security Center. Use it alongside a patched PHP, not instead of one.
Your checklist: ① find every PHP install → ② patch and restart workers → ③ mitigate if you can't patch → ④ turn on edge rules and lock your origin → ⑤ check for compromise → ⑥ harden (see the next article).
