Reduce exposure until you update
Only a PHP update fully fixes PHP2Shell. The settings on this page make some attacks harder while you wait for it. The flaw stays in place.
Last reviewed . Rules of .
Update first. Install PHP 8.2.35, 8.3.36, 8.4.27 or 8.5.12, or a patched build from your Linux distribution or host. Then restart every PHP worker.
On PHP 8.1 or older, ask your vendor for a patched build, or move to a supported branch. See PHP 7.4, 8.0 and 8.1.
Where each measure comes from
Each measure carries a label for its source:
- php.net advisory the PHP project's security announcement of 21 October 2026.
- GHSA the two PHP security advisories on GitHub, one for each CVE. They have the technical detail.
- php2shell.com the researchers who found the flaws.
- Our advice our own recommendation, not something PHP or the researchers said.
Change one thing at a time, and test your site after each change. Restart every PHP worker after you change a PHP setting.
Measures, in order
Against CVE-2026-109618 (out-of-memory corruption)
- php.net advisory Set
memory_limit=-1in a way that apps cannot override, for examplephp_admin_valuein the FPM pool or the Apache config. Make sure no pool, directory or app setting puts a finite limit back. This removes the memory-limit failure that an attacker can control. A real allocation failure can still reach the flaw. - php.net advisory Put a memory cap outside PHP: a container or cgroup limit. Ideally it kills only the affected worker. Do not use
RLIMIT_ASorRLIMIT_DATAinstead: they can cause the failure that triggers the flaw.
GHSA A container or cgroup kill can also kill the PHP-FPM master and every worker, unless each worker has its own group. - php.net advisory Set a low
post_max_size:8Mif the app takes no file uploads,32Mif it does. Keepupload_max_filesizebelowpost_max_size. - php.net advisory Limit requests at the web server or proxy: decoded body size, number of input fields, number of multipart parts, number of headers and nesting depth. These limits must also cover requests without a usable
Content-Length.
GHSA Also limit the headers inside each multipart part, and the number of uploads. - GHSA Lower
max_input_nesting_level. Bound the number of input variables and multipart parts.
Our advice In PHP, the matching settings aremax_input_nesting_level,max_input_varsandmax_multipart_body_parts. Set them as low as your app allows. - GHSA If your app does not use
multipart/form-data(forms with file uploads), block those requests at the frontend, before they reach PHP.
Against CVE-2026-109619 (stale state from an earlier request)
- php.net advisory Set
session.upload_progress.enabled=0inphp.ini, the FPM pool or the server config. Do not useini_set()or.user.ini: they apply too late. Restart every worker. This blocks the confirmed session paths, not every variant. - php.net advisory On PHP 8.5, set
fatal_error_backtraces=0and restart every worker. This blocks only the confirmed fatal-backtrace path. - php.net advisory Remove invalid or deprecated settings that are applied per request and print a warning before PHP starts the request.
GHSA Examples:auto_detect_line_endings=1, legacyassert.*settings (8.3 and newer), legacy session settings (8.4 and newer), explicitmbstring.http_input,mbstring.http_output,mbstring.internal_encodingandiconv.*_encodingvalues, invalidmemory_limit,date.timezoneorzend.assertionsvalues, and paths thatopen_basedirrejects. On Apache mod_php,.htaccessandphp_value,php_flagandphp_admin_*lines apply before the request starts. On PHP-FPM this applies only when the web server sendsPHP_VALUEorPHP_ADMIN_VALUE. Preferphp.ini, FPM pool or server config that applies at startup.
Our advice A valid value prints no warning.php_admin_value[memory_limit] = -1from step 1 is fine. - php.net advisory Fix fatal errors and execution timeouts that an attacker can reach. This includes failures in callbacks, upload or import processing, and cleanup.
GHSA Treat aMaximum execution time exceedederror like any other fatal error. - GHSA If performance allows, set
pm.max_requests=1so each PHP-FPM worker handles one request. Recycling workers lowers the chance of an attack without removing it.
php2shell.com The researchers also suggest a lowerpm.max_requests.
For both
- php2shell.com Use SELinux or AppArmor to limit what a compromised PHP worker can do.
- Our advice Keep a WAF in front of the site and lock the origin. See WAF and CDN.
Configuration examples
These follow the measures above. Fit the values to your app; the file paths depend on your system. Restart every PHP worker after a change.
php.ini
; Interim only. Restore a finite memory_limit after you update.
memory_limit = -1
post_max_size = 8M ; 32M if the app takes uploads
upload_max_filesize = 6M ; keep it below post_max_size
session.upload_progress.enabled = 0
fatal_error_backtraces = 0 ; PHP 8.5 only
An app can raise memory_limit again at runtime. php_admin_value, as below, stops that.
PHP-FPM pool (for example www.conf)
; php_admin_* values cannot be changed by the app.
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 6M
php_admin_flag[session.upload_progress.enabled] = off
; PHP 8.5 only. On older PHP, delete the next line: FPM logs an error for it.
php_admin_flag[fatal_error_backtraces] = off
; Only if performance allows. Remove the ; to turn it on.
; pm.max_requests = 1
Apache with mod_php (virtual host or server config)
php_admin_value memory_limit -1
php_admin_value post_max_size 8M
php_admin_value upload_max_filesize 6M
php_admin_flag session.upload_progress.enabled off
# PHP 8.5 only. Apache does not allow a comment on the same line as a directive.
php_admin_flag fatal_error_backtraces off
Run apachectl configtest before you restart Apache. On mod_php these lines apply before each request starts. Check every value with care: an invalid value prints a warning at that early point, and that warning is one of the paths into CVE-2026-109619.
Block multipart requests if the app does not need them
These are our examples. Test them first, because they also block normal file uploads and some forms.
# nginx (server block)
if ($http_content_type ~* "multipart") { return 403; }
# Apache (mod_rewrite)
RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart [NC]
RewriteRule ^ - [F]
What does not help
- Hiding errors. Changing
error_reporting, using@, or turning offdisplay_errorsorlog_errorsgives no protection against CVE-2026-109619 (GHSA). PHP reads the stale state before it decides whether to show or log the warning.display_errors=0in production is still good hardening: it reduces an extra path for leaking data (php2shell.com). - Hiding the PHP version.
expose_php=0removes the version from theX-Powered-Byheader. The researchers call it optional hardening that does not fix PHP2Shell (php2shell.com). - App maintenance mode or a login page. On Apache mod_php, the demonstrated attack runs before any application code (php.net advisory). Our reading: a switch inside the app cannot stop an attack that runs before the app.
- Updating the app. The flaws are in PHP itself (php2shell.com). New WordPress, Drupal or Joomla versions and new plugins do not change PHP.
- Settings that apply too late.
ini_set()and.user.inido not turn off session upload progress in time (php.net advisory). - Process limits.
RLIMIT_ASandRLIMIT_DATAcan cause the allocation failure that triggers CVE-2026-109618 (php.net advisory).
WAF and CDN
A web application firewall (WAF) or CDN with PHP2Shell rules can stop some attack requests. The researchers say that partners prepared detections and temporary mitigations, and that a protective rule does not replace a PHP update (php2shell.com).
A WAF sees only the traffic that passes through it. A request sent straight to your origin server skips it.
Our advice Lock the origin: let your server accept web traffic only from your CDN or WAF, for example with a firewall allowlist of its addresses. Keep the WAF rules on until you update PHP, and after.
After you update
- Restart everything that runs PHP. Restart Apache, PHP-FPM and every long-running PHP worker (php2shell.com). Our advice Rebuild and redeploy container images from the updated base image. Check every PHP runtime on the host, including control panels.
- Check the PHP that serves the web. Our advice
php -von the command line can show a different PHP than the one your web server uses. Check the PHP-FPM pool or the admin screen of your app or host. Distribution packages often keep the old upstream number, so compare the package version (dpkg -lorrpm -q) with your vendor's fixed version. See Fixed versions. - Restore a finite
memory_limit. If you set-1as a stopgap, set a real limit again. Fit it to your request-size limits and the memory your app really uses. Keeppost_max_sizewell below that memory budget (php2shell.com). - Know the new hard memory limit. The fixed releases change how PHP handles out-of-memory. PHP now stops a script at the next point where it can stop cleanly when it passes
memory_limit. If memory use reaches a second, higher limit, the process ends at once (GHSA). The new settingmemory_hard_limit_percentsets that second limit. It is unset by default, which works like-1: two timesmemory_limitup to 1G, andmemory_limitplus 1G above 1G. Other values must be 100 or more. At the hard limit, PHP does not run shutdown functions (php-src source). - Keep session upload progress off if you do not use it. The GHSA says this is prudent, because attackers now look closely at this little-used feature.
- Keep input limits tight. Limit
max_input_nesting_levelto what your app needs (php2shell.com). - Remove stopgaps you no longer need. Our advice For example
pm.max_requests=1, if it slows the site. - If PHP crashes after the update. php-src issue GH-24488 reports
zend_mm_heap corruptedcrashes in 8.4.27 and 8.5.12 with SimpleXML. It is a crash, not a reported vulnerability. The fix is in the php-src source since 2026-10-22, but not yet in a release. Our advice Do not downgrade: an older release brings both flaws back. Watch php.net for a follow-up release.
Check your logs
Clean logs prove nothing. A failure can happen before PHP writes a message, and old logs may have left out deprecations and other messages. An audit covers only the pages and app states that ran during it. Logs add to a review of your configuration and your app; they do not replace it (GHSA).
What the PHP security team says to look for (GHSA)
Run the audit on an isolated copy of the site, with log_errors=On, a working error_log and error_reporting=E_ALL in the startup configuration. Read the Apache, PHP-FPM, reverse proxy and service logs for:
- warnings, deprecations and core errors that repeat before the target scripts run;
- warnings and other messages during extension or server cleanup;
- fatal, parse and uncaught errors;
Maximum execution time exceeded;- failures tied to routes, content types, files, callbacks or plugin options that an attacker can control.
Signs the researchers name (php2shell.com)
- unexpectedly large or malformed
PHPSESSIDcookies in responses; - unusual multipart requests followed by memory-limit errors or repeated HTTP 500 responses;
- PHP worker crashes or restarts with no clear cause.
These signs do not prove an attack. Their absence does not prove that no attack happened (php2shell.com).
Rotate secrets on exposed hosts
The flaws can leak PHP process memory. That memory can hold passwords, login tokens, API keys and certificates from other requests or from the server (php2shell.com).
Our advice If a host ran an affected PHP version on the public internet, rotate the secrets that PHP could read, after you update:
- database passwords and API keys in the app configuration;
- app signing keys and session secrets, then end all active sessions;
- TLS private keys, if the PHP process can read them;
- passwords of admin accounts that logged in during the exposure.
Sources
- php.net security advisory, 21 October 2026
- GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
- GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- php2shell.com, upgrade and mitigation guidance
- php-src 8.5.12 main.c (memory_hard_limit_percent)
- php-src 8.5.12 zend_alloc.c (hard limit rule)
- php-src issue GH-24488
Check your site
The checker shows which PHP version your site reports in public. It sends only ordinary GET requests and does not test these measures.