# PHP2Shell.io — complete site text > PHP2Shell.io is an independent technical resource by miglen.com for CVE-2026-109618 and CVE-2026-109619: patch guidance, temporary compensating controls, monitoring, exposure checks, and credited research. Content review snapshot: 2026-10-21. This static snapshot is not a live advisory feed. Primary PHP and package-vendor advisories establish vulnerability scope and patch coverage. Patching the PHP runtime is the recommended remediation. PHP INI changes and edge filters are partial controls for specific paths, not complete fixes. An HTTP status, failed PoC, or absence of alerts cannot establish that a deployment is safe. The published CVSS v4.0 score of 9.2 describes vulnerability severity; it is not a personal deployment risk score. Configuration and lab examples were reviewed against documentation and source. They were not deployed or validated through exploit execution. Original findings remain attributed to their authors on the Read page. Canonical discovery: https://php2shell.io/llms.txt Generated from the public HTML pages. Site navigation, decorative graphics, and interface controls are omitted. Interactive examples are represented by their initial static content; visit the HTML page to change calculator inputs. ## Overview Source: https://php2shell.io/ CRITICAL · CVSS 9.2 PHP CORE / SECURITY BRIEF ### PHP2SHELL: PHP vulnerabilities, patches and mitigation Two vulnerabilities. A direct path to your runtime. Unauthenticated remote code execution in PHP core. Understand the exposure, patch your runtimes, and reduce risk where an immediate upgrade is impossible. [Patch — recommended](https://php2shell.io/patch.html) · [Compensating controls](https://php2shell.io/controls.html) CVE-2026-109618 · CVE-2026-109619 02 Critical vulnerabilities 9.2 / 10 CVSS v4.0 severity Pre-auth Remote attack paths Fix available 21 October 2026 #### Choose your next step. Start with a patched runtime. Then verify controls, improve visibility, and explore the evidence. ##### Patch the runtime. Install a fixed PHP build. Replace every worker and verify the runtime serving real requests. [Open the PHP patch guide](https://php2shell.io/patch.html) Fixed releases · Live verification ##### Reduce the exposure. When patching is impossible, apply scoped controls at the PHP runtime, web server, and edge. [Explore compensating controls](https://php2shell.io/controls.html) PHP · Web servers · Cloud WAFs ##### Watch the requests. Follow the worker. Connect web logs, PHP errors, process activity, and WAF events to investigate exploitation. [Improve detection and monitoring](https://php2shell.io/detection.html) Request logs · Process lineage ##### Know what a test proves. Use curl checks and reviewed labs. Understand which results establish exposure and which do not. [Review exposure checks and PoCs](https://php2shell.io/pocs.html) curl examples · Research labs ##### Read the research. Trace the guidance to PHP advisories, researchers, public repositories, and infrastructure docs. [Browse advisories and references](https://php2shell.io/references.html) Primary sources · Attribution ##### Understand the 9.2. Explore the published vulnerability metrics and calculate how a different base vector changes severity. [Explore the CVSS calculator](https://php2shell.io/#cvss-calculator) Published vector · What-if scenarios #### One name. Two failure modes. These flaws reach beyond session upload progress. A single configuration toggle cannot close every attack path. CVE-2026-109618 ##### Out-of-memory corruption A failed allocation can interrupt request initialization. Cleanup can then use incomplete internal data as though it were valid, opening a route to code execution. Confirmed pre-application exploitation on Apache mod_php. Other web runtimes still require an update. CVE-2026-109619 ##### Stale state between requests A worker can retain references to memory released by an earlier request. A subsequent request can encounter that stale state, leading to disclosure or code execution. Confirmed session paths affect mod_php and PHP-FPM. Prerequisites differ between runtimes. Sources: [PHP: OOM advisory](https://php2shell.io/references.html#php-advisory-oom) · [PHP: state-lifecycle advisory](https://php2shell.io/references.html#php-advisory-state) #### Anatomy of the vulnerability. Two failure modes in PHP’s request lifecycle, with exact excerpts from the upstream runtime changes. [`31c0ea7d` Avoid state corruption via bailout](https://github.com/php/php-src/commit/31c0ea7d7ff1d1fccb6492e52dab544011628065) php/php-src · PHP 8.5 CVE-2026-109618 ##### An interrupted operation. Invalid state. An allocation can fail while internal request data is only partly initialized. An immediate bailout skips the rest of that operation; shutdown can then encounter the unfinished state. 1. Request processing allocates memory 2. OOM interrupts an operation 3. Shutdown reaches invalid state [Zend/zend_alloc.c](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_alloc.c#L439-L441)PHP 8.5 · 31c0ea7d Selected removed and added lines; intervening diff lines omitted− removed+ added ``` - zend_bailout(); - exit(1); … intervening diff lines omitted … + EG(delayed_oom).state = ZEND_OOM_STATE_PENDING; + + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); ``` [Before the fix ↗](https://github.com/php/php-src/blob/dd830558ffb1ac8378e812b4db97626e6087de3f/Zend/zend_alloc.c#L418-L419)[Fixed source ↗](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_alloc.c#L439-L441) BeforeThe removed allocator path ends in zend_bailout(). That abrupt exit can leave intermediate state inconsistent. What changedThe added path records a pending OOM and signals the VM. The wider fix adds controlled unwinding and safe failure handling; it does not simply raise memory_limit. The advisory confirms pre-application exploitation on Apache mod_php. This excerpt illustrates the allocator redesign; the complete update also changes callers, parsers, and extensions. [Read the PHP advisory ↗](https://php2shell.io/references.html#php-advisory-oom)[Follow the OOM handler ↗](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_alloc.c#L3891-L3944) CVE-2026-109619 ##### One request ends. Its pointers survive. A worker can keep global references to an earlier request’s freed memory. A later request can use those references before initialization replaces them. The producer and consumer must run in the same worker. 1. Request A leaves a global reference 2. Request memory is released 3. Request B touches stale state [Zend/zend_execute_API.c](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_execute_API.c#L437-L445)PHP 8.5 · 31c0ea7d Added shutdown resets; selected contiguous lines− removed+ added ``` + ZVAL_UNDEF(&EG(last_fatal_error_backtrace)); + EG(record_errors) = false; + EG(num_errors) = 0; + EG(errors) = NULL; + EG(error_handling) = EH_NORMAL; + EG(exception) = NULL; ``` [Before the fix ↗](https://github.com/php/php-src/blob/dd830558ffb1ac8378e812b4db97626e6087de3f/Zend/zend_execute_API.c#L426-L431)[Fixed source ↗](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_execute_API.c#L437-L445) BeforeExecutor shutdown could leave error-related globals pointing at state that belonged to the completed request. What changedThese additions clear the backtrace, recorded errors, error mode, and exception pointer during shutdown, before early processing of another request can reuse them. This is one state family. The full patch also changes session and extension lifecycle handling. Disabling a single session feature only removes selected attack paths. [Read the PHP advisory ↗](https://php2shell.io/references.html#php-advisory-state)[See the early session reset ↗](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/ext/session/session.c#L3236-L3244) These are explanatory excerpts from one branch’s fix, with omitted lines identified. They are not a standalone patch. Install the complete [fixed release or vendor-confirmed backport](https://php2shell.io/patch.html); PHP INI settings only reduce selected attack paths. Verified against commit-pinned upstream files on 2026-10-21. [Fix & provenance](https://php2shell.io/references.html#php-upstream-memory-lifecycle-fix) · [Excerpt verification record](https://php2shell.io/data/anatomy.json). Zend Engine source excerpts © Zend Technologies Ltd.; [Zend Engine License 2.00](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/LICENSE). #### Why 9.2? Trace the score. Explore the Common Vulnerability Scoring System (CVSS) base metrics behind both PHP2Shell advisories. PHP advisory score · CVSS-B 9.2 / 10 CRITICAL Both CVE-2026-109618 and CVE-2026-109619 carry this same published score and vector. [OOM advisory ↗](https://php2shell.io/references.html#php-advisory-oom)[State-lifecycle advisory ↗](https://php2shell.io/references.html#php-advisory-state) ##### Remote. Pre-auth. High impact. `AV:N / PR:N / UI:N` describe a network attack requiring neither prior privileges nor another user’s participation. `VC:H / VI:H / VA:H` capture severe impact to the vulnerable system. `AC:H / AT:P` capture complexity and prerequisites: PHP’s advisories describe exploit reliability depending on the runtime and, for stale state, requests reaching the same worker. Those constraints do not remove the need to patch. `SC:N / SI:N / SA:N` are the advisories’ subsequent-system impact values, not a guarantee that your surrounding infrastructure is isolated. Published PHP2Shell CVSS v4.0 vector ``` CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N ``` **Explore the CVSS calculator11 base metrics** Change the inputs to see a hypothetical **CVSS v4.0 base score (CVSS-B)**. This does not change PHP’s published 9.2 rating. Threat and Environmental metrics are not included here; use the [full FIRST calculator](https://www.first.org/cvss/calculator/4.0) to model those factors. Hypothetical CVSS base metrics Exploitability Where the attack begins and what it requires. Attack vector`AV` Default selection: Network (N). Reachable across a network. Attack complexity`AC` Default selection: High (H). Security mechanisms must be overcome. Attack requirements`AT` Default selection: Present (P). Specific execution or deployment conditions matter. Privileges required`PR` Default selection: None (N). No prior privileges needed. User interaction`UI` Default selection: None (N). No other user participates. Vulnerable system impact Consequences for the system containing the vulnerability. Confidentiality`VC` Default selection: High (H). Total or seriously harmful disclosure. Integrity`VI` Default selection: High (H). Total or seriously harmful modification. Availability`VA` Default selection: High (H). Total or seriously harmful disruption. Subsequent system impact Consequences for a system beyond the vulnerable system. Confidentiality`SC` Default selection: None (N). No subsequent confidentiality loss scored. Integrity`SI` Default selection: None (N). No subsequent integrity loss scored. Availability`SA` Default selection: None (N). No subsequent availability loss scored. Your selected base metrics 9.2 Critical Matches the published PHP advisory vector. Selected hypothetical CVSS v4.0 vector ``` CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N ``` [Open this vector in FIRST’s calculator ↗](https://www.first.org/cvss/calculator/4.0#CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N) JavaScript is needed for interactive scoring. The published score, vector, and metric explanations remain available above. A severity score is not a test for exposure or compromise. A lower hypothetical score does not make an unpatched PHP deployment safe. [Patch and verify the running runtime.](https://php2shell.io/patch.html) Scoring uses FIRST’s CVSS v4.0 implementation, served locally. [Specification](https://php2shell.io/references.html#cvss-v4-spec) · [Calculator & source](https://php2shell.io/references.html#cvss-v4-calculator) · [BSD-2-Clause license](https://php2shell.io/assets/vendor/cvss/LICENSE). CVSS is owned by FIRST.Org, Inc. and used by permission. #### Check every PHP deployment. [How to verify →](https://php2shell.io/patch.html#verify) | PHP branch | First fixed release | Action | | --- | --- | --- | | 8.5 | **8.5.12** | Update to this release or newer | | 8.4 | **8.4.27** | Update to this release or newer | | 8.3 | **8.3.36** | Update to this release or newer | | 8.2 | **8.2.35** | Update; plan a supported-branch migration | | 8.1 and older | End of life | Move to a supported branch or verify a complete vendor backport | Vendor packages may carry a backport under an older version number. Confirm coverage for both CVEs in the package advisory. [PHP release advisory ↗](https://php2shell.io/references.html#php-security-release) #### Before you change anything. **Does updating WordPress or another application fix this?** The affected component is PHP itself. Update the PHP runtime beneath the application, including bundled runtimes and container images, then replace running workers. **Is disabling session upload progress enough?** It reduces confirmed session-related exposure. It does not repair the broader memory and lifecycle defects, and is not complete protection against either vulnerability class. **Can a WAF replace the patch?** A WAF can block selected request patterns. Other paths, parser differences, inspection limits, and direct access to the origin can leave exposure. Keep the runtime upgrade as the remediation goal. **What about PHP 8.1 and older?** These versions remain end of life. Some vendors provide backported fixes, and PHP published exceptional minimal source backports for 7.4, 8.0 and 8.1. That does not restore ongoing support. Plan a supported-branch upgrade. --- ## Patch Source: https://php2shell.io/patch.html RESPONSE / 01 · RECOMMENDED ### Patch the PHP runtime. Install a fixed release or a vendor-confirmed complete backport. Replace running workers, then verify the PHP instance that actually serves your application. #### 01 / Choose a fixed release | PHP branch | First fixed release | Action | | --- | --- | --- | | 8.5 | **8.5.12** | Update to this release or newer | | 8.4 | **8.4.27** | Update to this release or newer | | 8.3 | **8.3.36** | Update to this release or newer | | 8.2 | **8.2.35** | Update; plan a supported-branch migration | | 8.1 and older | End of life | Move to a supported branch or verify a complete vendor backport | These are the first fixed upstream releases for both CVEs. Use a current security release on a supported branch. Distribution version strings can differ when fixes are backported. Sources: [PHP release advisory](https://php2shell.io/references.html#php-security-release) · [Downloads](https://php2shell.io/references.html#php-downloads) #### 02 / Inventory the running application Include public and internal PHP services, virtual hosts, FPM pools, containers, hosting panels, appliances, long-lived workers, and bundled PHP binaries. A host can run several independent versions. shell / CLI inventory — read only ``` php -v php --ini php -r 'printf("PHP=%s SAPI=%s\n", PHP_VERSION, PHP_SAPI);' ``` **CLI ≠ web runtime** The commands above describe the CLI binary. They do not confirm the version loaded by Apache, PHP-FPM, LiteSpeed, or an application container. Map each web entry point to its serving process and installed package or container image. Check the vendor advisory for *both* CVE identifiers before choosing a candidate package. #### 03 / Install and replace workers Use the package source or image pipeline you already trust. The examples below assume the named packages are already installed and the repository offers a fixed build. Adjust the branch and service names to your deployment. Debian / Ubuntu · example PHP 8.4 FPM installation ``` # Check the candidate and its vendor security advisory first. sudo apt-get update apt-cache policy php8.4-fpm php8.4-cli # Proceed once the candidate includes fixes for BOTH CVEs. sudo apt-get install --only-upgrade php8.4-fpm php8.4-cli sudo systemctl restart php8.4-fpm ``` RPM-based distribution · existing PHP packages ``` # Review available packages and the vendor advisory first. sudo dnf --refresh check-update 'php*' # Proceed once the available build fixes BOTH CVEs. sudo dnf upgrade 'php*' sudo systemctl restart php-fpm ``` Install updates for every deployed PHP package and SAPI, not just the CLI. For Apache `mod_php`, update its PHP module package and restart Apache. A reverse proxy update alone does not update PHP-FPM. ##### Containers and embedded runtimes Rebuild with a verified fixed PHP base or bundle, redeploy every replica, and drain old workers. Confirm the running image digest, not only the image tag. Apply the same process to FrankenPHP and LiteSpeed packages. Fixed package / image · Replace workers · Verify live runtime #### 04 / Verify through the web SAPI Use an existing private diagnostic or a temporary access-restricted endpoint to inspect the live runtime. Keep the endpoint unavailable to the public and remove it after verification. PHP / temporary private runtime diagnostic ``` PHP_VERSION, 'sapi' => PHP_SAPI, 'upload_progress' => ini_get('session.upload_progress.enabled'), 'memory_limit' => ini_get('memory_limit'), ], JSON_PRETTY_PRINT), "\n"; ``` - Compare the web runtime with the fixed release or the vendor’s backport advisory. - Verify every pool, virtual host, and replica; one successful response does not cover a whole fleet. - Confirm old workers have exited, then test normal application and upload flows. - Record the package build or image digest and the advisory that confirms both fixes. **A blocked request is not patch verification** A 403, an absent exploit indicator, or a failed PoC does not prove the runtime has been fixed. Use package provenance and live runtime checks. #### 05 / End-of-life deployments PHP 8.1 and earlier are outside normal upstream security support. Prefer migration to a supported branch. If a vendor supplies an LTS build, require explicit coverage for both CVEs. PHP has published exceptional minimal source backports for 7.4, 8.0 and 8.1. They require a controlled build and validation process, and do not renew support. A community patch for upload-progress counters alone is not equivalent to the full upstream remediation. Sources: [PHP source backports](https://php2shell.io/references.html#php-backport-74) · [Support policy](https://php2shell.io/references.html#php-supported-versions) [Patching is impossible right now](https://php2shell.io/controls.html) --- ## Control Source: https://php2shell.io/controls.html RESPONSE / 02 · TEMPORARY & PARTIAL ### Compensating controls. If patching is impossible, reduce exposure while you prepare the runtime upgrade. Each example below addresses a limited attack surface; none is a substitute for the patch. #### Read the scope first **Patch remains the recommended action** The two flaws have multiple paths. A multipart block or upload-progress toggle does not cover all of them. [Go to the patch guide →](https://php2shell.io/patch.html) The frontend examples deliberately reject **all multipart/form-data requests** in scope, across HTTP methods. They can break legitimate forms and uploads. Use them only where that traffic can be stopped; route necessary uploads to a patched or isolated runtime. These are configuration templates, not vendor-certified PHP2Shell signatures. Adapt them in staging, test syntax and application behavior, and verify enforcement. Keep direct origin access behind the same control. The snippets have not been deployed or exploit-tested here. #### PHP configuration PARTIAL COVERAGE · Confirmed session and fatal-backtrace paths Why it helps: disabling upload progress removes confirmed session-related consumers of stale state; disabling PHP 8.5 fatal backtraces removes one confirmed producer. These settings do not repair memory lifetime handling or cover all variants. They are partial controls for CVE-2026-109619, not a fix for CVE-2026-109618. PHP configuration / ini / partial control ``` ; In the web runtime's php.ini, before request parsing. ; Partial control only. Restart every PHP worker. session.upload_progress.enabled = Off ; PHP 8.5 only: confirmed fatal-backtrace path. fatal_error_backtraces = Off ``` Alternative / PHP-FPM pool configuration ``` ; In each relevant PHP-FPM pool configuration. php_admin_flag[session.upload_progress.enabled] = off ; PHP 8.5 pools only. php_admin_flag[fatal_error_backtraces] = off ``` - Disabling upload progress blocks confirmed session consumers of CVE-2026-109619, not every stale-state variant. - Use php.ini, an FPM pool or server-level settings. ini_set() and FPM .user.ini are too late for these startup paths. - Restart every worker; merely editing files leaves existing workers and stale state in service. - Remove invalid/deprecated per-request INI settings that cause initialization diagnostics and fix attacker-triggered fatal errors/timeouts. **Verify:** Use a private diagnostic through the actual web runtime to confirm PHP_VERSION, PHP_SAPI and the effective INI values; remove it afterward. Do not expose phpinfo(). Sources: [Configuration reference](https://php2shell.io/references.html#docs-php-fpm) Sources: [Scope of the state-lifecycle mitigation](https://php2shell.io/references.html#php-advisory-state) #### PHP OOM control PARTIAL COVERAGE · Temporary administrative setting with an availability boundary Why it helps: an enforced unlimited PHP memory limit removes a controllable per-request failure trigger. Real allocation failures can still reach vulnerable cleanup. The underlying bug remains until PHP is patched. **Availability tradeoff — read before applying** Setting `memory_limit = -1` removes PHP’s memory cap. Establish a container/cgroup boundary first. An underlying allocation failure can still reach the vulnerable path; this is not complete remediation. PHP OOM control / ini / partial control ``` ; FPM pool example: only while an upgrade is impossible. ; Establish a container/cgroup memory boundary first. php_admin_value[memory_limit] = -1 php_admin_value[post_max_size] = 8M php_admin_value[upload_max_filesize] = 2M ``` - The upstream advisory proposes an enforced unlimited PHP memory_limit to remove the attacker-controlled per-request OOM trigger. Underlying allocation failure can still reach the flaw. - This removes PHP's memory guardrail. Use a container/cgroup boundary and an operational policy appropriate to worker termination; do not replace it with RLIMIT_AS or RLIMIT_DATA. - The size values are a no-upload example; review application needs. Upstream suggests 32M post_max_size for uploads and upload_max_filesize below it. - Bound decoded request bodies and parser work at the frontend, including requests without a usable Content-Length. Body size alone does not bound multipart metadata expansion. - Restart workers and check no pool, directory or application restores a finite PHP memory limit. Sources: [Configuration reference](https://php2shell.io/references.html#php-advisory-oom) #### Apache HTTP Server PARTIAL COVERAGE · Block multipart before PHP Apache HTTP Server / apache / partial control ``` # Inside each affected VirtualHost; requires mod_rewrite. # Stops multipart forms and uploads for this virtual host. RewriteEngine On RewriteCond %{HTTP:Content-Type} multipart/form-data [NC] RewriteRule ^ - [F,L] # Optional body-size ceiling; example: 8 MiB. LimitRequestBody 8388608 ``` - Keep the rule ahead of proxy/front-controller rewrite rules. Use server/VirtualHost configuration rather than depending on application code. - A body ceiling reduces risk but does not bound PHP's internal memory expansion. Header filtering leaves non-multipart paths unaddressed. - For mod_php, restart all Apache workers after PHP upgrades or runtime INI changes. For proxy_fcgi, restart the FPM pool as well. **Verify:** apachectl configtest; after a successful result, reload using your service manager. Service and binary names vary by distribution. Sources: [Configuration reference](https://php2shell.io/references.html#docs-apache) #### nginx PARTIAL COVERAGE · Reject multipart at the frontend nginx / nginx / partial control ``` # In the http {} context. map $http_content_type $php2shell_multipart { default 0; ~*multipart/form-data 1; } ``` nginx / add to each existing server {} block ``` # Add to each existing server {} serving unpatched PHP. # This intentionally disables multipart forms and uploads. if ($php2shell_multipart) { return 403; } client_max_body_size 8m; ``` - The map belongs in http {}; the active if/return and body limit belong in the existing server {} before PHP/proxy handling. - Add both nginx blocks in their indicated contexts; a map alone does not block requests. - Test upload and API paths, including larger bodies and requests without Content-Length. A request-body size cap is not a cap on PHP memory use. - Updating nginx does not update PHP-FPM; replace PHP workers separately. **Verify:** nginx -t; after a successful result, reload nginx using your service manager. Restart PHP workers when changing their binary or INI. Sources: [Configuration reference](https://php2shell.io/references.html#docs-nginx) #### AWS WAF PARTIAL COVERAGE · CloudFormation rule for an existing web ACL AWS WAF / yaml / partial control ``` # Add this item to AWS::WAFv2::WebACL Properties.Rules. # Choose a free priority before any terminating Allow rule. - Name: BlockMultipartToUnpatchedPHP Priority: 10 Action: Block: {} Statement: ByteMatchStatement: SearchString: multipart/form-data PositionalConstraint: CONTAINS FieldToMatch: Headers: MatchPattern: IncludedHeaders: - content-type MatchScope: VALUE OversizeHandling: MATCH TextTransformations: - Priority: 0 Type: LOWERCASE VisibilityConfig: CloudWatchMetricsEnabled: true MetricName: BlockMultipartToUnpatchedPHP SampledRequestsEnabled: true ``` - This is a CloudFormation fragment, not a complete stack or raw WAF API payload. Associate the ACL with every relevant CloudFront/ALB/API entry point. - Headers inspection is capped at 8 KiB or 200 headers. MATCH blocks requests when that inspection limit is exceeded, which can reject otherwise legitimate traffic. - Review rule priority and any Allow/Skip behavior. A Count action can measure impact but does not block traffic. - It blocks the media type, not a full exploit signature, and does not patch any runtime. **Verify:** Validate the full CloudFormation template, review the change set, then confirm sampled requests and WAF logs show a benign multipart probe being blocked. Verify direct origin access is restricted. Sources: [Configuration reference](https://php2shell.io/references.html#docs-aws-waf) #### lighttpd PARTIAL COVERAGE · Header condition with mod_access lighttpd / lighttpd / partial control ``` # Add at server scope or inside the affected host condition. # Ensure mod_access is already loaded in server.modules. $REQUEST_HEADER["Content-Type"] =~ "(?i)multipart/form-data" { url.access-allow = ( ) url.access-deny = ( "" ) } ``` - The empty deny suffix matches every URL when the header condition is true. This stops all multipart forms/uploads in scope. - Clearing url.access-allow in the matching condition prevents an inherited allow-suffix list from taking precedence over access-deny; review later matching conditions for overrides. - The condition and allow/deny precedence were checked against current lighttpd source; validate compatibility with the installed release. - Patch/restart the PHP FastCGI backend separately; changing lighttpd does not change the PHP runtime. **Verify:** lighttpd -tt -f /etc/lighttpd/lighttpd.conf; after a successful result, reload using your service manager. Check the real configuration path for your distribution. Sources: [Configuration reference](https://php2shell.io/references.html#docs-lighttpd) #### GCP Cloud Armor PARTIAL COVERAGE · Custom deny rule using request headers GCP Cloud Armor / cel / partial control ``` has(request.headers['content-type']) && request.headers['content-type'].lower().contains('multipart/form-data') ``` - Use this as an advanced match expression with action deny(403) on the backend security policy protecting the application. - Choose an unused priority before broad allow rules, attach the policy to the actual backend service, and restrict access that bypasses the load balancer. - Cloud Armor joins repeated header values with commas, so the substring check also sees that representation. - Preview mode reports matches only; turn preview off to enforce. This header rule avoids request-body inspection limits but only reduces multipart exposure. **Verify:** Preview against legitimate requests, inspect security-policy logs, then enforce and verify that a benign multipart request is denied. Preview alone is not protection. Sources: [Configuration reference](https://php2shell.io/references.html#docs-cloud-armor) #### Cloudflare PARTIAL COVERAGE · Custom multipart block Cloudflare / ruleset / partial control ``` http.request.headers.truncated or any(lower(http.request.headers["content-type"][*])[*] contains "multipart/form-data") ``` - Use a WAF custom rule with action Block. This intentionally rejects all multipart traffic and requests whose headers were truncated for inspection. - Keep the DNS record proxied and restrict direct origin traffic. Review earlier Skip rules and rule ordering. - Do not block the PHPSESSID cookie: that breaks normal sessions and is not a reliable exploit indicator. - Managed protections and narrower form-field rules are additional controls; do not describe any as a complete fix for both CVEs. **Verify:** Validate the expression in the dashboard and check Security Events with a harmless multipart request. Confirm legitimate business flows after enforcement. Sources: [Configuration reference](https://php2shell.io/references.html#docs-cloudflare-arrays) #### Check the control without an exploit Send an ordinary multipart request to your local test application. For the blanket block examples above, expect the configured rejection (usually HTTP 403) and a matching edge or web-server log entry. shell / benign local multipart probe ``` curl --include --max-time 10 \ --form 'probe=php2shell-rule-check' \ --form 'file=@/dev/null;filename=probe.txt' \ http://127.0.0.1:8080/upload.php ``` This checks request filtering only. It does not exercise the vulnerabilities, verify a PHP patch, or validate a rule that only matches a particular progress field. For AWS WAF, Cloud Armor, or Cloudflare, replace the localhost URL with your owned HTTPS test hostname that routes through that edge; localhost does not test cloud enforcement. Also test regular forms, APIs, header variants, and upload paths used by your application. [Return to the complete fix](https://php2shell.io/patch.html) --- ## Detect Source: https://php2shell.io/detection.html VISIBILITY / REQUEST → WORKER → HOST ### Detection & monitoring. Collect the context that connects unusual requests to PHP errors, worker behavior, and host changes. Use it to investigate attempted exploitation and possible compromise. #### Look for a sequence, not a single string. **Signals are leads, not proof** Some paths disclose memory or execute inside PHP without a shell process. A quiet dashboard does not establish safety. Keep [patching](https://php2shell.io/patch.html) as the recommended action. Start with web request metadata, runtime errors, and process-creation events. Join them by time, host, backend, and worker where possible. Establish a baseline and verify that logging reaches your collector before turning a query into an alert. Request anomaly · PHP / worker event · Host investigation These configurations and queries are starting templates. Match their fields, paths, services, and thresholds to your deployment. They have not been deployed or validated against live exploitation. #### Request metadata at the web server Start with timestamps, request volume, response status, duration, backend identity and a multipart flag. The examples deliberately omit raw URLs, query strings, cookies, authorization headers and request bodies. nginx / map and log_format in the existing http {} block ``` map $http_content_type $php2shell_is_multipart { default 0; ~*multipart/form-data 1; } log_format php2shell_security escape=json '{"ts":"$time_iso8601","request_id":"$request_id",' '"client":"$remote_addr","server":"$server_name",' '"method":"$request_method","multipart":$php2shell_is_multipart,' '"status":$status,"request_bytes":$request_length,' '"response_bytes":$body_bytes_sent,"seconds":$request_time,' '"upstream":"$upstream_addr","upstream_status":"$upstream_status"}'; ``` nginx / add to each relevant existing server {} block ``` access_log /var/log/nginx/php2shell-security.jsonl php2shell_security; ``` Apache / existing VirtualHost; requires mod_log_config and mod_setenvif ``` SetEnvIfNoCase Content-Type "multipart/form-data" php2shell_multipart=1 LogFormat "ts=%{%Y-%m-%dT%H:%M:%S%z}t client=%a peer=%{c}a vhost=%v method=%m multipart=%{php2shell_multipart}e status=%>s response_bytes=%B duration_us=%D worker_pid=%P error_id=%L" php2shell_security CustomLog "/var/log/apache2/php2shell-security.log" php2shell_security ``` - Test syntax with nginx -t or apachectl configtest, then reload using your service manager. Check effective logging in every location and virtual host; nested access_log settings and access_log off can override nginx inheritance. - Configure client-IP restoration only for trusted proxies. An untrusted forwarded address is attacker-controlled. Retain transport-peer or network-flow records when investigating origin bypass. - The Apache multipart field is 1 for a match and normally '-' otherwise. error_id may be '-' when no corresponding error-log entry exists. worker_pid is an Apache process, not an FPM worker. - nginx request_bytes includes the request line, headers and body; it is not decoded multipart size or PHP memory use. A small request can still cause substantial allocation. - Add server-controlled route categories and a trusted correlation ID through your existing tracing pipeline if needed. Avoid logging paths that contain reset tokens or identifiers. - Ship these records centrally with host/container labels, clock synchronization, rotation and restricted retention. The snippets do not sanitize other logs already enabled; audit those separately. Sources: [nginx HTTP access logging](https://php2shell.io/references.html#docs-nginx-logging) · [Apache HTTP Server request logging](https://php2shell.io/references.html#docs-apache-logging) · [CVE-2026-109618: out-of-memory corruption](https://php2shell.io/references.html#php-advisory-oom) #### PHP errors, memory pressure and worker exits Collect PHP diagnostics, FPM master logs, web-server errors and kernel/container lifecycle events together. Enable settings before requests begin; application-level ini_set() cannot recover earlier diagnostics. PHP-FPM / add to each existing pool; adapt paths and permissions ``` php_admin_flag[log_errors] = on php_admin_flag[display_errors] = off php_admin_value[error_log] = /var/log/php-fpm/php-errors.log ; Enable E_ALL during an isolated configuration/application audit. php_admin_value[error_reporting] = E_ALL access.log = /var/log/php-fpm/security-access.log access.format = "ts=%{%Y-%m-%dT%H:%M:%S%z}t pool=%n pid=%p status=%s duration_us=%{microseconds}d peak_bytes=%{bytes}M" ``` Linux / read-only examples; adapt paths and unit names ``` rg -n -i -- 'Allowed memory size of .* exhausted|Maximum execution time of .* exceeded|zend_mm_heap corrupted|PHP (Fatal|Parse) error|Uncaught' /var/log/php-fpm/php-errors.log journalctl -u php8.4-fpm --since '1 hour ago' --no-pager journalctl -k --since '1 hour ago' --no-pager ``` - Create non-public log paths with appropriate service write access and collector read access. Validate FPM configuration, replace workers to apply startup settings, and confirm records reach the collector. - For mod_php use the equivalent log_errors, display_errors, error_log and audit error_reporting settings in the active web php.ini, then restart Apache workers. The FPM access directives do not apply to mod_php. - Look for pre-script configuration warnings/deprecations, cleanup diagnostics, fatal/parse errors and execution timeouts as well as memory exhaustion. The regex is a starting filter, not a complete signature. - Correlate FPM child exit signals, unexpected respawns, kernel OOM kills and container termination reasons. Service journald records may not contain PHP errors written to a file; ingest both. - Pool plus PID plus host/container and process start time helps distinguish a persistent worker from PID reuse. A worker that crashes may never write its normal access record. - Imports, bugs, deployment restarts and normal pm.max_requests recycling are common alternatives. Logging may expose input in exception messages: restrict access, scrub secret fields at collection and keep verbose auditing time-bounded. - Changing error-reporting or display settings does not mitigate either CVE. Historical log gaps and unexercised application paths remain blind spots. Sources: [CVE-2026-109619: stale global state](https://php2shell.io/references.html#php-advisory-state) · [CVE-2026-109618: out-of-memory corruption](https://php2shell.io/references.html#php-advisory-oom) · [PHP-FPM pool configuration](https://php2shell.io/references.html#docs-php-fpm) #### Unexpected children of PHP workers Use process-creation telemetry to investigate PHP or Apache launching a shell or transfer utility. This experimental Sigma template is a behavioral lead; it does not identify a particular CVE. Sigma / Linux process_creation template; map fields to your EDR or SIEM ``` title: PHP Worker Starts Shell Or Transfer Utility status: experimental description: Investigate unexpected child processes; not a PHP2Shell-specific signature. author: php2shell.io date: 2026-10-21 logsource: category: process_creation product: linux detection: parent: ParentImage|endswith: - '/php-fpm' - '/php-fpm8.2' - '/php-fpm8.3' - '/php-fpm8.4' - '/php-fpm8.5' - '/php-cgi' - '/apache2' - '/httpd' - '/lsphp' - '/frankenphp' child: Image|endswith: - '/sh' - '/bash' - '/dash' - '/zsh' - '/curl' - '/wget' - '/nc' - '/ncat' - '/socat' condition: parent and child fields: - Image - ParentImage - ProcessId - ParentProcessId - User falsepositives: - Approved application subprocesses, converters and maintenance tasks level: medium ``` - Requires Linux execution events containing resolved executable and parent executable paths. Convert and validate the Sigma rule with the backend and field mappings used by your deployment; this is not a standalone executable detector. - Adapt executable names to inventory, including versioned CGI, LiteSpeed and embedded runtimes. Monitor php-fpm when nginx or Apache forwards to FPM; monitoring nginx descendants alone misses that runtime. - Investigate process ancestry, service account, deployment context and outbound connections. Use narrow, documented exceptions for legitimate behavior rather than excluding the entire web-service account. - This direct-parent template misses later descendants, renamed tools, shell built-ins and actions performed inside PHP. No child process is required for memory disclosure or every RCE path. - Command lines can expose secrets. Restrict richer forensic command-line collection rather than publishing raw argv in general dashboards. Track event loss and sensor health. Sources: [Sigma rule specification](https://php2shell.io/references.html#docs-sigma) · [process-watcher](https://php2shell.io/references.html#process-watcher) · [Early PHP2Shell incident-response guidance](https://php2shell.io/references.html#huntress-response) #### Optional HTTP inspection with Zeek Corelight publishes a Zeek package for suspicious form keys, multipart headers and serialized-data patterns. It can connect related requests by configured session cookies; its findings require investigation. Zeek / local policy after installing and reviewing corelight/php2shell-detect ``` @load packages # Suppress raw POST-body excerpts in detector notices. redef PHP2SHELL::notice_body_sample_bytes = 0; ``` - Requires Zeek 7.0 or later, the reviewed package installed through your normal package process, and HTTP visible to the analyzer. Encrypted traffic needs an appropriate inspection point. - Review PHP2SHELL notices in notice.log. PHP_Crash_Sequence means related suspicious transactions, not a confirmed operating-system crash or successful exploitation. - The documented defaults inspect POST bodies only within the first three HTTP transactions per connection, with an 8 MiB budget per transaction shared across MIME parts. These limits and parser differences leave gaps. - The package retains cookie correlation in memory; disabling its body excerpts does not sanitize other sensor logs. Review packet capture and adjacent logging policies separately. - Use current upstream advisories and package provenance for version verification. Response banners can be hidden, rewritten or show a version with vendor backports. Legitimate traffic can trigger these indicators. Sources: [PHP2Shell detection before disclosure](https://php2shell.io/references.html#corelight-research) · [PHP2Shell detections for Zeek and Suricata](https://php2shell.io/references.html#corelight-detector) #### Correlate changes instead of trusting one indicator Compare requests with your normal workload, then connect anomalies to the same backend and worker timeline. Repeated multipart errors, cookie-shape changes and unexpected process activity become more useful when they agree. Splunk SPL / illustrative hunt over the nginx JSON fields above ``` index=web sourcetype=php2shell:nginx multipart=1 | bin _time span=5m | stats count AS requests count(eval(status>=500 AND status<600)) AS server_errors values(upstream) AS backends by _time server client | where requests>=10 AND server_errors>=3 ``` - Prerequisite: ingest the JSON fields, map ts to event time, preserve host/container identity, and replace the example index and sourcetype. Ten requests and three server errors in five minutes are illustrative tuning values, not research-derived exploit thresholds. - Baseline by application and traffic pattern. Bulk uploads, imports, deployment failures, bots and clients behind shared NAT can create the same pattern; distributed or low-volume activity can evade this grouping. - Pivot from a result into PHP error and process records before and after the interval. For stale-state paths, examine successive requests handled by the same worker, not only a single request. - Investigate unexpectedly large or malformed PHPSESSID response-cookie values. Prefer derived length and format flags from an approved sensor, adjusted for custom session names and expected encoding. Do not log raw Set-Cookie headers or session values; disclosure may place sensitive memory there. - The baseline access logs above do not collect multipart field names or response cookies. A simple grep for PHP_SESSION_UPLOAD_PROGRESS cannot find a body field that was never logged; use authorized inspection metadata rather than broadly enabling body capture. - Treat a rare high-impact event seriously even below the illustrative thresholds. A 2xx response, no shell process, or no matching alert does not establish that exploitation was absent. Sources: [Original PHP2Shell disclosure site](https://php2shell.io/references.html#php2shell-original) · [PHP2Shell technical research](https://php2shell.io/references.html#wiz-research) · [CVE-2026-109619: stale global state](https://php2shell.io/references.html#php-advisory-state) · [Splunk aggregate functions](https://php2shell.io/references.html#docs-splunk-aggregate) #### WAF visibility and origin bypass Record which policy evaluated a request and whether its action was enforced. Compare edge activity with origin traffic so a quiet WAF dashboard is not mistaken for a quiet application. Google Cloud Logs Explorer / enforced Cloud Armor denials ``` resource.type="http_load_balancer" jsonPayload.enforcedSecurityPolicy.outcome="DENY" ``` AWS CloudWatch Logs Insights / the custom rule from Controls ``` fields @timestamp, action, terminatingRuleId | filter terminatingRuleId = "BlockMultipartToUnpatchedPHP" | stats count(*) as requests by bin(5m), action | sort requests desc ``` - Cloud Armor requires load-balancer logging on the relevant backend service. Its sampling rate controls visibility; preview matches and enforced actions are different. Filter by your policy/resource when multiple applications share a project. - AWS requires web ACL traffic logging to the queried CloudWatch log group. Change terminatingRuleId to your deployed rule name. The example selects terminating matches; Count matches and nested rule-group matches need their own fields. - Track action, rule ID, policy revision, request time, inspected-size limits and origin status. AWS oversizeFields describes components inspected above the service limit; it is not proof of malicious content. - Redact secrets and query strings in vendor logs. AWS log redaction does not automatically redact sampled requests or Security Lake data; review each destination separately. Cloudflare Security Events and other sampled views likewise are not a complete request archive. - Compare origin connection peers with the approved load-balancer/proxy path, accounting for health checks and internal traffic. Missing edge events may be sampling or delivery failure; unexpected direct-origin flows warrant investigation. - Check changes to policy attachments, priorities, Count/preview settings, exceptions and DNS exposure. A blocked request proves that rule matched that request, not that PHP is patched or the origin was never reached by another path. Sources: [Cloud Armor request logging](https://php2shell.io/references.html#docs-cloud-armor-logging) · [AWS WAF log fields](https://php2shell.io/references.html#docs-aws-waf-logging) · [AWS WAF web ACL rule specification](https://php2shell.io/references.html#docs-aws-waf) · [Cloudflare request-header fields](https://php2shell.io/references.html#docs-cloudflare) #### Preserve context and investigate the host Use correlated evidence to decide scope and containment. Keep the runtime upgrade moving; detection and investigation cannot replace remediation. - Preserve relevant edge, origin, PHP, process and network records with timestamps, time zones, host/container identifiers and the affected package build or image digest. Keep original evidence access-controlled. - Review new or modified files in web roots, upload directories, temporary storage, PHP configuration and startup/persistence locations against trusted deployment manifests or file-integrity baselines. Expected deployments and uploads are common sources of change. - Investigate unexpected outbound connections, service-account activity and child-process chains alongside file changes. Fileless execution and memory disclosure may leave no new file. - If compromise is credible, use the incident-response process to restrict exposure and isolate affected instances while preserving evidence. Prefer rebuilding from trusted images, rotating potentially exposed credentials and invalidating affected sessions as appropriate to the findings. - Record whether symptoms preceded the patch, verify all replicas and workers are replaced, and retain monitoring after remediation to investigate earlier exposure. - Validate collection with benign requests and known test events in staging. Confirm time alignment, parser behavior, rotation and delivery; do not run public exploit code against production to check an alert. Sources: [Original PHP2Shell disclosure site](https://php2shell.io/references.html#php2shell-original) · [PHP2Shell technical research](https://php2shell.io/references.html#wiz-research) · [CVE-2026-109618: out-of-memory corruption](https://php2shell.io/references.html#php-advisory-oom) · [CVE-2026-109619: stale global state](https://php2shell.io/references.html#php-advisory-state) --- ## Exploit Source: https://php2shell.io/pocs.html UNDERSTAND / VERIFY / INVESTIGATE ### Exploit anatomy & exposure checks. Follow the request through the PHP worker. Then check your running build, verify temporary controls, and understand what public lab tools actually measure. #### Anatomy of an exploit. Two paths through the request lifecycle. An attack does not have to combine both. HTTP → PHP → WORKER STATESimplified lifecycle · based on upstream advisories **A request reaches an unpatched PHP worker.**Runtime and application conditions determine the path. CVE-2026-109618 ##### An interrupted operation. Cleanup encounters incomplete request state. 1. REQUEST / INPUT ###### PHP allocates request memory. Input processing creates structures that can become reachable before initialization finishes. 2. INTERRUPTION / OOM ###### An allocation fails. An out-of-memory exit interrupts the operation and leaves incomplete state. 3. SAME REQUEST / CLEANUP ###### Shutdown uses incomplete state. Cleanup accesses it. A crafted memory layout can turn corruption into code execution. **Runtime matters.** Confirmed before application code on mod_php. FPM exits on startup failure; later application-driven OOM remains susceptible, but this advisory demonstrates no complete FPM OOM exploit. [PHP advisory: OOM corruption ↗](https://php2shell.io/references.html#php-advisory-oom) CVE-2026-109619 ##### A reference outlives its request. A later request consumes an old reference. 1. REQUEST A / PRODUCER ###### A reference survives reset. The worker retains request-owned data. An interruption skips reset, or late cleanup repopulates the reference. 2. REQUEST A / RELEASE ###### The request memory is freed. Request memory is released while the worker keeps its reference. 3. REQUEST B / SAME WORKER ###### An early consumer uses it. Another request reaches that worker. An INI diagnostic or session upload progress accesses stale memory before normal initialization. **Runtime matters.** Confirmed: fatal-backtrace RCE on mod_php; session-lifecycle RCE on mod_php and FPM. FPM requires a suitable application operation after successful startup. [PHP advisory: stale global state ↗](https://php2shell.io/references.html#php-advisory-state) POSSIBLE IMPACT A successful chain can disclose memory or execute code with the web worker’s privileges. A crash alone is not proof of RCE. ##### What to connect in monitoring. | Layer | Look for | Interpretation | | --- | --- | --- | | Request | Multipart anomalies; repeated requests | Entry-point leads, not exploit proof | | Worker | Memory errors; fatal errors; worker exits | Correlate by time and worker | | Host | Unexpected child processes or outbound traffic | Investigate; quiet logs do not clear exposure | ##### Evidence has limits. Confirmed cases are attributed to PHP’s maintainers, not reproduced here. Lab behavior does not establish real-world exploitation. [Read the lab limitations →](https://php2shell.io/pocs.html#slabb-lab) [FOLLOW THE EVIDENCE**Correlate requests and worker events.**](https://php2shell.io/detection.html#correlation)[CLOSE BOTH PATHS**Patch PHP. Verify the running workers.**](https://php2shell.io/patch.html#verify) Structure inspired by [Sophos’s Log4Shell anatomy article](https://php2shell.io/references.html#sophos-log4shell-anatomy). PHP2Shell evidence comes from the PHP advisories above. #### Source reviewed. Execution unverified. The repositories below were inspected as source. No exploit was executed for this site. Their findings and scripts vary in scope, and some explore related session or deserialization behavior rather than reproduce every path in the official advisories. **Keep reproduction in an isolated lab** Use only systems you own or are authorized to test. Bind lab services to loopback, avoid public FastCGI exposure, and inspect setup scripts before running them. Use disposable instances without production secrets. Sources: [Official CVE-2026-109618 scope](https://php2shell.io/references.html#php-advisory-oom) · [Official CVE-2026-109619 scope](https://php2shell.io/references.html#php-advisory-state) #### Check your exposure with curl There is no universal non-exploit HTTP probe that proves either PHP2Shell CVE is present or fixed. The strongest routine check combines your live web runtime, the installed package or image, and an advisory confirming both fixes. ##### 1. Read your private runtime diagnostic Use the access-restricted diagnostic from the [Patch guide](https://php2shell.io/patch.html#verify), or your existing authenticated inventory endpoint. Replace the URL and use its normal authentication. An arbitrary application URL will not return this information. curl / private diagnostic on your owned host ``` curl --fail --silent --show-error --max-time 10 \ --header 'Accept: application/json' \ 'https://your-owned-host.example/internal/php-runtime-check.php' ``` Compare the returned web-SAPI version with [the first fixed releases](https://php2shell.io/patch.html#versions). For vendor backports, check the exact package build and advisory. Verify every replica. The upload-progress value describes one feature; an Off value is not a patched-state verdict. Remove the temporary endpoint afterward. ##### 2. Check a blanket multipart block Use a disposable endpoint through the actual edge or web server you configured. This sends a normal form field, without a PHP upload-progress trigger or exploit payload. The endpoint may still process form submissions. curl / benign control probe through your edge ``` curl --silent --show-error --max-time 10 \ --output /dev/null --write-out 'HTTP %{http_code}\n' \ --form-string 'probe=php2shell-control-check' \ 'https://your-owned-host.example/your-test-endpoint' ``` | Observation | What it establishes | What it does not establish | | --- | --- | --- | | Fixed live build + matching advisory | Evidence that both fixes are installed for that runtime | Coverage of other replicas or absence of earlier compromise | | 403 + matching rule log | The selected control rejected that request | PHP patch status or coverage of other paths | | 2xx response | The request was accepted | Vulnerability or successful exploitation | | 5xx, timeout, or crash | A failure worth investigating | A CVE-specific result or successful RCE | | Upload-progress metadata | The feature ran in that lab configuration | Memory corruption or either CVE being exploitable | HTTP banners can be hidden, rewritten, or carry an older version with backported fixes. A missing version header, a failed PoC, or a clean log search cannot clear a deployment. Sources: [PHP OOM advisory](https://php2shell.io/references.html#php-advisory-oom) · [PHP state-lifecycle advisory](https://php2shell.io/references.html#php-advisory-state) · [Normal upload-progress behavior](https://php2shell.io/references.html#docs-upload-progress) #### Use the slabb lab as an observation exercise The linked article suggests useful practices: pin a reference build, observe request/session behavior, and compare a vulnerable build with a verified fixed one. The reviewed repository provides a research scaffold; it does not demonstrate a reliable end-to-end RCE chain. **Isolated, disposable lab only** The top-level Compose file publishes ports on all host interfaces by default. Before starting it, change each published mapping to an explicit loopback binding: `127.0.0.1:8898:80`, `127.0.0.1:8899:8899`, `127.0.0.1:8900:8899`, and `127.0.0.1:8901:8899`. Keep production data and credentials out of the lab. shell / retrieve the reviewed source and inspect the configuration ``` git clone https://github.com/slabbdev/php2shell-cve-2026-109618-109619.git cd php2shell-cve-2026-109618-109619 git checkout --detach 9d70d5c825e56ef413d6e7e3bae9a3d76ebc8d7c # Read source and correct port bindings before startup. docker compose config python3 harness/race.py --help ``` After reviewing the source and applying the loopback bindings, start only the FPM/nginx lab. The ping endpoint starts a session; its response checks availability, not vulnerability. shell / start the isolated lab and check availability ``` docker compose up -d fpm nginx curl --fail --silent --show-error --max-time 5 \ 'http://127.0.0.1:8898/index.php?a=ping' ``` ##### Observe one small upload The following source-verified flags disable concurrent disturbance modes and send one upload with 1 KiB of file content plus multipart overhead. It still writes upload/session state. Use only the isolated lab. shell / lab observation — not an exposure scanner ``` python3 harness/race.py \ --host 127.0.0.1 --port 8898 --path /index.php \ --modes "" --rounds 1 --total-kb 1 --parts 0 ``` **Read the output correctly:** the harness counts connectivity failures, accepts any HTTP status in its health probes, and discards upload outcomes. `failures=0` does not prove a successful upload, a safe runtime, or either CVE. There is no `--check` or `--dry-run` mode. Its INI settings change progress cleanup and update frequency, so persistent metadata is not evidence of default production behavior. The separate WordPress impact payload assumes code execution; it is not a chain produced by this harness. Keep patched/unpatched comparison results tied to exact builds and actual memory-error evidence. shell / stop the disposable lab ``` docker compose down ``` Sources: [Article](https://php2shell.io/references.html#slabb-article) · [Pinned-source research lab](https://php2shell.io/references.html#slabb-lab) · [PHP feature documentation](https://php2shell.io/references.html#docs-upload-progress) #### Public repositories eness / PUBLIC REPOSITORY ##### [php2shell-CVE-2026-109618-CVE-2026-109619-PoC](https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC) Community PoC source and mitigation examples for PHP, Apache, Cloudflare, FrankenPHP and lighttpd. The reviewed snapshot contains poc_109618.py despite the README's older coming-soon notice. Source inspected and Python syntax checked; exploit not executed. The script depends on build-specific addresses. Its presence does not establish reliable exploitation across PHP deployments. [PoC source ↗](https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC/blob/8ed851963798e1d08d7cf8676967b85ab2a728ee/poc_109618.py) · [Repository documentation ↗](https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC/blob/8ed851963798e1d08d7cf8676967b85ab2a728ee/README.md) · [Mitigation helper source ↗](https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC/blob/8ed851963798e1d08d7cf8676967b85ab2a728ee/quick-fix/run.sh) Reviewed snapshot: `8ed851963798` · 21 Oct 2026 Qi Deng / ikow / PUBLIC REPOSITORY ##### [php2shell-poc](https://github.com/ikow/php2shell-poc) Session-file injection and serializer-mismatch verification scripts, a deserialization UAF reproducer, and research notes. The described RCE chains require additional conditions such as application LFI, unsafe deserialization or a usable gadget. Source inspected; scripts not executed. The lab generator uses a floating PHP image, publishes HTTP and FastCGI on all interfaces, and enables privileged mode with seccomp disabled. Review and isolate it before use; the supplied setup is not a safe localhost-only recipe. [Session injection verification ↗](https://github.com/ikow/php2shell-poc/blob/6143dcbab9b92aa4238fcb4512ecd3556734f738/poc/verify_session_injection.py) · [Handler mismatch verification ↗](https://github.com/ikow/php2shell-poc/blob/6143dcbab9b92aa4238fcb4512ecd3556734f738/poc/verify_handler_mismatch.py) · [Deserialization UAF source ↗](https://github.com/ikow/php2shell-poc/blob/6143dcbab9b92aa4238fcb4512ecd3556734f738/poc/verify_uaf_asan.php) · [Lab generator to review ↗](https://github.com/ikow/php2shell-poc/blob/6143dcbab9b92aa4238fcb4512ecd3556734f738/lab/setup.sh) Reviewed snapshot: `6143dcbab9b9` · 21 Oct 2026 Zer061 / PUBLIC REPOSITORY ##### [CVE-2026-109618](https://github.com/Zer061/CVE-2026-109618) Research bundle with claimed exploit implementations, a framework and validation notes. The repository credits J4ck3LSyN, Andrew Dorman and Arch&Yuki; reproduction claims remain attributed to its authors. Source inspected; nothing executed. All four Python files in this reviewed snapshot fail syntax parsing at line 1 because uncommented prose precedes the shebang. The README also refers to directories absent from the snapshot. This is not a verified runnable package. [Framework source ↗](https://github.com/Zer061/CVE-2026-109618/blob/53624b2c61df9339329d994a98195bda52614a23/php_up_framework.py) · [CVE-2026-109618 source ↗](https://github.com/Zer061/CVE-2026-109618/blob/53624b2c61df9339329d994a98195bda52614a23/poc0_109618.py) · [CVE-2026-109619 source ↗](https://github.com/Zer061/CVE-2026-109618/blob/53624b2c61df9339329d994a98195bda52614a23/poc1_109619.py) · [Author validation report ↗](https://github.com/Zer061/CVE-2026-109618/blob/53624b2c61df9339329d994a98195bda52614a23/REPORT_VALIDATION.md) Reviewed snapshot: `53624b2c61df` · 21 Oct 2026 slabbdev / PUBLIC REPOSITORY ##### [php2shell-cve-2026-109618-109619](https://github.com/slabbdev/php2shell-cve-2026-109618-109619) Upload/session research lab with pinned PHP images, nginx/FPM targets, a WordPress example and an AddressSanitizer build scaffold. Useful for controlled observation and build comparisons. Source reviewed, not executed. The harness does not return a reliable vulnerability verdict; normal progress metadata is not proof of either CVE. Top-level port bindings require loopback correction. The separate impact payload assumes code execution rather than demonstrating how to obtain it. [Harness source ↗](https://github.com/slabbdev/php2shell-cve-2026-109618-109619/blob/9d70d5c825e56ef413d6e7e3bae9a3d76ebc8d7c/harness/race.py) · [Compose configuration ↗](https://github.com/slabbdev/php2shell-cve-2026-109618-109619/blob/9d70d5c825e56ef413d6e7e3bae9a3d76ebc8d7c/docker-compose.yml) · [Lab PHP target ↗](https://github.com/slabbdev/php2shell-cve-2026-109618-109619/blob/9d70d5c825e56ef413d6e7e3bae9a3d76ebc8d7c/target/www/index.php) · [WordPress INI settings ↗](https://github.com/slabbdev/php2shell-cve-2026-109618-109619/blob/9d70d5c825e56ef413d6e7e3bae9a3d76ebc8d7c/wordpress-demo/php/zz-defaults.ini) Reviewed snapshot: `9d70d5c825e5` · 21 Oct 2026 #### A benign control-check example This ordinary upload checks whether a blanket multipart deny rule fires in your local test environment. It contains no exploit payload. shell / localhost only ``` curl --include --max-time 10 \ --form 'probe=php2shell-rule-check' \ --form 'file=@/dev/null;filename=probe.txt' \ http://127.0.0.1:8080/upload.php ``` Look for the configured denial and corresponding logs. A 403 is evidence of that request being rejected; it is not evidence that PHP is patched. See the [compensating controls](https://php2shell.io/controls.html) for matching configuration. #### Signals to investigate - New or unusual multipart traffic, especially alongside memory-limit errors. - Repeated HTTP 500 responses, worker crashes, or unexpected process restarts. - Malformed or unusually large `PHPSESSID` response cookies. - Unexpected shell or transfer-tool processes started by PHP workers, and unfamiliar files in web roots or temporary directories. Correlate these with your baseline and preserve relevant logs. None is conclusive by itself; absence of child processes does not rule out memory disclosure or exploitation. Sources: [Advisory source](https://php2shell.io/references.html#php2shell-original) · [Detection research](https://php2shell.io/references.html#corelight-research) · [Process monitoring](https://php2shell.io/references.html#process-watcher) --- ## Read Source: https://php2shell.io/references.html SOURCES / ATTRIBUTION & FURTHER READING ### References. Primary advisories, independent research, public PoCs, and infrastructure documentation. Technical guidance is paraphrased here; original findings and credit belong to the linked authors. **How sources are used** The current PHP advisories take precedence over early reports and community README files. Some linked research predates the final release. External publications may contain vendor messaging; inclusion is attribution, not endorsement. 51 references #### [CVE-2026-109618: out-of-memory corruption](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) PHP's authoritative advisory covering the OOM vulnerability class, affected branches, fixed releases and the limits of configuration workarounds. PHP security team #### [CVE-2026-109619: stale global state](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp) PHP's authoritative advisory on state surviving across requests, confirmed attack paths and the complete state-reset fix. PHP security team #### [21 October 2026 security release](https://www.php.net/archive/2026.php#2026-10-21-1) Release announcement for PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12, with update instructions and partial mitigation guidance. PHP project #### [PHP downloads](https://www.php.net/downloads.php) Official release downloads and verification information. Distribution users should also check their vendor's security packages and backport notices. PHP project #### [Supported PHP branches](https://www.php.net/supported-versions.php) Upstream maintenance timelines for active support, security fixes and end of life. PHP project #### [PHP 7.4 minimal source backport](https://github.com/php/php-src/tree/PHP-7.4-CVE-2026-109618-109619) Exceptional source backport linked by the PHP security announcement. PHP 7.4 remains end of life; this does not restore normal support. PHP project #### [PHP 8.0 minimal source backport](https://github.com/php/php-src/tree/PHP-8.0-CVE-2026-109618-109619) Exceptional source backport linked by the PHP security announcement for maintainers building their own packages. PHP 8.0 remains end of life. PHP project #### [PHP 8.1 minimal source backport](https://github.com/php/php-src/tree/PHP-8.1-CVE-2026-109618-109619) Exceptional source backport linked by the PHP security announcement. Check vendor packages or migrate to a supported branch; PHP 8.1 remains end of life. PHP project #### [Original PHP2Shell disclosure site](https://www.php2shell.com/) Research overview, demonstrations, release matrix and coordinated disclosure references. A source for the technical context summarized on this independent site. PHP2Shell research collaborators #### [PHP2Shell technical research](https://www.wiz.io/blog/php2shell-php-rce) Original research publication linked by the disclosure site, covering the PHP vulnerability family and exploitation research. Wiz Research #### [PHP2Shell: discovery and technical analysis](https://calif.io/php2shell/) Ryan Austin's research into interrupted PHP operations, multipart processing and request lifecycle state, including distinctions between mod_php and FPM. Calif #### [Coordinated disclosure of critical vulnerabilities](https://openai.com/index/coordinated-disclosure-of-critical-vulnerabilities) Coordinated disclosure publication linked by the original PHP2Shell site. OpenAI #### [Critical remote code execution vulnerabilities in PHP core](https://www.akamai.com/blog/security-research/critical-remote-code-execution-vulnerabilities-php-core) Security research publication linked by the original disclosure site. Consult the publisher for its current detection and mitigation guidance. Akamai #### [PHP2Shell vulnerability updates](https://www.imperva.com/blog/php2shell-vulnerability-updates/) Provider publication on PHP2Shell linked by the disclosure site, with updates for its customers. Imperva #### [PHP vulnerabilities and WAF protection](https://blog.cloudflare.com/php-vulnerabilities-waf-protection/) WAF response publication linked by the disclosure site. Provider rules address particular request patterns and do not replace a runtime update. Cloudflare #### [PHP2Shell detection before disclosure](https://corelight.com/blog/php2shell-detection-before-disclosure) Detection research publication linked by the original PHP2Shell disclosure site. Corelight #### [Response to the PHP RCE vulnerabilities](https://www.crowdstrike.com/en-us/blog/crowdstrike-protects-customers-from-php-rce-zero-days/) Provider response publication linked by the original disclosure site. Check the source for current product coverage and investigation guidance. CrowdStrike #### [CVE-2026-109618 and CVE-2026-109619 analysis](https://unit42.paloaltonetworks.com/cve-2026-109618-cve-2026-109619/) Security analysis and response publication linked by the original PHP2Shell disclosure site. Palo Alto Networks Unit 42 #### [Early PHP2Shell incident-response guidance](https://www.huntress.com/blog/php2shell-leaked-critical-php-vulnerabilities) Early disclosure context and examples of suspicious processes launched by PHP workers. Pre-release statements should be checked against the final PHP advisories. Huntress #### [Historical context: PHP bug #78876](https://bugs.php.net/bug.php?id=78876) A 2019 multipart allocation and temporary-file cleanup report, referenced by later research. This is a separate historical issue, CVE-2019-11048. PHP bug tracker #### [Historical context: the 2024 PHP security audit](https://ostif.org/php-audit-complete/) OSTIF's April 2025 account of Quarkslab's 2024 PHP audit. Background research referenced by Calif, separate from the October 2026 advisories. OSTIF / Quarkslab #### [php2shell-CVE-2026-109618-CVE-2026-109619-PoC](https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC) Community repository containing mitigation examples, helper scripts and research material. Individual snippets are partial controls, not substitutes for the official fix. eness #### [php2shell-poc research and lab](https://github.com/ikow/php2shell-poc) Independent lab and verification material for several session-related chains. Requirements differ between examples; repository claims are not independent validation of both CVEs. Qi Deng / ikow #### [CVE-2026-109618 validation bundle](https://github.com/Zer061/CVE-2026-109618) Community mirror of a session upload-progress research bundle. Its README describes the CVE association as presumed; use it as research material rather than an authoritative advisory. Zer061 and credited contributors #### [process-watcher](https://github.com/Neo23x0/process-watcher) Linux process monitoring for investigating programs launched by services. It cannot detect every PHP2Shell path, including memory disclosure or activity contained within PHP. Florian Roth / Neo23x0 #### [PHP-FPM pool configuration](https://www.php.net/manual/en/install.fpm.configuration.php) Official reference for FPM pool directives, administrative PHP settings and worker lifecycle options. PHP manual #### [Apache HTTP Server rewrite rules](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html) Official syntax and context reference for the Apache request-filtering example. Apache HTTP Server project #### [nginx HTTP map module](https://nginx.org/en/docs/http/ngx_http_map_module.html) Official reference for mapping request headers to variables used by the nginx mitigation example. nginx #### [AWS WAF web ACL rule specification](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-wafv2-webacl-rule.html) AWS CloudFormation reference for WAF rules, statements, actions, priorities and visibility configuration. Amazon Web Services #### [lighttpd access-control implementation](https://github.com/lighttpd/lighttpd1.4/blob/master/src/mod_access.c) Upstream mod_access implementation supporting the lighttpd access-denial example. Confirm compatibility with the deployed lighttpd version. lighttpd project #### [Google Cloud Armor rules language](https://docs.cloud.google.com/armor/docs/rules-language-reference) Official CEL expression reference for matching request attributes in Cloud Armor security policies. Google Cloud #### [Cloudflare request-header fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.headers/) Rules-language reference for request-header arrays used by the Cloudflare custom-rule example. Cloudflare Developers #### [nginx HTTP access logging](https://nginx.org/en/docs/http/ngx_http_log_module.html) Official reference for access_log and log_format, including escaping, buffering and conditional logging. nginx #### [Apache HTTP Server request logging](https://httpd.apache.org/docs/2.4/mod/mod_log_config.html) Official reference for CustomLog, LogFormat and fields used to record HTTP request and response metadata. Apache HTTP Server project #### [Sigma rule specification](https://github.com/SigmaHQ/sigma-specification/blob/main/specification/sigma-rules-specification.md) Upstream specification for portable detection rules, including log sources, selections, conditions and rule metadata. SigmaHQ #### [Cloud Armor request logging](https://docs.cloud.google.com/armor/docs/request-logging) Google Cloud documentation for security-policy request logs, logging configuration and interpreting policy decisions. Google Cloud #### [AWS WAF log fields](https://docs.aws.amazon.com/waf/latest/developerguide/logging-fields.html) AWS reference for WAF log records and the fields used to investigate rule matches and request handling. Amazon Web Services #### [PHP2Shell detections for Zeek and Suricata](https://github.com/corelight/php2shell-detect) Open-source HTTP detections and configuration guidance. Findings identify suspicious traffic or potentially affected software; they do not establish successful exploitation. Corelight #### [PHP logo color source](https://www.php.net/download-logos.php) Official PHP logo assets used as a color-palette reference. php2shell.io is an independent site and is not affiliated with the PHP project. PHP project #### [PHP2Shell remote code execution FAQ](https://watchtowr.com/intelligence/php-cve-2026-109618-faq/) Early disclosure FAQ first published on 20 October 2026. Its pre-release patch and exposure statements should be read alongside the final PHP advisories. watchTowr Intel #### [Splunk aggregate functions](https://help.splunk.com/en/splunk-enterprise/search/spl-search-reference/9.4/statistical-and-charting-functions/aggregate-functions) Official SPL reference for aggregate functions used to summarize events in the sample detection query. Splunk #### [PHP2Shell lab demonstration and remediation notes](https://dev.to/slabb/php2shell-two-critical-rces-in-php-core-lab-demo-and-how-to-fix-cve-2026-109618-and-2ieb) Sam Labbe’s community write-up on a local PHP research lab. Some scope and version statements predate the final advisories; feature activation is not confirmed exploitation. Sam Labbe / DEV Community #### [PHP2Shell local lab and WordPress target](https://github.com/slabbdev/php2shell-cve-2026-109618-109619) Research scaffold with pinned PHP images, an upload-progress harness and sanitizer build support. The reviewed material demonstrates feature exposure, not a verified end-to-end RCE chain. slabbdev / Sam Labbe #### [PHP session upload progress](https://www.php.net/manual/en/session.upload-progress.php) Official description of upload-progress behavior and session metadata. The presence of progress entries alone is normal feature behavior and does not demonstrate either vulnerability. PHP manual #### [Cloudflare arrays and transformation syntax](https://developers.cloudflare.com/ruleset-engine/rules-language/values/#arrays) Array unpacking syntax used with lower(), header values and any() in the custom-rule example. Cloudflare documentation #### [CVSS v4.0 specification](https://www.first.org/cvss/v4.0/specification-document) The primary definition of CVSS v4.0 metrics, scoring, severity bands, and nomenclature used by the Overview calculator. FIRST.Org, Inc. #### [CVSS v4.0 reference calculator and scoring source](https://github.com/FIRSTdotorg/cvss-v4-calculator/tree/c5b0d409ae9f57c44264c6ce5f27d89298e1d32a) Pinned BSD-2-Clause source for the official scoring implementation served locally by this site. The complete FIRST calculator also supports Threat and Environmental metrics. FIRST.Org, Inc. #### [Log4Shell Hell: anatomy of an exploit outbreak](https://www.sophos.com/en-us/blog/log4shell-hell-anatomy-of-an-exploit-outbreak) Narrative inspiration for this site's exploit-anatomy walkthrough. This article concerns Log4Shell and is not evidence for PHP2Shell mechanisms, indicators or exploitation. Sophos / Sean Gallagher #### [PHP 8.5: upstream fix for both PHP2Shell CVEs](https://github.com/php/php-src/commit/31c0ea7d7ff1d1fccb6492e52dab544011628065) Pinned upstream commit 31c0ea7d: allocator failure handling, request-state resets, and regression tests. The commit explicitly fixes CVE-2026-109618 and CVE-2026-109619. PHP project #### [PHP allocator: pending OOM and VM interruption](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_alloc.c#L439-L441) Exact added allocator lines shown in the Overview anatomy, pinned to the PHP 8.5 fixing commit. The surrounding implementation is part of the complete runtime update. PHP project #### [PHP executor: clear request-owned error state](https://github.com/php/php-src/blob/31c0ea7d7ff1d1fccb6492e52dab544011628065/Zend/zend_execute_API.c#L437-L445) Pinned shutdown-reset code shown in the Overview anatomy. It clears the fatal backtrace and related executor globals before they can be reused by a subsequent request. PHP project Reviewed 21 October 2026. This is a static snapshot; verify current vendor guidance before making changes. ---