<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>PHP2Shell on Daniel Zhang</title><link>https://zhangdapeng.dev/tags/php2shell/</link><description>Recent content in PHP2Shell on Daniel Zhang</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sun, 08 Nov 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://zhangdapeng.dev/tags/php2shell/index.xml" rel="self" type="application/rss+xml"/><item><title>PHP2Shell (CVE-2026-109618 / CVE-2026-109619): Nginx Temporary Mitigation and Verification Guide</title><link>https://zhangdapeng.dev/p/php2shell-nginx-mitigation-guide/</link><pubDate>Sat, 07 Nov 2026 18:01:00 +0800</pubDate><guid>https://zhangdapeng.dev/p/php2shell-nginx-mitigation-guide/</guid><description>&lt;img src="https://zhangdapeng.dev/p/php2shell-nginx-mitigation-guide/cover.png" alt="Featured image of post PHP2Shell (CVE-2026-109618 / CVE-2026-109619): Nginx Temporary Mitigation and Verification Guide" /&gt;&lt;h1 id="php2shell-cve-2026-109618--cve-2026-109619-nginx-temporary-mitigation-and-verification-guide"&gt;PHP2Shell (CVE-2026-109618 / CVE-2026-109619): Nginx Temporary Mitigation and Verification Guide
&lt;/h1&gt;&lt;h2 id="1-vulnerability-overview"&gt;1. Vulnerability Overview
&lt;/h2&gt;&lt;p&gt;In October 2026, the PHP project disclosed two critical remote code execution vulnerabilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CVE-2026-109618&lt;/li&gt;
&lt;li&gt;CVE-2026-109619&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Collectively known in the security community as &lt;strong&gt;PHP2Shell&lt;/strong&gt;, these vulnerabilities may allow unauthenticated attackers to execute arbitrary code on affected PHP servers.&lt;/p&gt;
&lt;p&gt;Unlike typical application-level vulnerabilities, PHP2Shell involves memory management issues within the PHP interpreter itself. Exploitation may occur before normal application code is executed.&lt;/p&gt;
&lt;p&gt;Therefore, having a WAF, SQL injection protection, or application-level security filters in place does not mean your server is protected against PHP2Shell.&lt;/p&gt;
&lt;p&gt;According to the PHP security advisories, potentially affected deployment environments include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PHP-FPM&lt;/li&gt;
&lt;li&gt;Apache with mod_php&lt;/li&gt;
&lt;li&gt;php-cgi&lt;/li&gt;
&lt;li&gt;FrankenPHP&lt;/li&gt;
&lt;li&gt;LiteSpeed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The PHP project has highlighted Apache mod_php deployments as particularly concerning. However, other PHP deployment models capable of processing web requests should also be reviewed.&lt;/p&gt;
&lt;h3 id="11-affected-versions-and-fixed-releases"&gt;1.1 Affected Versions and Fixed Releases
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;PHP Branch&lt;/th&gt;
					&lt;th&gt;Fixed Version&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;PHP 8.5&lt;/td&gt;
					&lt;td&gt;8.5.12&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;PHP 8.4&lt;/td&gt;
					&lt;td&gt;8.4.27&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;PHP 8.3&lt;/td&gt;
					&lt;td&gt;8.3.36&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;PHP 8.2&lt;/td&gt;
					&lt;td&gt;8.2.35&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;PHP 8.1 and earlier versions are no longer covered by regular upstream security maintenance.&lt;/p&gt;
&lt;p&gt;If you are running one of these older versions, prioritize migrating to a supported PHP release or verify whether your operating system vendor or commercial PHP provider offers an applicable security backport.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Updating the PHP core is the only fundamental way to address the underlying vulnerability.&lt;/p&gt;
&lt;p&gt;If an immediate PHP upgrade is not possible, you can introduce additional request restrictions at the Nginx layer as a temporary mitigation.&lt;/p&gt;
&lt;p&gt;However, Nginx cannot fully fix PHP2Shell or guarantee protection against every possible exploitation method.&lt;/p&gt;
&lt;h2 id="2-temporary-nginx-mitigation"&gt;2. Temporary Nginx Mitigation
&lt;/h2&gt;&lt;p&gt;If you cannot upgrade PHP immediately, you can introduce request restrictions at the Nginx layer based on your application&amp;rsquo;s requirements.&lt;/p&gt;
&lt;p&gt;One important distinction: blocking &lt;code&gt;multipart/form-data&lt;/code&gt; requests only restricts a particular category of HTTP traffic. It does not cover every potential PHP2Shell attack vector.&lt;/p&gt;
&lt;p&gt;The following sections describe three possible configurations.&lt;/p&gt;
&lt;h3 id="option-a-block-all-multipartform-data-requests"&gt;Option A: Block All multipart/form-data Requests
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Suitable for:&lt;/strong&gt; PHP websites that do not support file uploads.&lt;/p&gt;
&lt;p&gt;If your website does not provide image uploads, attachment uploads, file imports, or other multipart-based functionality, you can add the following rule to the corresponding Nginx &lt;code&gt;server&lt;/code&gt; block:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Temporarily block multipart requests
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$http_content_type&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;multipart/form-data&amp;#34;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Existing application configuration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri/&lt;/span&gt; &lt;span class="s"&gt;/index.php?&lt;/span&gt;&lt;span class="nv"&gt;$query_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Keep other PHP configuration unchanged
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Configuration details:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$http_content_type&lt;/code&gt;: Reads the client&amp;rsquo;s &lt;code&gt;Content-Type&lt;/code&gt; request header.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~*&lt;/code&gt;: Performs a case-insensitive regular expression match.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;return 403&lt;/code&gt;: Immediately returns an HTTP 403 Forbidden response when the condition matches.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach is simple and suitable for websites that do not need to process file uploads.&lt;/p&gt;
&lt;p&gt;However, it will also block legitimate upload requests if your application relies on them.&lt;/p&gt;
&lt;h3 id="option-b-configuration-for-aapanel-bt-panel"&gt;Option B: Configuration for aaPanel (BT Panel)
&lt;/h3&gt;&lt;p&gt;For servers managed through aaPanel (BT Panel), you can introduce request restrictions through a shared Nginx configuration file.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Locate the Nginx configuration file&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Open:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/www/server/nginx/conf/pathinfo.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Step 2: Add the blocking rule&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After confirming where this file is included and which configuration context it belongs to, add the following rule in an appropriate location:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Temporarily restrict multipart/form-data requests
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$http_content_type&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;multipart/form-data&amp;#34;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Keep the existing PATH_INFO configuration unchanged.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Test the configuration and reload Nginx&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, validate the Nginx configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx -t
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A successful result should look similar to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx: the configuration file syntax is ok
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx: configuration file test is successful
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then reload Nginx:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx -s reload
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If aaPanel uses a custom Nginx installation path, adjust the command according to your actual environment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important considerations:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Whether modifying &lt;code&gt;pathinfo.conf&lt;/code&gt; affects all PHP websites depends on where and how the file is included in individual site configurations.&lt;/p&gt;
&lt;p&gt;If the file is included only in specific locations or PHP configuration blocks, changing it once will not necessarily protect every website.&lt;/p&gt;
&lt;p&gt;You can inspect its references using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;grep -R &lt;span class="s2"&gt;&amp;#34;pathinfo.conf&amp;#34;&lt;/span&gt; /www/server/nginx/conf/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Review the results carefully before deciding whether this approach provides sufficient coverage.&lt;/p&gt;
&lt;h3 id="option-c-apply-restrictions-selectively-while-preserving-upload-endpoints"&gt;Option C: Apply Restrictions Selectively While Preserving Upload Endpoints
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Suitable for:&lt;/strong&gt; Websites that support legitimate file uploads but want to restrict multipart requests on other application endpoints.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user avatar endpoint needs to accept uploads.&lt;/li&gt;
&lt;li&gt;Regular API endpoints do not need multipart requests.&lt;/li&gt;
&lt;li&gt;Upload functionality is available through clearly defined URLs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this situation, avoid using overly broad URI regular expressions to whitelist entire categories of requests.&lt;/p&gt;
&lt;p&gt;A better approach is to configure upload endpoints separately and explicitly define which paths and HTTP methods are allowed.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Regular API endpoints do not accept multipart requests
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$http_content_type&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;multipart/form-data&amp;#34;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Existing API proxy or PHP processing configuration
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Dedicated user avatar upload endpoint
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/api/v1/user/avatar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Preserve the existing upload configuration.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Authentication, file size limits, and upload validation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# should also be configured here.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following directive uses an exact URI match:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/api/v1/user/avatar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This prevents unrelated paths from being treated as authorized upload endpoints.&lt;/p&gt;
&lt;p&gt;Additional precautions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Require authentication and authorization for upload endpoints.&lt;/li&gt;
&lt;li&gt;Restrict uploaded file sizes and permitted file types.&lt;/li&gt;
&lt;li&gt;Avoid configuring upload directories as locations where PHP files can be executed.&lt;/li&gt;
&lt;li&gt;Upgrade PHP as soon as possible rather than relying on upload endpoint whitelisting indefinitely.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Whitelisted upload endpoints may still be vulnerable to PHP2Shell. This configuration is only a traffic management strategy, not a security exemption from the vulnerability.&lt;/p&gt;
&lt;h2 id="3-verifying-the-nginx-mitigation"&gt;3. Verifying the Nginx Mitigation
&lt;/h2&gt;&lt;p&gt;After applying the configuration, perform both positive and negative tests to confirm that Nginx behaves as expected without disrupting normal application traffic.&lt;/p&gt;
&lt;p&gt;It is important to distinguish between two different objectives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Configuration verification:&lt;/strong&gt; Confirming that Nginx processes requests according to the configured rules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vulnerability verification:&lt;/strong&gt; Confirming that the underlying PHP installation has been patched.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following curl tests only verify Nginx request restrictions. They do not prove that PHP2Shell has been fixed or that the server is no longer vulnerable.&lt;/p&gt;
&lt;h3 id="31-verify-that-multipart-requests-are-blocked"&gt;3.1 Verify That multipart Requests Are Blocked
&lt;/h3&gt;&lt;p&gt;Use curl to send a POST request with a multipart content type:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -i -X POST https://your-api.com &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Content-Type: multipart/form-data; boundary=----TestBoundary&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Expected result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 403
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the server returns HTTP 403, the request has matched the corresponding Nginx blocking rule.&lt;/p&gt;
&lt;p&gt;Note that this test primarily verifies request-header matching behavior. It is not an actual vulnerability exploitation test and does not prove that every multipart request or alternative attack path has been blocked.&lt;/p&gt;
&lt;h3 id="32-verify-that-json-api-requests-still-work"&gt;3.2 Verify That JSON API Requests Still Work
&lt;/h3&gt;&lt;p&gt;Next, send a regular POST request using JSON:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -i -X POST https://your-api.com &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &lt;span class="s1"&gt;&amp;#39;{&amp;#34;test&amp;#34;: &amp;#34;data&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Expected result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 200
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The actual response code depends on your application.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;200&lt;/code&gt;: The request was processed successfully.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;400&lt;/code&gt;: The request parameters are invalid.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;401&lt;/code&gt;: Authentication is required.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;403&lt;/code&gt;: The request is not authorized.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;405&lt;/code&gt;: The endpoint does not support the POST method.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The objective is to confirm that normal application requests are not incorrectly blocked by the newly introduced multipart restriction.&lt;/p&gt;
&lt;h3 id="33-verify-that-get-requests-still-work"&gt;3.3 Verify That GET Requests Still Work
&lt;/h3&gt;&lt;p&gt;Use a GET request to check basic website accessibility:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -i https://yourdomain.com/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Expected result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 200
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A response of &lt;code&gt;301&lt;/code&gt; or &lt;code&gt;302&lt;/code&gt; may also be normal, depending on whether your website uses HTTPS redirection or other application-level redirects.&lt;/p&gt;
&lt;h3 id="34-check-whether-the-nginx-configuration-loaded-successfully"&gt;3.4 Check Whether the Nginx Configuration Loaded Successfully
&lt;/h3&gt;&lt;p&gt;In addition to HTTP request testing, inspect the Nginx configuration and running processes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Validate the configuration:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nginx -t
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Check Nginx processes:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps aux &lt;span class="p"&gt;|&lt;/span&gt; grep nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Inspect the error log:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tail -n &lt;span class="m"&gt;100&lt;/span&gt; /www/wwwlogs/nginx_error.log
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adjust the log path according to your actual Nginx installation and website configuration.&lt;/p&gt;
&lt;h3 id="35-a-common-mistake-when-testing-with-curl"&gt;3.5 A Common Mistake When Testing with curl
&lt;/h3&gt;&lt;p&gt;When testing POST requests, make sure you understand the difference between these two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-i&lt;/code&gt;: Includes HTTP response headers in the output.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-I&lt;/code&gt;: Sends a HEAD request and retrieves response headers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -i -X POST https://your-api.com &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &lt;span class="s1"&gt;&amp;#39;{&amp;#34;test&amp;#34;: &amp;#34;data&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is an appropriate way to test a POST request.&lt;/p&gt;
&lt;p&gt;Do not accidentally use uppercase &lt;code&gt;-I&lt;/code&gt; when you intend to test POST behavior, as it can cause the request method to differ from what you expect and produce misleading results.&lt;/p&gt;
&lt;h2 id="4-additional-temporary-security-hardening"&gt;4. Additional Temporary Security Hardening
&lt;/h2&gt;&lt;p&gt;Besides Nginx-level request restrictions, you should also strengthen security across the PHP runtime environment, operating system permissions, and network access controls.&lt;/p&gt;
&lt;h3 id="41-review-php-configuration"&gt;4.1 Review PHP Configuration
&lt;/h3&gt;&lt;p&gt;You can inspect relevant PHP settings using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;php -i &lt;span class="p"&gt;|&lt;/span&gt; grep -E &lt;span class="s2"&gt;&amp;#34;memory_limit|session.upload_progress.enabled&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If upload progress tracking is not required by your application, consider disabling it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;session.upload_progress.enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Off&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, it is important to understand that:&lt;/p&gt;
&lt;p&gt;Disabling upload progress tracking does not fix PHP2Shell and should not be considered a reliable vulnerability mitigation.&lt;/p&gt;
&lt;p&gt;Also, avoid setting:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;memory_limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This removes PHP&amp;rsquo;s memory usage limit and may allow abnormal requests to consume excessive server memory, increasing the risk of denial-of-service attacks.&lt;/p&gt;
&lt;h3 id="42-restrict-php-runtime-account-permissions"&gt;4.2 Restrict PHP Runtime Account Permissions
&lt;/h3&gt;&lt;p&gt;Review the permissions of your PHP-FPM runtime accounts.&lt;/p&gt;
&lt;p&gt;Recommended practices include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do not run PHP-FPM workers as root.&lt;/li&gt;
&lt;li&gt;Use separate runtime accounts for different websites whenever possible.&lt;/li&gt;
&lt;li&gt;Restrict PHP processes from accessing sensitive system directories.&lt;/li&gt;
&lt;li&gt;Avoid granting PHP runtime accounts unnecessary administrative privileges.&lt;/li&gt;
&lt;li&gt;Apply appropriate read and write permissions to upload directories.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if remote code execution occurs, proper privilege isolation can help reduce the potential impact of a compromise.&lt;/p&gt;
&lt;h3 id="43-investigate-suspicious-php-processes"&gt;4.3 Investigate Suspicious PHP Processes
&lt;/h3&gt;&lt;p&gt;For PHP servers exposed to the public internet, regularly inspect running processes and suspicious system activity.&lt;/p&gt;
&lt;p&gt;Pay particular attention to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PHP-FPM workers unexpectedly spawning shell processes.&lt;/li&gt;
&lt;li&gt;PHP processes launching unknown external programs.&lt;/li&gt;
&lt;li&gt;Unusual file download activity.&lt;/li&gt;
&lt;li&gt;Unexpected or unfamiliar scheduled tasks.&lt;/li&gt;
&lt;li&gt;Recently created suspicious PHP files.&lt;/li&gt;
&lt;li&gt;Unexpected modifications or new files within web directories.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If suspicious activity is discovered, do not simply restart PHP-FPM or delete logs.&lt;/p&gt;
&lt;p&gt;Preserve relevant logs and forensic evidence, then investigate whether the server has already been compromised.&lt;/p&gt;
&lt;h2 id="5-permanent-solution-upgrade-php"&gt;5. Permanent Solution: Upgrade PHP
&lt;/h2&gt;&lt;p&gt;Nginx-level restrictions are only temporary mitigation measures. They cannot replace the security patches provided by the PHP project.&lt;/p&gt;
&lt;p&gt;The corresponding fixed releases listed in this guide are:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PHP 8.5.12
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PHP 8.4.27
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PHP 8.3.36
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PHP 8.2.35
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Upgrade your PHP installation to the corresponding fixed release or a later security release within the same supported branch.&lt;/p&gt;
&lt;p&gt;Before upgrading, follow these recommended steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Back up your website code, databases, and PHP configuration.&lt;/li&gt;
&lt;li&gt;Identify the current PHP version and deployment model.&lt;/li&gt;
&lt;li&gt;Check compatibility between your PHP extensions and application code.&lt;/li&gt;
&lt;li&gt;Complete upgrade testing in a staging environment.&lt;/li&gt;
&lt;li&gt;Upgrade PHP in production.&lt;/li&gt;
&lt;li&gt;Restart or reload PHP-FPM as required.&lt;/li&gt;
&lt;li&gt;Verify the PHP version and service status.&lt;/li&gt;
&lt;li&gt;Test critical application functionality, including file uploads, authentication, payments, and other essential workflows.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Check the PHP CLI version:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;php -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Keep in mind that the PHP CLI version may differ from the PHP-FPM version used by your website.&lt;/p&gt;
&lt;p&gt;For aaPanel, Docker, or environments running multiple PHP versions, verify each PHP runtime instance that actually handles web requests.&lt;/p&gt;
&lt;p&gt;Otherwise, you may end up with an upgraded CLI installation while your website continues running an outdated and vulnerable PHP-FPM instance.&lt;/p&gt;
&lt;h2 id="6-conclusion"&gt;6. Conclusion
&lt;/h2&gt;&lt;p&gt;PHP2Shell is a security vulnerability involving the PHP runtime itself. It cannot be fully addressed through application-level filtering or a single Nginx configuration rule.&lt;/p&gt;
&lt;p&gt;If an immediate upgrade is not possible, consider the following temporary risk-reduction measures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Restrict unnecessary &lt;code&gt;multipart/form-data&lt;/code&gt; requests based on your application&amp;rsquo;s requirements.&lt;/li&gt;
&lt;li&gt;Apply independent access controls to upload endpoints that must remain available.&lt;/li&gt;
&lt;li&gt;Disable unnecessary PHP upload progress tracking, without treating this as a vulnerability fix.&lt;/li&gt;
&lt;li&gt;Restrict permissions assigned to PHP-FPM runtime accounts.&lt;/li&gt;
&lt;li&gt;Investigate suspicious processes, files, and system activity.&lt;/li&gt;
&lt;li&gt;Upgrade to a PHP release containing the official security fixes or a vendor-provided security backport.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The key takeaway: Nginx request filtering is an additional defensive measure, not a complete solution to PHP2Shell.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For PHP services directly exposed to the public internet, prioritize security upgrades.&lt;/p&gt;
&lt;p&gt;If a vulnerable system cannot be patched immediately and presents a significant risk, consider restricting or isolating its public internet access until the necessary security updates have been applied.&lt;/p&gt;
&lt;h2 id="7-references"&gt;7. References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;PHP Official Website: &lt;a class="link" href="https://www.php.net/" target="_blank" rel="noopener"
 &gt;https://www.php.net/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PHP Official Release Information: &lt;a class="link" href="https://www.php.net/releases/" target="_blank" rel="noopener"
 &gt;https://www.php.net/releases/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CISA: &lt;a class="link" href="https://www.cisa.gov/" target="_blank" rel="noopener"
 &gt;https://www.cisa.gov/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Canadian Centre for Cyber Security: &lt;a class="link" href="https://www.cyber.gc.ca/" target="_blank" rel="noopener"
 &gt;https://www.cyber.gc.ca/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Continue monitoring official PHP security advisories and security updates from your operating system vendor to ensure that relevant patches are applied promptly.&lt;/p&gt;</description></item></channel></rss>