The Attacker Wrapped Its Output in Delimiters: Unit 42 Puts an Agentic Operator Inside a PHP2Shell Breach

Unit 42’s PHP2Shell threat brief has been revised four times since 21 October. The fourth revision is the one that matters. Its own changelog line reads: “Updated October 23, 2026, at 12:30 p.m. PT to add details on agentic AI post-exploitation activity and Managed Threat Hunting queries.” Behind that sentence is the most specific account published so far of an AI-driven operator working inside a real breach of CVE-2026-109618 and CVE-2026-109619 — and, unusually, a description of how the responders knew.

We read the updated brief first-hand, in full, including both published hunting queries. This is a different story from the ones we have already covered: the patch release, the exploitation that predated disclosure, the appliance-firmware spread and Cisco’s product impact. This one is about what happened after the shell.

Two hours from web shell to the directory’s MFA secrets

Unit 42 states that its researchers “observed attackers using agentic AI attack platforms for post-exploitation activity.” In one case the target was a government entity in Europe, and the brief gives the clock: within two hours of the initial exploitation the attackers had successfully accessed password hashes and multi-factor authentication secrets. They also established an NTLM-relay tunnel into Active Directory and attempted Domain Admin privilege escalation.

Note what is and is not remarkable there. The techniques are entirely conventional — web shell, local recon, credential material, NTLM relay, escalation attempt. Any competent human operator runs the same chain. What has changed is the interval. Two hours from an unauthenticated request against a PHP worker to the credential store of a government directory is not a sophistication claim; it is a tempo claim, and tempo is the thing an incident-response rota is built around.

The second-order detail is the one defenders should sit with: MFA secrets, not just hashes. Password hashes are a known quantity — crack them, relay them, rotate them. Multi-factor seeds are the control that is supposed to still be standing after the hashes are gone. If they were read, remediation is not a password reset; it is a re-enrolment of every affected second factor, which is a far larger operational and political undertaking inside a government body than forcing new passwords. Unit 42 does not say which secrets, from which store, or whether the escalation attempt succeeded, and we are not going to guess.

The tell: machine-parseable output

The attribution argument is published in plain text, which is rarer than it should be. Unit 42 writes that it observed the attacker enumerating the compromised endpoint and that “the commands and behavioral markers used in the attack are strong indicators of an agentic attacker.” Three markers are named:

  • Section-header delimiters around each command batch, given as ==SHELLUSER== and ==PASSWD==. Unit 42’s own explanation: these “produce machine-parseable output for an AI model to read.”
  • Short, serially spaced tasks rather than one long chained command line.
  • Quick pivots after failures — no pause, no re-reading, straight to the next approach.

The delimiters are the interesting artefact because of who they are for. A human at a web shell reads cat /etc/passwd output with their eyes; the framing is irrelevant. Wrapping every batch in a start marker and an end marker is what you do when something downstream has to split a noisy stream into labelled fields before handing it to a model with a fixed context budget. The operator did not add structure for themselves. They added it for the harness. That is our reading of the marker, not a Unit 42 statement — but it is the reading the brief’s own sentence invites.

It also tells you how much weight the marker can carry. A delimiter convention is a line of prompt scaffolding. It costs an operator nothing to change it, randomise it, or drop it for inline JSON. Treat ==PASSWD== as a lead that is true today and brittle tomorrow; the durable signals in Unit 42’s list are the behavioural two — granularity and recovery latency — because those are properties of the control loop rather than of its formatting.

The brief’s Figure 1 is captioned “Recon commands executed via web shell by an agentic attacker” and shown as a Cortex XDR flow. The image did not render for us; its accompanying description sets out a multi-step sequence covering reconnaissance of an SQL database, password storage, LDAP configuration files and hunting a domain controller for administrator accounts. We carry that as the figure’s description rather than as text we read in the diagram itself.

The query catches the actions, not the author

The same update shipped two XQL hunting queries, and reading them against the prose above produces the sharpest finding of this story. The larger query is 117 lines and it does not look for ==SHELLUSER==, ==PASSWD==, command granularity, or inter-command timing. It contains no agentic signal at all. Unit 42 says so itself about scope: “This hunting query is not specific to CVE-2026-109618 and CVE-2026-109619. It is capable of identifying exploitation of various web application vulnerabilities.”

What it actually is, is a well-built generic model of post-exploitation under a web worker. It anchors on a PHP or web-server process as parent or causality actor — apache2, httpd, php-fpm, php-cgi, frankenphp, lsphp-family, LiteSpeed, or a shell under w3wp.exe, or the service account outside an interactive login — then scores a set of named signals: recon, download, staging, writable_exec, revshell, pipe_to_shell, encoded, persistence, interpreter, cred_access. Three of those fire standalone; otherwise it wants three distinct recon tools in a one-hour bucket, or one recon tool plus a follow-on signal. It is a good query, and it is an action detector.

So the honest summary is: the agentic attribution is an incident-response observation, and the shipped detection logic catches what the operator did, not what was driving it. That is a reasonable engineering choice — a behavioural marker that is cheap to change is a poor thing to hard-code into customer hunting content — but it means nobody should read “Unit 42 published agentic detections” into this release. They published agentic findings and generic detections. The gap is ours to notice, not theirs to apologise for.

One incidental detail in the query is worth a defender’s attention on its own. The benign-exclusion list is effectively an inventory of what legitimately spawns processes under a PHP worker: Nagios plugins, cPanel, Plesk, DirectAdmin, ISPConfig, Virtualizor, phpsysinfo, LibreNMS, Zabbix, Phusion Passenger spawn helpers, and richdocumentscode. That last one is the Collabora Online built-in CODE server — the same component behind CVE-2026-110447, which CISA added to its Known Exploited Vulnerabilities catalogue on 23 October. One of the things you must suppress to hunt PHP post-exploitation cleanly is itself a currently-exploited PHP RCE. Tune that exclusion deliberately rather than inheriting it.

The other two numbers in the brief

Unit 42 states that at the time of publication Cortex Xpanse telemetry identified over 22.6 million exposed instances potentially vulnerable to the two CVEs. That is a vendor exposure estimate derived from internet-wide scanning, not a count of confirmed-exploitable systems, and the brief words it that way. It also repeats, from earlier revisions, that at least one European government has taken a website offline as a precaution — which is a separate statement from the compromise described above, and the brief does not link the two.

The second number is a date. Palo Alto says its Advanced Threat Prevention Plus with Frontier Virtual Patching has blocked the attacks since 10:21 p.m. PT on 20 October 2026 via Threat ID 543004, with conventional Advanced Threat Prevention signatures following on 21 October. The PHP project’s fixed releases went out on 21 October. A network-layer block that precedes the upstream patch by hours is consistent with what we documented in our piece on exploitation preceding disclosure: by the time the advisory was public, both sides had been working the bug for a while.

Where this sits in the pattern

This is now the fourth independent incident-response account we have covered in which the post-exploitation phase was run by a model rather than a person: Sysdig’s Marimo intrusion, the DIVD breach, Unit 42’s own BUGSTER reporting, and now this. Set against the ARTEX operator dossier and Microsoft’s machine-speed attribution work, the shape is consistent and unglamorous: the agent is not finding novel techniques, it is removing the idle time between known ones. The DIVD case was described as loud and messy; this one left a formatting convention in the command history. Agentic operators are currently noisier than good human ones, not quieter — which is a window, and windows close.

What to do with this

  • Patch, then assume credentials moved. If a PHP front end of yours was exposed and unpatched between 20 and 21 October, a cleaned web shell is not containment. The published case reached hashes and second-factor secrets in two hours; scope your response to the directory, not the web server.
  • Treat MFA seed material as rotatable inventory. Know, before you need to, which store holds your second-factor secrets, who can read it, and what re-enrolling every user actually costs you in days. Most organisations have a password-reset runbook and no seed-rotation runbook.
  • Hunt the NTLM-relay leg specifically. The relay tunnel into Active Directory is the step that turns a compromised web host into a directory problem. It is also well-instrumented, and it is not a new technique — the detection you already have for it is still the right one.
  • Run the action-level query; log the author-level markers. Unit 42’s scoring query is worth adapting to whatever telemetry you have. Separately, if you retain web-shell command history, it is cheap to grep for symmetric ==MARKER== framing and for bursts of single-purpose commands with sub-second gaps. Low yield, near-zero cost, and the only way you will ever build a baseline for this.
  • Review your benign-exclusion lists for KEV entries. Anything you suppress under a web worker is a place an attacker can stand. richdocumentscode is the worked example this week.

Verification note: Unit 42’s “Threat Brief: Critical Vulnerabilities in PHP: CVE-2026-109618, CVE-2026-109619 (Updated October 23)” was read first-hand and in full, including both XQL hunting queries, the product-protection section and all four dated update notices. Every quoted phrase — the agentic post-exploitation paragraph, the two-hour timeline, the delimiter explanation, the query scope caveat, the 22.6 million figure and the 10:21 p.m. PT 20 October protection date — is taken directly from that page. The Figure 1 image did not render in our retrieval; its content is carried strictly as the figure’s caption and accompanying description, and we do not quote any command from the diagram. We did not contact Palo Alto Networks, did not use any Cortex or Xpanse product, and did not run, adapt or test either hunting query against any live telemetry. No exploit, proof of concept or reproducer for either CVE was written, obtained or run; no PHP deployment, appliance or third-party system was contacted or tested; no indicator was resolved. Unit 42 does not name the affected government entity and neither do we. The reading of the delimiter convention as harness scaffolding, the observation that the published query contains no agentic signal, the brittleness argument about formatting markers, the MFA-seed remediation point and the exclusion-list observation about richdocumentscode are our analysis and are labelled as such. The 22.6 million figure is Palo Alto Networks telemetry and an exposure estimate, not a confirmed vulnerable count. Brave Search was used for discovery only; the primary source was then fetched and read directly.

Sources: