At a Glance
Are you affected?
If you run PHP that serves web requests (PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP or LiteSpeed) and it is older than 8.2.35, 8.3.36, 8.4.27 or 8.5.12, assume you are affected. This includes applications built on PHP such as WordPress, Drupal, Magento and Laravel.
Is TR7 affected?
No. TR7 appliances have no PHP component that processes HTTP requests, so TR7 products are not affected by these vulnerabilities. Details are in Is TR7 Affected?.
What to do now
- Update PHP on your web application servers and restart every PHP worker.
- Apply the temporary PHP settings below on those servers if you cannot update today.
- Until the update is complete, apply the core protection settings in TR7 WAF-WAAP; putting your PHP applications in Blocking mode is the first of them.
Key Facts
| Advisory ID | TR7-SA-2026-001 |
|---|---|
| Name | PHP2Shell |
| CVEs | CVE-2026-109618 (remote code execution via out-of-memory corruption), CVE-2026-109619 (remote code execution via stale global state) |
| Official advisories | PHP Security Team announcement GHSA-w8hw-w9fx-j79w (CVE-2026-109618) GHSA-6wmf-4rv5-p3rp (CVE-2026-109619) |
| Severity | CVSS v4.0 9.2, Critical (PHP Security Team) |
| Authentication required | No |
| Fixed versions | PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12 |
| Older branches | The PHP Security Team published source backports for PHP 7.4, 8.0 and 8.1. Linux distributions provide their own patched packages. |
| Exploitation | Exploitation attempts are being reported. A successful compromise had not been publicly confirmed as of October 22, 2026. |
| CISA KEV | Not listed as of the October 21, 2026 catalog |
What Happened
- October 20, 2026 Details of the vulnerabilities became public before the coordinated release.
- October 21, 2026 The PHP project released fixed versions and published the advisories GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp.
- October 21-22, 2026 Exploitation attempts were reported, and public proof-of-concept code appeared.
How the Attack Works
Both vulnerabilities are in PHP itself, not in application code. The attack happens while PHP is still reading the incoming request, before any line of your application runs. Updating WordPress, a plugin or your own code does not fix it.
- CVE-2026-109618 abuses the moment PHP runs out of memory. Attackers send requests that force PHP to use a lot of memory while it parses form data and file uploads, so that PHP stops in an unsafe state.
- CVE-2026-109619 leaves stale data behind in a PHP worker after one request, and a second request to the same worker uses it. One documented path uses PHP's session upload progress feature, which is enabled by default and is triggered by a form field named
PHP_SESSION_UPLOAD_PROGRESS.
Because the requests that carry these attacks are mostly multipart/form-data (file upload) requests, large request bodies and repeated requests, a web application firewall can see and restrict many of them. It cannot see what happens inside PHP's memory.
Is TR7 Affected?
These vulnerabilities are in PHP's own request handling layer and affect application servers that run PHP. TR7 appliances have no PHP component that processes HTTP requests, so TR7 products are not affected by these vulnerabilities.
What You Should Do Now
The work is in two places: your own web application servers that run PHP, and TR7 WAF-WAAP. Each section numbers its own steps.
On your servers
Step 1: Update PHP on your web application servers (the only complete fix)
- Update PHP on the servers that run your web application to 8.2.35, 8.3.36, 8.4.27 or 8.5.12, or install your Linux distribution's patched package. Distribution packages often keep the old version number; check the package changelog for the CVE numbers.
- Restart every PHP worker (PHP-FPM pools, Apache, LiteSpeed, long-running workers). Running processes keep using the old code until they restart.
- Rebuild container images that include their own PHP. Updating the host does not update PHP inside an image.
- PHP 8.1 and older no longer receive updates from the PHP project. Plan an upgrade to a supported branch.
Step 2: Temporary PHP settings on your web application servers (if you cannot update today)
These settings are made in the PHP configuration of the server that runs your web application (php.ini or PHP-FPM pool settings). The PHP Security Team lists these measures. They reduce exposure to specific attack paths but do not make an installation safe.
| Setting | Purpose |
|---|---|
session.upload_progress.enabled = 0 | Removes the session upload progress path of CVE-2026-109619. Restart all workers. The PHP Security Team suggests keeping it off after patching if you do not need it. |
fatal_error_backtraces = 0 (PHP 8.5) | Removes the fatal error backtrace path |
post_max_size = 8M (no uploads) or 32M (uploads), with upload_max_filesize lower | Reduces the memory an attacker can force PHP to use |
memory_limit = -1, set with php_admin_value | Removes the controllable memory limit failure. One request can then use all server memory; use container or cgroup limits, never RLIMIT_AS or RLIMIT_DATA |
On TR7 WAF-WAAP
If you can update PHP right away, that is the real fix. If you cannot, until the update is complete you can protect your PHP applications against these attacks with the security settings TR7 WAF-WAAP already provides, without any TR7 update. The three settings in Step 1 are the core protection; the additional measures in Step 2 narrow the attack surface further, so choose the ones that fit your application. Apply the settings per vService and try them on a non-production vService first.
Step 1: Core protection
1.1 Put the WAF in Blocking mode
A WAF that only monitors does not stop an attack. When the WAF is first enabled it starts in Learning mode; Monitor mode only records. For each PHP vService, open the WAF Mode screen and confirm it is in Blocking mode.
Caution: Before you switch, review the signature exclusions learned on each field. If the exclusions on a field exceed the Max. owasp exclusions value, signature inspection is turned off for that field.
1.2 Add two custom rules
On the Signature & Rule Library screen (WAF → Signature & Rule Library → Add), add the two rules below separately. Start both in the Monitor state and change them to Enabled after reviewing Event Logs. The rules apply to every WAF-protected vService.
Rule 1: Session upload progress field
- Pattern (Regex):
PHP_SESSION_UPLOAD_PROGRESS - Inspection Scopes: Form and Raw
- Score: Very High
Catches the form field that triggers the session upload progress path of CVE-2026-109619. For applications that legitimately use this feature, exclude only the upload paths that need it.
Rule 2: PHPSESSID form field
- Pattern (Regex):
^PHPSESSID$ - Inspection Scopes: Form
- Score: Very High
Catches requests that carry the session ID in a form field named PHPSESSID instead of a cookie; some attack paths use this form, and it is rare in legitimate traffic. If your application uses a different session name (session.name), use that name.
For the rules to work: The rules are scanned with the Form and RAW inspections of the page type that matches the request. On a page type without a Form inspection, form and file upload bodies are not scanned.
- Keep OWASP check on in the Any Paths rule and in page types that have their own Form or RAW inspection.
- Add its own Form and RAW inspection to every glob page type with the Add common rule for Form and Add common rule for Raw buttons; do not rely on inherited settings.
1.3 Block large and uninspectable bodies
On the WAF Rules screen, make two settings in the RAW inspection:
- Set Raw Body Size to the largest body the path needs (in bytes; for example 8388608 = 8 MB on paths without uploads, 33554432 = 32 MB on upload paths). The default range allows bodies up to 256 MB.
- Switch the unparsed body toggle from Allow unparsed body to Block unparsed body. Otherwise a body that does not fit the inspection buffer is forwarded to the Backend Service without any content inspection.
Where? The WAF inspects a request only with the settings of the page type that matches its path. Make these two settings on the Any Paths rule, on every page type that shows Raw in the Check Fields column, and on every glob page type; add a RAW inspection first with Add common rule for Raw to a glob page type that has none.
Caution: Raw Body Size applies while Structure Checks is on, on the Checks screen. Test legitimate large uploads first. Bodies sent without a declared length are not measured by this limit; on paths outside the upload paths they can be blocked with 2.1.
Step 2: Additional measures
These measures complement the core protection; choose the ones that fit your application.
2.1 Block file uploads where you do not need them
Attack requests are mostly multipart/form-data (file upload) requests. If only a few paths in your application accept files, block multipart requests to every other path with a load balancer rule. The rule consists of two conditions and a Block action. All screens are reached from the Configuration Menu, opened with the TR7 logo at the bottom left.
A. Create the conditions (Load Balancer → Conditions → Add)
- Multipart request condition: Criteria = HTTP header, matching method Includes, Header Name = Request →
Content-Type, Query =multipart/form-data, Case Insensitive on. Enter a Condition Name such asmultipart-requestand save with Add. - Upload paths condition: Criteria = Path, matching method Regex, and in Query enter the paths that accept files (for example
^/(upload|media/upload)). Enter a Condition Name such asupload-pathsand save with Add.
B. Create the Block action (Load Balancer → Actions → Add)
- Enter an Action Name (for example
block-multipart), Action Type = Block, Execution Level = On Request, Deny Type = Standard, Status Code = 403. - In Conditions, select
multipart-requestand!upload-pathsin the same condition group (default and). Every condition appears in the list twice: itself and its negation (NOT) starting with!;!upload-pathsmeans "not one of the upload paths". - Turn on Hit Counter to count blocked requests and save with Add.
C. Add the action to the vService
- On Load Balancer → Load Balancer vService List, select the vService and click Edit, select the action in Actions under Details, and click Save.
D. Also block bodies sent without a declared length
- Create another HTTP header condition: matching method Is present, Header Name = Request →
Content-Length, Condition Name for examplehas-length. - Create a second Block action (On Request, Standard, 403). In Conditions, select the predefined If HTTP method is POST condition,
!has-lengthand!upload-pathsin the same condition group, and add the action to the vService Actions field. The POST condition is required; without it, GET requests without a body are blocked too.
The size limit in 1.3 does not see the real size of a body sent without a declared length. This rule covers both HTTP/1.1 streamed (chunked) uploads and HTTP/2 bodies without a declared length on paths outside the upload paths. POST requests with no body and no Content-Length header also match this rule; try it on a non-production vService first.
Verify: A multipart request (curl -s -o /dev/null -w '%{http_code}\n' -F 'a=b' https://www.example.com/), an HTTP/1.1 chunked request (curl -s -o /dev/null -w '%{http_code}\n' --http1.1 -H 'Transfer-Encoding: chunked' -d 'a=b' https://www.example.com/) and an HTTP/2 request without a declared length (printf 'a=b' | curl -s -o /dev/null -w '%{http_code}\n' --http2 -X POST -T - https://www.example.com/) to a path outside the upload paths should get 403, and requests to your upload paths should pass. --http1.1 is required for the HTTP/1.1 test: curl uses HTTP/2 over https by default and does not send Transfer-Encoding over HTTP/2. The counter appears on the Action Hits tab of the vService dashboard.
Caution: A Block action with no condition selected applies to every request to the vService. List all upload paths completely and try the rule on a non-production vService first.
2.2 Limit POST requests per client
This rule does not stop a targeted attack: the exploit can work with only a few requests. It does raise the cost of automated tools that try many targets. The rule counts the POST requests of each client IP and blocks the POST requests of a client over the threshold with 429. The block lifts by itself when the counter drops below the threshold.
A. Create the counter action (Load Balancer → Actions → Add)
- Enter an Action Name, Action Type = Advanced Traffic Inspection, Fields to Track = Client IP address, Traffic Tag = for example
post-rate(3-20 characters; letters, digits,-,_), Tracking Period = 1 minute. - In Conditions, select the predefined If HTTP method is POST condition and save with Add. Only POST requests are then counted.
B. Create the threshold condition (Load Balancer → Conditions → Add)
- Criteria = Tracking Condition, Tracked Table =
post-rate, Tracking Criteria = HTTP requests, and the threshold with Tracking Operator (for example> 100). Save with Add.
C. Create the Block action (Load Balancer → Actions → Add)
- Action Type = Block, Execution Level = On Request, Deny Type = Standard, Status Code = 429.
- In Conditions, select the threshold condition from step 3 and If HTTP method is POST in the same condition group (default and). Without the POST condition, the GET requests of a client over the threshold are blocked too. Save with Add.
D. Add the actions to the vService
- In the vService Edit form, in Details → Actions, select the counter action first and the Block action second, and click Save. Actions run in list order.
Verify: On the vService Logs & Tracking tab, select the counter action's tracking table in the Logs Type list; POST counters per client are shown. Set the threshold from your application's normal traffic: observe the POSTs per minute of legitimate clients (for example systems using an API, or organizations behind a shared outbound IP) in the table and set the threshold above them.
2.3 Set L7 DDoS protection to Active
If Bot/DDoS protection is in your license, Source IP Request Protection under L7 DDoS Protection limits the total number of requests a single source address can make in a period. Unlike 2.2, it counts all requests and needs no extra rule.
- In the vService Edit form, select L7 DDoS & Threat Protection under Details and click Save (if it is not on). When protection is turned on, L7 DDoS Protection starts in Monitor mode; in this mode limit violations are only recorded as events.
- On Left Monitor Panel → Bot/DDoS Protected vServices → vService → Bot/DDoS Management, click the Edit link on the L7 DDoS Protection card.
- Set DDoS Protection = Active and save with the Edit button.
- On the card, click the pencil icon of the Source IP Request Protection block. Set Time Window (default 10 seconds), Request Limit (default 1000) and Limit Action (default Show Captcha; Block can also be selected) for your application's traffic and save with the Edit button.
Caution: Watch the events in Monitor mode for a while before switching to Active. Repeat the same observation when you lower the Request Limit.
Check whether you were targeted
See Detection and Monitoring. Exploitation attempts were reported before public disclosure, so review logs from October 17, 2026 onward.
What a WAF Can and Cannot Do
| A WAF can | A WAF cannot |
|---|---|
| Block known request shapes, such as the session upload progress field | Fix the vulnerable code inside PHP |
| Limit body size, upload paths and request rates | Measure memory use inside the PHP process |
| Block uploads on paths that do not need them | See requests that reach your server without passing through it |
| Record blocked and rate-limited requests | Undo code that already ran on the server |
WAF rules buy time for the update; the lasting fix is updating PHP. For these protections to work, all traffic to your PHP applications must pass through TR7 WAF-WAAP.
Detection and Monitoring
In TR7
- On the Event Logs screen of each WAF-protected vService, filter the records by your custom rules and look at the matched field and score.
- On the same screen, review the requests blocked by the body size and unparsed body rules.
- If you applied the additional measures, watch the load balancer rule counters on the Action Hits tab of the vService dashboard, and the clients that hit the POST rate limit in the tracking table on the Logs & Tracking tab.
On your servers
- Search the PHP error logs for errors such as
Allowed memory size ... exhausted, worker crashes and repeated HTTP 500 responses; pay attention to those that come right after largemultipart/form-datarequests. - Check responses for unusually large or malformed
PHPSESSIDcookies. - Check web roots for new or changed files, and look for unexpected processes started by the web server user, new cron jobs and unexpected outbound connections.
FAQ
No. TR7 appliances have no PHP component that processes HTTP requests, so TR7 products are not affected by these vulnerabilities. See Is TR7 Affected?.
No WAF can fully protect against these vulnerabilities. TR7 WAF-WAAP reduces the attack surface and blocks known attack paths; updating PHP is the only complete fix.
Use the two custom rules in TR7 WAF-WAAP 1.2 against PHP2Shell; they apply to all WAF-protected vServices immediately.
No. The vulnerabilities are in the PHP runtime. Update PHP itself, or ask your hosting provider to do it.
They can. Body size limits, upload blocking and the custom rules may affect legitimate uploads and forms. For WAF rules, start in Monitor mode, review Event Logs, then switch to Blocking mode. Try load balancer rules (2.1, 2.2) on a non-production vService first.
Update History
- Oct 23, 2026 Initial publication.
References
- PHP Security Team announcement: php.net/archive/2026.php
- GHSA-w8hw-w9fx-j79w (CVE-2026-109618): github.com/php/php-src
- GHSA-6wmf-4rv5-p3rp (CVE-2026-109619): github.com/php/php-src
- CVE-2026-109618: cve.org
- CVE-2026-109619: cve.org
- CISA Known Exploited Vulnerabilities Catalog: cisa.gov
- TR7 Documentation: docs.tr7.com
Need help applying these settings?
The TR7 Support Team can review your WAF configuration and help you deploy these protections. Contact your TR7 representative or the TR7 Support Team at support@tr7.com.