Do you want to update your Linux Server? Then click on the blog article below:
“If you run websites or applications on PHP, update today. On Wednesday, October 21, 2026, at 4:00 PM Dutch time (14:00 UTC), the PHP team will release an emergency update for two critical vulnerabilities known as PHP2Shell. The details were already leaked before the patch was ready, so attackers have a head start.
In this article, you will read what PHP2Shell is, how to temporarily shield your server until the patch is released, how to update safely afterward, and how to check if anyone has already gained access.
This article has been updated as of Wednesday morning, October 21. As soon as PHP publishes the official list of affected and patched versions, we will update it.
What is PHP2Shell?
PHP2Shell is the nickname for two vulnerabilities in PHP itself: CVE-2026-109618 and CVE-2026-109619. The PHP team has assigned both a score of 9.2 out of 10 (CVSS v4.0). According to CERT-EU and others, an attacker can use these to execute their own code on your server without logging in (remote code execution).
The name comes from an exploit tool that appeared in a leaked screenshot. On Tuesday afternoon, October 20, the first details appeared online, well before the planned disclosure. Security firm Sansec expects mass attacks within fifteen minutes of the patch release, as attackers will then be able to see exactly what has been repaired.
Where is the vulnerability?
PHP has not yet confirmed the technical cause. Independent researchers point to the way PHP processes multipart requests: the format a browser uses to send forms with files. According to them, it involves a memory error (use-after-free) in the session upload progress function, which tracks the progress of an upload. This function is enabled by default.
The most important thing to remember: the vulnerability is in PHP itself, not in WordPress, Laravel, or a plugin. PHP processes the request before your application executes even a single line of code. Therefore, a site without an upload form is not automatically safe, and updating WordPress will not resolve this.
Are you vulnerable?
Assume you are if you use PHP. The official list of affected versions will only follow with the release, but the signs are clear:
| PHP Version | Status | What to do |
|---|---|---|
| 8.2, 8.3, 8.4, 8.5 | Supported, will receive a patch | Temporary measures today, update after 16:00 |
| 8.1 and older | End-of-life, expected to receive NO patch | Keep temporary measures in place and upgrade as soon as possible |
| Unknown | Inventory | First determine which PHP version your site is actually serving (Step 1) |
watchTowr and CERT-EU take into account that versions from PHP 5 onwards may be affected. If you are still running on Ubuntu 20.04 with PHP from Ondřej Surý’s PPA, there will likely be no updated package for you: that PPA now only provides for Ubuntu 22.04 and 24.04.
Step 1: Map all your PHP instances
You can only patch what you know. Make a list of every server and every site running PHP, including staging environments, old campaign sites, management tools like phpMyAdmin, and containers. Note for each host which PHP versions are present, where PHP comes from (distribution packages, PPA, Docker image, hosting panel), and whether the host is accessible from the internet.
On a Debian or Ubuntu server, you can get quite far with:
# Welke PHP-versies zijn geïnstalleerd?
ls /etc/php
# Welke PHP-processen draaien er?
ps -eo pid,comm,args | grep -E '[p]hp-fpm|[a]pache2|[h]ttpd|[l]sphp'
# Welke sites geven verzoeken door aan PHP?
sudo nginx -T | grep -E 'server_name|fastcgi_pass'
# Luistert PHP ergens rechtstreeks op een poort?
sudo ss -tlnp
Note: php -v on the command line says nothing about the version serving your website. PHP-FPM, Apache mod_php, and separate FPM pools can each load a different version and a different php.ini. Also, never put a public phpinfo() page online to check this.
Step 2: Temporary measures until the patch
The only real solution is to update PHP. A PHP core developer stated this literally: patching is the only mitigation. The two measures below are not official PHP recommendations, but they significantly reduce the risk in the hours leading up to the update. Implement both.
A. Disable session upload progress
In your web server’s php.ini (not just the CLI one):
session.upload_progress.enabled = Off
If you use PHP-FPM, also lock the setting in every pool, so that a .user.ini in a web directory cannot silently turn it back on. On Debian/Ubuntu, the pools are located in /etc/php/<versie>/fpm/pool.d/:
php_admin_flag[session.upload_progress.enabled] = off
Then restart PHP-FPM for each version, for example sudo systemctl restart php8.3-fpm. The only thing you will notice: progress bars relying on this PHP function will no longer work.
Shared hosting? Place the line above in a .user.ini file next to your index.php (for PHP-FPM; it may take up to 5 minutes to become active). If PHP runs as an Apache module, use this in .htaccess: php_flag session.upload_progress.enabled off. If you get a 500 error afterward, remove the line and ask your host for help.
B. Block multipart requests on the web server
This is the strongest temporary measure: refuse any request with “multipart” in the Content-Type header before it reaches PHP. Do this for all HTTP methods (PHP 8.4 can also process multipart with PUT and PATCH) and in every server block or virtual host that forwards to PHP, including the default/catch-all. Attackers also send requests directly to your IP address.
Nginx — in the http context, for example in /etc/nginx/conf.d/block-multipart.conf:
map $http_content_type $block_multipart {
default 0;
"~*multipart" 1;
}
And at the top of every server block that forwards to PHP:
if ($block_multipart) {
return 403;
}
Check with sudo nginx -t and reload nginx.
Apache 2.4 — in the virtual host or at the top of .htaccess (above the WordPress rules):
<If "req('Content-Type') =~ /multipart/i">
Require all denied
</If>
Be sure to use req('Content-Type') here and not %{CONTENT_TYPE}: the latter looks at the response instead of the request, which makes the block ineffective.
LiteSpeed — at the top of .htaccess, outside the WordPress block, and then restart LiteSpeed:
RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart [NC]
RewriteRule ^ - [F]
Cloudflare (supplement, not a replacement) — a Custom Rule with action Block and the expression:
any(lower(http.request.headers["content-type"][*])[*] contains "multipart")
Cloudflare only protects traffic that passes through Cloudflare. Therefore, also implement the block on the server itself, or only allow traffic from Cloudflare IP ranges on ports 80 and 443.
Testing — from another machine, both via your domain and directly to your server IP:
curl -sS -o /dev/null -w '%{http_code}\n' -F test=1 https://jouwdomein.nl/
curl -sS -o /dev/null -w '%{http_code}\n' -X PUT -F test=1 https://jouwdomein.nl/index.php
curl -sS -o /dev/null -w '%{http_code}\n' -F test=1 --resolve jouwdomein.nl:443:<server-ip> https://jouwdomein.nl/
You want to see a 403 everywhere. Note: a WordPress security plugin can also return a 403, but it only runs after PHP has already processed the request. Therefore, check if the 403 page comes from your web server.
Side effects: as long as the block is in place, file uploads will not work. This includes the WordPress media library, forms with attachments, and Livewire or Filament uploads. Contact Form 7 also sends regular forms as multipart, so test your most important forms. Normal pages, logins, and JSON APIs will continue to work as usual.
C. Reduce your attack surface
- Take staging sites and PHP applications that you do not need today offline until they are patched.
- Restrict management tools like phpMyAdmin to your own IP address (
allow+deny all;in nginx). - Ensure your server is not accessible outside of your CDN or WAF.
What does NOT help
Anything that only runs after PHP has read the request is too late. Therefore, do not rely on:
- Updating WordPress or plugins. The vulnerability is in PHP, not in your CMS.
- Security plugins like Wordfence. Even the Wordfence firewall (via
auto_prepend_file) only runs once PHP has already processed the multipart request. file_uploads = Off. PHP still reads the multipart request; it only skips the files.disable_functions. Blocking functions likesystem()does not affect the processing error.- A small
post_max_size. No safe limit is known. - Only a WAF or CDN. This only helps if your server is not directly accessible via its IP address.
- Laravel maintenance mode or a 419 message. These only appear after PHP has already processed the request.
Step 3: Update as soon as the patch is available
From 16:00 onwards, keep an eye on php.net, the php.announce mailing list, and your distribution’s advisories. PHP may also release earlier if active attacks are observed. Update your internet-facing servers first, then the rest.
Before you begin, save a copy of your web server and PHP logs from October 20. You will need these later in Step 4, and a deployment or log rotation might erase them.
Debian and Ubuntu
sudo apt update
# Staat er een pakket op 'hold'? Dan doet de update stilletjes niets.
apt-mark showhold
# Welke versie staat er en welke is beschikbaar?
apt-cache policy php8.3-fpm
sudo apt upgrade
Update every installed PHP version, not just the version pointed to by the php command. Distributions like Debian and Ubuntu often apply security fixes to the existing version (backport). The version number may then look old even though the fix is included. Check the changelog for confirmation:
zcat /usr/share/doc/php8.3-fpm/changelog.Debian.gz | head -20
If you are far behind on updates, keep in mind that you will also be pulling in other changes. Click through your site briefly afterward.
Restarting, and really everything
- Restart PHP-FPM for every version, or Apache if PHP runs as a module.
- Restart long-running PHP processes: queue workers, Laravel Horizon, schedulers, Reverb, Octane. Otherwise, they will continue to use the old PHP.
- Search for processes still running on the old, now replaced PHP binary:
ls -l /proc/*/exe 2>/dev/null | grep -i 'php.*deleted'
Docker, hosting, and panels
- Docker: An updated host does not repair the PHP in your containers. Pull the patched base image, rebuild, and deploy. Check with
docker run --rm jouw-image php -v. - FrankenPHP: PHP is included in the binary itself, so you need a new FrankenPHP build.
- Shared or managed hosting, cPanel, Plesk, DirectAdmin: Ask your host to confirm which patched PHP build is serving your domain. Switching to a different PHP version in the panel does not guarantee that the build is patched.
- PHP 8.1 or older: Keep the temporary measures in place or keep the site offline until you have upgraded.
Step 4: Check if anyone has already gained access
Patching closes the door, but says nothing about who has already walked through it. Look back to Tuesday, October 20, around 17:00 Dutch time, shortly before the first public reports about the vulnerability.
- Search your web server and PHP logs for unusual multipart requests and PHP-FPM worker crashes.
- Search for new or modified files in web roots, upload folders, plugins, and mu-plugins:
find /var/www -type f -newermt '2026-10-20 15:00 UTC'(expect some noise from caches and logs). - Check
.user.inifiles and theauto_prepend_filesetting for changes. - Review cron jobs, systemd units, and Supervisor for new tasks, and check for new SSH keys.
- Watch for PHP processes starting a shell, Python, or curl/wget, and for unexpected outgoing connections from the PHP user.
- Check your applications for any new administrator accounts.
Find something? Isolate the server and preserve the logs. If the evidence points to a breach, rebuild the server and change every secret the PHP user had access to: .env files, database passwords, API keys, and app keys. A clean check is no guarantee, but it is a good sign.
After the patch: Cleaning up temporary measures
Is the patched PHP version demonstrably running on your site? Then remove the multipart block from your web server and Cloudflare. Afterward, test a file upload and the forms that were temporarily disabled. Session upload progress can remain disabled unless your application specifically uses that function.
Need help?
Customers with server management do not need to take any action: we have already implemented the temporary measures and will patch as soon as the update is available.
If you do not have a management contract, or if you are not sure if your server is properly shielded, please contact Servermeister via [email protected] or 020 895 0045. We will assist you today.
Block "serverbeheer-aanbod-content" not found