Insights / Threat Brief / 22 Oct 2026 · Morning

Threat Brief • 22 October 2026 • Morning Edition

PHP2Shell Was Attacked Before It Was Fixed, and Ransomware Crews Ride a Patched VPN Flaw Into the Hypervisor: GlobalProtect, PHP and Three Supply-Chain Trust Breaks, With Hunts You Can Run Today

Ransomware operators are using a GlobalProtect authentication bypass Palo Alto disclosed in May to get inside; in one case Unit 42 investigated, they reached vCenter, switched off an ESXi safeguard and dumped domain credentials from a virtual disk. Plus: two critical PHP remote-code-execution flaws were being tried against Amazon's honeypots four days before PHP's fix, a hijacked account swapped OVHcloud CLI release binaries for a secret-stealer, eight eMudhra certificate-authority keys were compromised, a search-ad phishing campaign is turning Google Cloud billing accounts into someone else's AI budget, and six more flaws joined CISA's catalog, three of them due this Friday and three on 3 November.

By Fezz · Threat Vector Management · October 22, 2026

Research, fact-checking and graphics support by Claude (Anthropic)

: added Akamai and AWS WAF coverage for PHP2Shell to the WAF vendors section (Akamai rule 3000991).

: added Azure WAF, Google Cloud Armor and Imunify360 (CloudLinux) coverage to the same WAF vendors section.

: added F5 coverage and a Barracuda line (no advisory found) to the same section.

: IP addresses now use two brackets instead of three (for example 203.0[.]113[.]7); remove the brackets before use. The audio narration will be refreshed shortly.

Status as of publication on Thursday, 22 October 2026, US Eastern. Item 1 has exploitation attempts reported by Amazon and watchTowr; item 2 is a confirmed, ransomware-linked campaign; item 6 lists flaws CISA confirms are exploited. Items 3 and 5 are confirmed compromises of a software release and of cloud accounts; item 4 has no reported exploitation. Where anything here differs from a vendor's own advisory to you, follow the advisory.

BLUF

Bottom Line Up Front

How to read this. The table below gives every fix and the most huntable indicators. Each item opens with its own bottom line and indicator table, and closes with a hunt pack. Items are ranked by consequence if they reach you, not by likelihood. Reported facts are cited; priority, PIVCCERL™ staging, hunt logic and indicators marked ours are our analysis.

At a glance: fixes and indicators

Written for organizations and the teams who defend them. IoC = evidence it already happened (an address, an account, a log line). IoA = the behavior of an attack in progress. Network IoCs are defanged: remove the square brackets before using them. Indicators age fast, so re-check the source before blocking.

Item Exploited? · Fix Do now Top IoCs Top IoAs
1. PHP2Shell CVE-2026-109618 / -109619 Yes: attempts since 17 Oct (Amazon), active attempts (watchTowr); not in CISA's catalog as of 2026.10.21 · 8.5.12, 8.4.27, 8.3.36, 8.2.35 Update every PHP runtime and restart workers; hunt web logs back to 17 Oct 103.216[.]220[.]92, 134.209[.]159[.]64 (Amazon: shared infrastructure, investigate) "Allowed memory size … exhausted" "in Unknown on line 0"; PHP_SESSION_UPLOAD_PROGRESS in multipart uploads; PHP workers starting /bin/sh
2. Palo Alto GlobalProtect CVE-2026-0257 Yes, ransomware-linked (Unit 42); CISA catalog since 29 May · fixed builds per branch Test management ports 4443 and 3879 from outside; check ESXi execInstalledOnly; confirm Veeam is fixed 146.19[.]216[.]119, 179.43[.]172[.]213; host IDs WINDOWS-LAPTOP-001, DESKTOP-GP01 ESXi execInstalledOnly turned off; vCenter logins from the VPN pool
3. OVHcloud CLI release binaries Yes, release assets replaced 19 Oct · v0.16.0 Find the CLI on workstations and build hosts; rotate secrets if an affected binary ran Replaced binary SHA-256 3833daff…933cb; build revision 5ead8ef9b43d…; ~/init.json Release-binary build info showing vcs.modified=true / +dirty
4. eMudhra intermediate CAs Keys compromised; no misissued certificate seen in CT logs (Chrome) · Go 1.27.3 / 1.26.10, NSS 3.131.1, Firefox 158.0.1 Rebuild Go programs; update CA bundles None published Ours: a TLS chain through EM … TLS CA - G3B/G3C on your network
5. Google Cloud LLMjacking Yes, multiple intrusions (Wiz) · not a software flaw Audit billing-account members and the iam.allowedPolicyMemberDomains policy 212.73[.]134[.]136; gboogl[.]com, groosl[.]com SetOrgPolicy removing the domain restriction; Gmail accounts given roles/billing.admin
6. CISA catalog: Plex, Siemens, SiteGuard Yes (CISA, added 20 Oct) · vendor fixes Patch by 23 Oct (three CVEs) and 3 Nov (three CVEs) None published in the catalog Requests to /video/:/transcode/universal carrying a full URL

Highest payoff today — analysis. Item 2. It is the only item where a defender who patched months ago can still be inside an active intrusion, and the two checks that answer the question — an outside connection attempt to two ports, and one ESXi setting per host — take minutes.

How to use this. A published-IoC hit means compromise: handle it under the item's defined response. An IoA hit alone is a lead to validate (PIVCCERL™'s Validation stage). An empty IoC row is not reassurance. The hunt packs say what to do on a hit and what a clean result means.

1. PHP2Shell: two critical PHP flaws were attacked before the fix, and the fixes are out

Bottom line

Bottom line. PHP released 8.5.12, 8.4.27, 8.3.36 and 8.2.35 on 21 October to fix CVE-2026-109618 and CVE-2026-109619, two flaws that "can allow unauthenticated remote code execution" (CVSS 4.0 9.2 each).

  • PHP says every installation serving web requests is at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, with the risk highest for mod_php.
  • Amazon saw a first exploitation attempt against its honeypots on 17 October, four days before disclosure, and more from several sources on 21 October; watchTowr reports "active exploitation attempts of both" flaws. Neither flaw was in CISA's catalog as of version 2026.10.21.
  • Amazon says to start any investigation from 17 October, not the disclosure date.
  • Do now: update every PHP runtime to the fixed release for its branch, or the vendor's backported package, and restart every worker; for PHP 8.1 and older, get a vendor backport or take the site off the internet; then hunt web logs back to 17 October.
  • Skip if: you run no PHP anywhere, including inside products and platforms you host.
Five-step path from one unauthenticated web request to code execution on a PHP server. 5 steps. Step 1, The request. An unauthenticated POST with a multipart upload; the session upload-progress field (PHP_SESSION_UPLOAD_PROGRESS) is one confirmed path, not the only one (watchTowr, Amazon). Holds: nothing yet. (reported). Step 2, The fault. Request startup hits a memory-limit failure while request data is half-initialized (CVE-2026-109618), or reads state a previous request left behind (CVE-2026-109619) (PHP). Holds: corrupted interpreter state. (reported). Step 3, Code execution. Cleanup or the next request uses the corrupted state; on Apache mod_php this was demonstrated before any application code runs (PHP). Holds: code running as the web server user. (reported). Step 4, The shell. Not yet reported as observed: Fastly tells defenders to watch for a mod_php worker running /bin/sh -c as a child process. Holds: a command shell on the server, if it happens. (not yet reported). Step 5, What follows. Not yet reported by any source. watchTowr tells defenders to check for new web shells, unexpected cron jobs or newly created accounts tied to PHP processes. Holds: whatever the web server user can reach. (not yet reported). Five-step path from one unauthenticated web request to code execution on a PHP server. Steps 1 to 3 are as PHP, Amazon and watchTowr describe them; steps 4 and 5 are what defenders are told to look for, not observed events. 1 The request. An unauthenticated POST with a multipart upload; the session upload-progress field (PHP_SESSION_UPLOAD_PROGRESS) is one confirmed path, not the only one (watchTowr, Amazon). Holds: nothing yet. 2 The fault. Request startup hits a memory-limit failure while request data is half-initialized (CVE-2026-109618), or reads state a previous request left behind (CVE-2026-109619) (PHP). Holds: corrupted interpreter state. 3 Code execution. Cleanup or the next request uses the corrupted state; on Apache mod_php this was demonstrated before any application code runs (PHP). Holds: code running as the web server user. 4 The shell. Not yet reported as observed: Fastly tells defenders to watch for a mod_php worker running /bin/sh -c as a child process. Holds: a command shell on the server, if it happens. 5 What follows. Not yet reported by any source. watchTowr tells defenders to check for new web shells, unexpected cron jobs or newly created accounts tied to PHP processes. Holds: whatever the web server user can reach.
Updating PHP and restarting every worker stops step 2. Blocking multipart uploads and turning off upload progress close only the confirmed paths into step 1. Nothing here helps a server attacked from 17 October onward: that needs the hunt. Solid blue boxes are reported steps; dashed orange boxes are not yet reported. The diagram is our analysis.

Indicators

Type Indicator Where to look Source
IoC 103.216[.]220[.]92 (17 Oct); 31.223[.]184[.]166, 37.19[.]200[.]5, 134.209[.]159[.]64, 103.114[.]163[.]188, 95.217[.]98[.]37 (21 Oct) — sources of exploitation attempts against Amazon's honeypots. Amazon says these are shared anonymization infrastructure: investigate hits, do not just block Web server, proxy, WAF and firewall logs from 17 October Amazon Threat Intelligence
IoC No hashes, payloads or domains published — Amazon, watchTowr, PHP, Fastly (checked 22 Oct, ~13:35 UTC)
IoA URL-encoded form POSTs above 1–2 MB, or bodies starting with = followed by a field name of repeated [ characters Web server, proxy or WAF logs Fastly
IoA POST multipart uploads containing PHP_SESSION_UPLOAD_PROGRESS; unexpectedly large PHPSESSID values in responses Web server, proxy or WAF logs Amazon, Fastly (upload field); Imperva, Wiz (PHPSESSID)
IoA "Allowed memory size … exhausted" with the location "in Unknown on line 0"; bursts of Apache AH00052 "exit signal Segmentation fault (11)" PHP and Apache error logs Fastly
IoA A mod_php, php-fpm, php-cgi, httpd or apache2 worker starting /bin/sh or a downloader EDR process events Fastly; Huntress

What

So what

Now what — P → I (analysis)

Hunt pack — run it, then act on what it says

No indicators of compromise have been published, so these hunts implement the behaviors Fastly and Huntress published (memory-exhaustion and segfault log lines, web-server or PHP processes starting shells and downloaders); the first Datadog query adds Amazon's six addresses and the upload-progress field for web, proxy or WAF logs plus a runtime inventory; the logic is our analysis. The php parent and the dash, python3 and ncat children are our additions. The bash script was executed against synthetic process tables (a PHP-FPM worker with a shell child, a clean table, an empty file and bad arguments). It exits 1 whenever any PHP runtime is present, so each listed runtime should be checked against the fixed versions. The Sigma, KQL and Datadog queries were reviewed, not executed. We are not offering a YARA or Suricata rule: no exploit strings have been published, and the request patterns depend on body size, which a signature handles poorly. The Sigma rule converts with pySigma to Splunk, Kusto and Lucene. Adjust field and table names to your logging.

bash — Linux host: PHP inventory and process lineage; executed against synthetic data
#!/usr/bin/env bash
# Read-only. Lists PHP runtimes on this host and flags web-server or PHP processes
# with shell or downloader children (Huntress guidance). Optional arg: a saved
# 'ps -eo pid,ppid,comm' file to read instead of the live process table.
# Exit: 0 no PHP, no suspicious lineage | 1 PHP present or suspicious lineage | 2 usage | 3 nothing readable
[ $# -le 1 ] || { echo "usage: $0 [ps-snapshot]" >&2; exit 2; }
php_found=0
for b in $(compgen -c 2>/dev/null | grep -E '^php(-fpm|-cgi)?[0-9.]*$' | sort -u); do
  p=$(command -v "$b") || continue; v=$("$p" -v 2>/dev/null | head -1)
  echo "php runtime: $p ${v:-version unreadable}"; php_found=$((php_found+1)); done
if [ $# -eq 1 ]; then [ -r "$1" ] && [ -s "$1" ] || { echo "unreadable or empty: $1" >&2; exit 3; }; PS=$(cat "$1"); else PS=$(ps -eo pid=,ppid=,comm= 2>/dev/null); fi
[ -n "$PS" ] || { echo "process table unreadable" >&2; exit 3; }
sus=$(awk 'NR==FNR{name[$1]=$3; next} ($3 ~ /^(sh|bash|dash|cmd|powershell|python[0-9.]*|perl|curl|wget|nc|ncat|certutil)$/) && (name[$2] ~ /^(php-fpm[0-9.]*|php-cgi|php|httpd|apache2)$/) {print "suspicious: pid " $1 " " $3 " child of " name[$2] " (ppid " $2 ")"}' <(echo "$PS") <(echo "$PS"))
[ -n "$sus" ] && echo "$sus"; n=$(printf '%s' "$sus" | grep -c . )
echo "php_runtimes=$php_found suspicious_children=$n"
[ "$n" -gt 0 ] || [ "$php_found" -gt 0 ] && exit 1; exit 0
Sigma — process creation (validated with pySigma; reviewed, not executed)
title: Shell or downloader spawned by PHP or web server process
id: 6b1f7c2e-4a8d-4b55-9f3e-2d7c1a9e5b40
status: experimental
description: Behavioral lead from Huntress and Fastly guidance for CVE-2026-109618 / CVE-2026-109619. Validate against known application behavior.
references:
  - https://www.huntress.com/blog/php2shell-leaked-critical-php-vulnerabilities
  - https://www.fastly.com/blog/fastlys-proactive-protection-critical-php-rce-cve-2026-109618
logsource:
  category: process_creation
  product: linux
detection:
  parent:
    ParentImage|endswith: ['/php-fpm', '/php-cgi', '/httpd', '/apache2', '/php']
  child:
    Image|endswith: ['/sh', '/bash', '/dash', '/python', '/python3', '/perl', '/curl', '/wget', '/nc']
  condition: parent and child
level: high
KQL — Microsoft Defender XDR advanced hunting, DeviceProcessEvents (reviewed, not executed)
DeviceProcessEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName matches regex @"^(php-fpm[0-9.]*|php-cgi(\.exe)?|php(\.exe)?|httpd(\.exe)?|apache2)$"
| where FileName in~ ("sh","bash","dash","cmd.exe","powershell.exe","python","python3","perl","curl","wget","nc","certutil.exe")
   or ProcessCommandLine has_any ("/dev/tcp/","fsockopen","mkfifo")
| project Timestamp, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine
Datadog Logs — web, proxy or WAF logs: Amazon's addresses (remove the brackets; attribute names vary by integration; reviewed, not executed)
@network.client.ip:(103.216[.]220[.]92 OR 31.223[.]184[.]166 OR 37.19[.]200[.]5 OR 134.209[.]159[.]64 OR 103.114[.]163[.]188 OR 95.217[.]98[.]37) OR *:"PHP_SESSION_UPLOAD_PROGRESS"
Datadog Logs — PHP and Apache error logs (Fastly's published log lines; reviewed, not executed)
(*:"Allowed memory size" *:"Unknown on line 0") OR (*:"AH00052" *:"Segmentation fault")
Datadog Logs — process or audit logs from an endpoint agent (field name varies by integration; reviewed, not executed)
(*:"php-fpm" OR *:"php-cgi" OR *:"apache2" OR *:"httpd") (*:"/dev/tcp/" OR *:"fsockopen" OR *:"mkfifo")
If you see Do this
A PHP or web-server process starting a shell or downloader that the application does not normally run Confirmed compromise under the defined response: isolate, preserve the web root and logs, rotate secrets, rebuild patched.
A shell child that matches a known job (an admin script, a cron wrapper) Expected. Record it as an exception with an owner, so the next hit stands out.
PHP runtimes listed by the script Check each against 8.5.12, 8.4.27, 8.3.36 or 8.2.35; anything older is unpatched.
The script exits 3, or the EDR in use does not record parent processes This is not a clean result. Fix the telemetry before relying on it.
Memory-exhaustion lines "in Unknown on line 0" or AH00052 segfault bursts with no shell child Attempts, or an exploit that failed. Confirm the update is in place and look for new files in the web root.
A request from one of Amazon's addresses Shared anonymization infrastructure, so not proof on its own. Check what it requested and the server's error log at that minute; a matching memory or segfault line or a shell child makes it a confirmed compromise.
No hits A good sign, not an exoneration. Amazon published six addresses from shared infrastructure, so attackers elsewhere are invisible to this search; application logs may show nothing because the flaws run before application code; a payload that runs inside PHP never starts a child process; and new variants are expected. Patch anyway.

2. Palo Alto GlobalProtect: ransomware crews are using a May flaw to reach the hypervisor

Bottom line

Bottom line. Unit 42 updated its CVE-2026-0257 threat brief on 19 and 20 October: Qilin and Inc ransomware operators use the GlobalProtect authentication bypass to get a VPN session.

  • In one case it investigated, they then moved to vCenter, disabled an ESXi safeguard and dumped domain credentials from a domain controller's virtual disk.
  • CISA added the flaw to its catalog on 29 May and marks ransomware use as known; Palo Alto published its advisory on 13 May.
  • Unit 42 also found management interfaces exposed on ports 4443 and 3879 through GlobalProtect profiles, a recurring misconfiguration Unit 42 saw in its incident-response engagements.
  • Do now: test the management IP on ports 4443 and 3879 from outside your network; check every ESXi host's execInstalledOnly setting; confirm the GlobalProtect fix and the Veeam fix for CVE-2023-27532 are in place; hunt the indicators below.
  • Skip if: you run no PAN-OS GlobalProtect portal or gateway and no Prisma Access. Palo Alto says only portals and gateways with authentication override cookies enabled are affected; check before skipping the hunt.
Five-step path from a GlobalProtect authentication bypass to domain credentials, as Unit 42 reported it. 5 steps. Step 1, VPN session. The attacker uses CVE-2026-0257 against an unpatched GlobalProtect portal or gateway and bypasses MFA to establish a VPN session. Holds: a session on the internal network. (reported). Step 2, Reconnaissance and movement. Dual-use remote-management tools for reconnaissance; lateral movement over RDP and SMB. Holds: footholds on internal hosts. (reported). Step 3, Hypervisor. A pivot from the VPN gateway to a vCenter appliance; execInstalledOnly disabled on ESXi hosts. Holds: control of the virtualization layer. (reported). Step 4, Credentials. Offline credential dumping directly against a domain controller's virtual disk (VMDK), out of reach of in-guest EDR. Holds: domain credentials. (reported). Step 5, Backups and ransomware. Access chained with Veeam CVE-2023-27532; tools staged for exfiltration and ransomware. Holds: backups and the ability to encrypt. (reported). Five-step path from a GlobalProtect authentication bypass to domain credentials, as Unit 42 reported it. 1 VPN session. The attacker uses CVE-2026-0257 against an unpatched GlobalProtect portal or gateway and bypasses MFA to establish a VPN session. Holds: a session on the internal network. 2 Reconnaissance and movement. Dual-use remote-management tools for reconnaissance; lateral movement over RDP and SMB. Holds: footholds on internal hosts. 3 Hypervisor. A pivot from the VPN gateway to a vCenter appliance; execInstalledOnly disabled on ESXi hosts. Holds: control of the virtualization layer. 4 Credentials. Offline credential dumping directly against a domain controller's virtual disk (VMDK), out of reach of in-guest EDR. Holds: domain credentials. 5 Backups and ransomware. Access chained with Veeam CVE-2023-27532; tools staged for exfiltration and ransomware. Holds: backups and the ability to encrypt.
Patching or mitigating GlobalProtect stops step 1 only. Steps 3 to 5 are stopped by vCenter access limits, execInstalledOnly enforcement, and a fixed, isolated Veeam server. Solid blue boxes are reported steps; dashed orange boxes are not yet reported. The diagram is our analysis.

Indicators

Type Indicator Where to look Source
IoC 23.128[.]228[.]6, 104.207[.]144[.]154, 146.19[.]216[.]119, 146.19[.]216[.]120, 146.19[.]216[.]125, 179.43[.]172[.]213, 185.195[.]232[.]139, 198.12[.]106[.]60, 202.144[.]192[.]47 — source addresses from activity before the 29 May proof-of-concept; Unit 42 says to look for successful logins from them GlobalProtect logs (successful gateway-connected events) Unit 42
IoC Host IDs WINDOWS-LAPTOP-001, DESKTOP-GP01, GP-CLIENT; MAC addresses aa:bb:cc:dd:ee:ff, 00:11:22:33:44:55 — search gateway-connected events from any address GlobalProtect logs Unit 42
IoC endpoint_os_version "Microsoft Windows 10 Pro 64-bit" with an empty source_user_info.domain — values hard-coded in the public proof-of-concept GlobalProtect logs (treat as a lead: real clients can share the OS string) Unit 42
IoA execInstalledOnly disabled on an ESXi host; vCenter logins from the VPN address pool ESXi host settings and logs; vCenter events Unit 42 (behavior); ours (where to look)
IoA Offline access to a domain controller's VMDK (datastore browse, copy or snapshot of the DC disk) vCenter tasks and events; datastore access logs Unit 42 (behavior); ours (where to look)
IoA A successful connection to the firewall's management IP on port 4443 or 3879 from outside External test; firewall traffic logs Unit 42

What

So what

Now what — P → I (analysis)

Hunt pack — run it, then act on what it says

These hunts implement Unit 42's published indicators (addresses, host IDs, MAC addresses and proof-of-concept log values) and the ESXi behavior it describes; the logic is our analysis. The bash script was executed against synthetic logs (a hit, a near-miss address, a host-ID hit, a compressed log, an empty file and no arguments). The Sigma rule (Unit 42's addresses and host values, against a generic firewall log source) and the KQL, SPL and Datadog queries were reviewed, not executed. We are not offering a Suricata rule: the activity is inside an encrypted VPN session. The Sigma rule converts with pySigma to Splunk, Kusto and Lucene. Adjust field and table names to your logging.

bash — GlobalProtect log exports (text, CSV or .gz); executed against synthetic data
#!/usr/bin/env bash
# Read-only. Usage: panos.sh <globalprotect-log-export>... (text, csv or .gz)
# Exit: 0 scanned, none found | 1 found | 2 usage | 3 nothing readable
[ $# -ge 1 ] || { echo "usage: $0 <gp-log-export>..." >&2; exit 2; }
IOC='23.128[.]228[.]6 104.207[.]144[.]154 146.19[.]216[.]119 146.19[.]216[.]120 146.19[.]216[.]125 179.43[.]172[.]213 185.195[.]232[.]139 198.12[.]106[.]60 202.144[.]192[.]47'
pat=""; for i in $IOC; do r=$(printf '%s' "$i" | tr -d '[]' | sed 's/\./\\./g'); pat="$pat|(^|[^0-9.])$r([^0-9]|$)"; done
pat="${pat#|}|WINDOWS-LAPTOP-001|DESKTOP-GP01|GP-CLIENT|aa:bb:cc:dd:ee:ff|00:11:22:33:44:55"
scanned=0; hits=0
for f in "$@"; do
  [ -r "$f" ] && [ -s "$f" ] || { echo "unreadable or empty: $f" >&2; continue; }
  case "$f" in *.gz) c="zcat -f";; *) c="cat";; esac
  scanned=$((scanned+1))
  n=$($c "$f" | grep -Eic -- "$pat"); hits=$((hits+n))
  [ "$n" -gt 0 ] && $c "$f" | grep -Ei -- "$pat" | cut -c1-300
done
echo "scanned=$scanned hits=$hits"
[ $scanned -eq 0 ] && exit 3; [ $hits -gt 0 ] && exit 1; exit 0
KQL — Microsoft Sentinel, CommonSecurityLog from PAN-OS (field mapping varies by connector; remove the brackets; reviewed, not executed)
let iocs = dynamic(["23.128[.]228[.]6","104.207[.]144[.]154","146.19[.]216[.]119","146.19[.]216[.]120","146.19[.]216[.]125","179.43[.]172[.]213","185.195[.]232[.]139","198.12[.]106[.]60","202.144[.]192[.]47"]);
let ids = dynamic(["WINDOWS-LAPTOP-001","DESKTOP-GP01","GP-CLIENT","aa:bb:cc:dd:ee:ff","00:11:22:33:44:55"]);
CommonSecurityLog
| where TimeGenerated > ago(180d)
| where DeviceVendor == "Palo Alto Networks"
| where SourceIP in (iocs) or AdditionalExtensions has_any (ids) or Message has_any (ids)
| project TimeGenerated, DeviceName, SourceIP, SourceUserName, Activity, AdditionalExtensions
Sigma — firewall or GlobalProtect logs (generic firewall taxonomy; remove the brackets; validated with pySigma; reviewed, not executed)
title: GlobalProtect activity from Unit 42 CVE-2026-0257 indicators
id: 3c9e2a71-5d84-4f0b-9a6e-81d2c4b7e015
status: experimental
description: Source addresses and hard-coded client values Unit 42 published for CVE-2026-0257 exploitation. A successful login match is a confirmed compromise.
references:
  - https://unit42.paloaltonetworks.com/active-exploitation-of-pan-os-cve-2026-0257/
logsource:
  category: firewall
detection:
  ip:
    src_ip:
      - '23.128[.]228[.]6'
      - '104.207[.]144[.]154'
      - '146.19[.]216[.]119'
      - '146.19[.]216[.]120'
      - '146.19[.]216[.]125'
      - '179.43[.]172[.]213'
      - '185.195[.]232[.]139'
      - '198.12[.]106[.]60'
      - '202.144[.]192[.]47'
  hostid:
    - 'WINDOWS-LAPTOP-001'
    - 'DESKTOP-GP01'
    - 'GP-CLIENT'
    - 'aa:bb:cc:dd:ee:ff'
    - '00:11:22:33:44:55'
  condition: ip or hostid
falsepositives:
  - Real devices named GP-CLIENT; validate the user and device
level: high
Splunk SPL — ESXi syslog (sourcetype assumption: vmw-syslog; reviewed, not executed)
index=* sourcetype=vmw-syslog ("execInstalledOnly" OR "execinstalledonly")
| table _time host _raw
Datadog Logs — PAN-OS firewall or GlobalProtect logs (attribute names vary by integration; remove the brackets; reviewed, not executed)
@network.client.ip:(23.128[.]228[.]6 OR 104.207[.]144[.]154 OR 146.19[.]216[.]119 OR 146.19[.]216[.]120 OR 146.19[.]216[.]125 OR 179.43[.]172[.]213 OR 185.195[.]232[.]139 OR 198.12[.]106[.]60 OR 202.144[.]192[.]47) OR *:"WINDOWS-LAPTOP-001" OR *:"DESKTOP-GP01" OR *:"GP-CLIENT"
If you see Do this
A successful GlobalProtect login from a listed address, host ID or MAC Confirmed compromise. Follow the defined response: isolate hypervisor management, preserve vCenter, ESXi and firewall evidence, reset domain credentials.
Attempts from listed addresses with no successful login Attempts only. Confirm the fix or mitigation is in place and keep the hunt running weekly.
The proof-of-concept OS string on a session from a known employee device Expected for some real clients. Validate the device and user before acting.
execInstalledOnly disabled with no change record Treat as confirmed compromise of the hypervisor layer; start incident response.
The script exits 3, or logs do not reach back to May This is not a clean result. Find older logs or record the gap.
No hits A good sign, not an exoneration. Only Unit 42's published values were searched, the address list covers activity before 29 May, firewall log retention is often shorter than the exposure window, and the VMDK step leaves no trace inside the guest. Close the management ports anyway.

3. OVHcloud CLI: a hijacked account swapped release binaries for a secret-stealer

Bottom line

Bottom line. On 19 October, release binaries of OVHcloud's command-line tool were replaced with a build that, per OVHcloud founder Octave Klaba (translated, as reported by SecurityWeek), was meant to "retrieve secrets from the disk", using a contributor's hijacked GitHub account.

  • The files were downloadable from about 12:47 UTC until OVHcloud deleted them at 14:21 UTC.
  • OVHcloud lists v0.11.0 through v0.15.0 as affected; v0.10.0 and v0.16.0 are clean.
  • Installs through the official install script, Homebrew or a direct GitHub download on macOS, 64-bit Linux and Windows x86_64 are affected; go install, building from source and the Docker image are not.
  • Do now: find the CLI on every workstation and build host; if an affected binary ran, rotate every secret that machine could read, from a different machine; install v0.16.0.
  • Skip if: no one in your organization uses the OVHcloud CLI, or it was only installed with go install, from source or as the Docker image.

Indicators

Type Indicator Where to look Source
IoC SHA-256 3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb — replaced v0.15.0 ovhcloud-cli_Linux_arm64.tar.gz (the original was 5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0) Download folders, package caches, CI artifact stores Issue reporter on OVHcloud's GitHub; OpenSourceMalware
IoC Build info in the replaced binary: vcs.revision=5ead8ef9b43d354dfb5caadff803b11afc8c5c58, vcs.modified=true, a +dirty pseudo-version go version -m <binary> Issue reporter; OpenSourceMalware
IoC Uploader account HassenBF on the replaced release assets GitHub release metadata Issue reporter; OpenSourceMalware
IoC ~/init.json (a macOS throttle marker limiting the loader to about one run every two days), preinstall.js SHA-256 43df42fd79f6f81e530892b54634598770d6e496796a863c596e616bcb3fec70, stage-two SHA-256 0f79989912572a24ba13baabb32b3fd084496271c51448d47b66fe1aedbf293c, Solana dead-drop wallet BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC — from the related loader in the same account's repositories; OpenSourceMalware links it to the CLI case as its own inference Developer machines; npm projects; egress logs OpenSourceMalware
IoA Outbound Solana RPC traffic from a build host or developer workstation that has no reason to make it DNS and proxy logs OpenSourceMalware (recommends blocking it); ours (hunting for it)

What

So what

Now what — P → I (analysis)

Hunt pack — run it, then act on what it says

These hunts implement the hashes, build revision and file marker published by the issue reporter and OpenSourceMalware; the logic is our analysis. The bash script was executed against synthetic files (a binary carrying the revision and modified flag, a clean build, an empty file and no arguments). The Sigma rule (the loader's published preinstall command and the build revision), SPL and Datadog queries were reviewed, not executed. We are not offering a Suricata or YARA rule: no network indicator or byte pattern for the stealer itself has been published, and a rule from a guess would be counted as a control it is not. The Sigma rule converts with pySigma to Splunk, Kusto and Lucene. Adjust field and table names to your logging.

bash — macOS or Linux: files you point it at, plus `~/init.json`; executed against synthetic data
#!/usr/bin/env bash
# Read-only. Usage: ovh.sh <path-to-ovhcloud-binary-or-archive>...  Also checks ~/init.json.
# Exit: 0 scanned, none found | 1 found | 2 usage | 3 nothing readable
[ $# -ge 1 ] || { echo "usage: $0 <file>..." >&2; exit 2; }
BAD="3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb 43df42fd79f6f81e530892b54634598770d6e496796a863c596e616bcb3fec70 0f79989912572a24ba13baabb32b3fd084496271c51448d47b66fe1aedbf293c"
scanned=0; hits=0
for f in "$@"; do
  [ -r "$f" ] && [ -s "$f" ] || { echo "unreadable or empty: $f" >&2; continue; }
  scanned=$((scanned+1)); h=$(sha256sum "$f" | cut -d' ' -f1)
  for b in $BAD; do [ "$h" = "$b" ] && { echo "HIT hash $h $f"; hits=$((hits+1)); }; done
  if grep -aq '5ead8ef9b43d354dfb5caadff803b11afc8c5c58' "$f"; then echo "HIT build revision 5ead8ef9b43d in $f"; hits=$((hits+1)); fi
  if grep -aq 'ovhcloud-cli' "$f" && grep -aq 'vcs.modified=true' "$f"; then echo "LEAD vcs.modified=true in $f (a locally modified build; verify)"; hits=$((hits+1)); fi
done
[ -e "$HOME/init.json" ] && echo "LEAD $HOME/init.json exists (macOS throttle marker per OpenSourceMalware; check its contents and age)"
echo "scanned=$scanned hits=$hits"
[ $scanned -eq 0 ] && exit 3; [ $hits -gt 0 ] && exit 1; exit 0
Sigma — process creation on macOS or Linux (validated with pySigma; reviewed, not executed)
title: OVHcloud CLI compromise - related loader or modified build revision
id: 8f41d6b2-0c37-4e9a-b5d1-6a2e9c7f3b48
status: experimental
description: The npm preinstall loader OpenSourceMalware tied to the hijacked account, and the build revision of the replaced OVHcloud CLI binary. A match is a lead to validate against the hashes in the item.
references:
  - https://opensourcemalware.com/blog/glassworm-hacks-ovh-clouds-cli-tool
  - https://github.com/ovh/ovhcloud-cli/issues/300
logsource:
  category: process_creation
detection:
  loader:
    CommandLine|contains: 'node preinstall.js'
  build:
    CommandLine|contains: '5ead8ef9b43d354dfb5caadff803b11afc8c5c58'
  condition: loader or build
falsepositives:
  - Legitimate npm packages that ship a file named preinstall.js
level: medium
Splunk SPL — EDR file-hash events (field names vary by connector; reviewed, not executed)
index=* (sha256="3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb" OR sha256="43df42fd79f6f81e530892b54634598770d6e496796a863c596e616bcb3fec70" OR sha256="0f79989912572a24ba13baabb32b3fd084496271c51448d47b66fe1aedbf293c")
| table _time host sha256 file_path
Datadog Logs — DNS or proxy logs from build hosts (ours: the Solana lead is our reading of OpenSourceMalware's advice; reviewed, not executed)
@dns.question.name:*solana* [email protected]:*.yourdomain.example
If you see Do this
A hash match or the 5ead8ef9b43d build revision Confirmed compromise under the defined response: isolate, rotate from another machine, review the cloud accounts, rebuild.
vcs.modified=true on an OVHcloud CLI binary with no revision match A lead. Compare the binary's hash against v0.16.0 and treat it as compromised until proven otherwise.
~/init.json on a Mac A lead only: other software can create a file with that name. Read it and check its age.
Solana lookups from a host with a wallet or crypto tooling Expected. Exclude that host by name.
The script exits 3 This is not a clean result. Point it at the actual binary path.
No hits A good sign, not an exoneration. Hashes were published for one replaced file only, the stealer's behavior was never analysed, so what it leaves behind is unknown, and the binary may already have been updated over. If anyone installed v0.11.0 to v0.15.0 from a release on 19 October, rotate anyway.

4. eMudhra: eight intermediate CA keys are compromised

Bottom line

Bottom line. The private keys of eight eMudhra intermediate certificate authorities were compromised; Mozilla received the report on 17 October and browsers blocked the certificates between 17 and 20 October.

  • Chrome found no TLS certificate under the six TLS intermediates logged to Certificate Transparency before its block.
  • Programs that do not check revocation are not covered by browser blocks: Go programs need a rebuild on Go 1.27.3 or 1.26.10, and bundled trust stores need updating.
  • Do now: rebuild Go services on a fixed Go release; update NSS, certifi, webpki-roots and similar bundles; check internal trust stores for the eMudhra root.
  • Skip if: you ship no Go binaries, bundle no CA list and rely only on up-to-date browsers and operating-system trust stores that receive revocation updates.

Indicators

Type Indicator Where to look Source
IoC None published — no misissued certificate was found in Certificate Transparency before the block — The Hacker News, citing Chrome (checked 21 Oct)
IoA A TLS chain through EM DV TLS CA - G3B/G3C, EM OV TLS CA - G3B/G3C, EM EV TLS CA - G3B/G3C, or code signed under EM OV CS CA - G3B/G3C TLS-inspection and proxy logs; code-signing verification logs Ours, built on the certificate names reported by The Hacker News
IoA The roots emSign ECC Root CA - G3 or emSign Root TLS CA - G3 in a bundled CA file Application CA bundles, container images The Hacker News (names); ours (where to look)

What

So what

Now what — P (analysis)

Hunt pack — run it, then act on what it says

No IoCs have been published, so these hunts look for the certificate names reported by The Hacker News in trust bundles and in TLS logs; the logic is our analysis. The bash script was executed against synthetic PEM bundles (a bundle holding a test certificate with the root's name, a clean certificate, a non-PEM file and an empty file). The Sigma rule (Zeek x509 log source), SPL and Datadog queries were reviewed, not executed. We are not offering a Suricata rule: we have not checked a published fingerprint list. The Sigma rule converts with pySigma to Splunk, Kusto and Lucene. Adjust field and table names to your logging.

bash — any PEM bundle (operating-system store, certifi, image layers); executed against synthetic data
#!/usr/bin/env bash
# Read-only. Usage: emudhra.sh <PEM-bundle>... (e.g. /etc/ssl/certs/ca-certificates.crt, certifi's cacert.pem)
# Exit: 0 scanned, none found | 1 found | 2 usage | 3 nothing readable
[ $# -ge 1 ] || { echo "usage: $0 <pem-bundle>..." >&2; exit 2; }
command -v openssl >/dev/null || { echo "openssl not found" >&2; exit 3; }
pat='emSign ECC Root CA - G3|emSign Root TLS CA - G3|EM (DV|OV|EV) TLS CA - G3[BC]|EM OV CS CA - G3[BC]'
scanned=0; hits=0
for f in "$@"; do
  [ -r "$f" ] && [ -s "$f" ] || { echo "unreadable or empty: $f" >&2; continue; }
  subj=$(openssl crl2pkcs7 -nocrl -certfile "$f" 2>/dev/null | openssl pkcs7 -print_certs -noout 2>/dev/null | grep -E '^subject=')
  [ -n "$subj" ] || { echo "no certificates parsed: $f" >&2; continue; }
  scanned=$((scanned+1)); m=$(printf '%s\n' "$subj" | grep -E -- "$pat")
  [ -n "$m" ] && { printf '%s: %s\n' "$f" "$m"; hits=$((hits+$(printf '%s\n' "$m" | wc -l))); }
done
echo "scanned=$scanned hits=$hits"
[ $scanned -eq 0 ] && exit 3; [ $hits -gt 0 ] && exit 1; exit 0
Sigma — Zeek x509 logs (validated with pySigma; reviewed, not executed)
title: Certificate chaining through a compromised eMudhra intermediate
id: d27b5e94-61a3-4c8f-9e02-4fb3a1c6d859
status: experimental
description: Certificates whose issuer is one of the eight eMudhra intermediates reported compromised in October 2026. Seen after 17 October, treat traffic through them as intercepted.
references:
  - https://blog.mozilla.org/security/2026/10/20/protecting-firefox-users-following-the-compromise-of-emudhra-intermediate-certificates/
  - https://thehackernews.com/2026/10/eight-emudhra-ca-keys-compromised.html
logsource:
  product: zeek
  service: x509
detection:
  selection:
    certificate.issuer|contains:
      - 'EM DV TLS CA - G3B'
      - 'EM DV TLS CA - G3C'
      - 'EM OV TLS CA - G3B'
      - 'EM OV TLS CA - G3C'
      - 'EM EV TLS CA - G3B'
      - 'EM EV TLS CA - G3C'
      - 'EM OV CS CA - G3B'
      - 'EM OV CS CA - G3C'
  condition: selection
falsepositives:
  - Legitimate eMudhra-issued sites contacted before the block
level: high
Splunk SPL — Zeek x509 logs (sourcetype assumption: bro:x509:json; reviewed, not executed)
index=* sourcetype="bro:x509:json" ("certificate.issuer"="*EM DV TLS CA - G3*" OR "certificate.issuer"="*EM OV TLS CA - G3*" OR "certificate.issuer"="*EM EV TLS CA - G3*")
| stats count earliest(_time) latest(_time) by "certificate.subject" "certificate.issuer"
Datadog Logs — TLS-inspection or proxy logs (field name varies by integration; reviewed, not executed)
*:"EM DV TLS CA - G3B" OR *:"EM DV TLS CA - G3C" OR *:"EM OV TLS CA - G3B" OR *:"EM OV TLS CA - G3C" OR *:"EM EV TLS CA - G3B" OR *:"EM EV TLS CA - G3C" OR *:"EM OV CS CA - G3B" OR *:"EM OV CS CA - G3C"
If you see Do this
A connection or signed file chaining through one of the eight after 17 October Defined response: capture the certificate, identify the endpoint or file, and treat the traffic as intercepted.
A legitimate eMudhra-issued site your business depends on Expected. Ask the site owner when they will move to a new chain, and note the date.
The root in a bundle you ship Update the bundle and rebuild.
The script exits 3 This is not a clean result. Point it at a PEM file, not a directory or a Java keystore.
No hits A good sign, not an exoneration. Only names were searched, many networks log no certificate chains at all, and a Go binary can still trust the old chain without any log line. Rebuild anyway.

5. Google Cloud: search-ad phishing ends in someone else's AI bill

Bottom line

Bottom line. Wiz reported on 20 October multiple intrusions that start with Google Search ads for terms like "google cloud" and end with Gemini API charges of tens to hundreds of thousands of dollars within 24 to 48 hours.

  • In between, they pass through a Google Sites redirect to a fake Google login that captures credentials and MFA codes.
  • The attackers delete the organization policy that limits IAM members to company domains, add external Gmail accounts to billing with admin roles, link their own projects to the victim's billing account, and demote existing billing admins to viewers.
  • Do now: check who holds roles/billing.admin and whether iam.allowedPolicyMemberDomains is still set; set budget alerts on billing accounts.
  • Skip if: you have no Google Cloud organization or billing account.

Indicators

Type Indicator Where to look Source
IoC 212.73[.]134[.]136 — attacker infrastructure, initial login from the phishing page Google Workspace login logs; GCP audit logs Wiz
IoC Phishing domains as Wiz wrote them: *.gboogl[.]com, *.groosl[.]com, *.gprokl[.]com, *.gxoosl[.]com, *.gsoolg[.]com, *gzoozl[.]com, *groonl[.]com, *gsool[.]space, *gbrokl[.]space, *gbrokl[.]xyz, *gsoosl[.]xyz, *gsool[.]xyz, *gpoosl[.]com, *groolg[.]com, *gcslom[.]com, *gcoalg[.]com DNS and proxy logs Wiz
IoA SetOrgPolicy removing iam.allowedPolicyMemberDomains Cloud Audit Logs (organization) Wiz
IoA EnableService, CreateServiceAccount, CreateServiceAccountKey, CreateKey in old, low-use projects; grants of roles/ml.admin, roles/mcp.toolUser, roles/recommender.billingAccountCudAdmin, roles/billing.admin Cloud Audit Logs Wiz
IoA External Gmail accounts added to a billing account; billing admins demoted to viewer; sudden Gemini spend Billing IAM; billing reports Wiz

What

So what

Now what — P → I (analysis)

Hunt pack — run it, then act on what it says

These hunts implement the address, method names, roles and policy name Wiz published; the Gemini service name in the bash script (generativelanguage.googleapis.com) is our addition. The bash script was executed against synthetic audit-log JSON (a hit on the address and policy, a near-miss address, a compressed file and an empty file). The Sigma rule (Google Cloud audit log source), SPL and Datadog queries were reviewed, not executed. The Sigma rule converts with pySigma to Splunk, Kusto and Lucene. Adjust field and table names to your logging.

bash — Cloud Audit Log export (`gcloud logging read --format=json`), .json or .gz; executed against synthetic data
#!/usr/bin/env bash
# Read-only. Usage: gcp.sh <audit-log-export.json[.gz]>...  (from 'gcloud logging read --format=json' or a sink)
# Exit: 0 scanned, none found | 1 found | 2 usage | 3 nothing readable
[ $# -ge 1 ] || { echo "usage: $0 <file>..." >&2; exit 2; }
ip=$(printf '%s' '212.73[.]134[.]136' | tr -d '[]' | sed 's/\./\\./g')
pat="(^|[^0-9.])$ip([^0-9]|\$)|allowedPolicyMemberDomains|roles/ml\.admin|roles/mcp\.toolUser|roles/recommender\.billingAccountCudAdmin|roles/billing\.admin|generativelanguage\.googleapis\.com"
scanned=0; hits=0
for f in "$@"; do
  [ -r "$f" ] && [ -s "$f" ] || { echo "unreadable or empty: $f" >&2; continue; }
  case "$f" in *.gz) c="zcat -f";; *) c="cat";; esac
  scanned=$((scanned+1)); n=$($c "$f" | grep -Eoc -- "$pat"); hits=$((hits+n))
  [ "$n" -gt 0 ] && $c "$f" | grep -Eo -- ".{0,120}($pat).{0,80}" | head -50
done
echo "scanned=$scanned hits=$hits"
[ $scanned -eq 0 ] && exit 3; [ $hits -gt 0 ] && exit 1; exit 0
Sigma — Google Cloud audit logs (validated with pySigma; reviewed, not executed)
title: GCP organization policy change or billing-admin grant matching Wiz LLMjacking reporting
id: 5a8c3f17-92e6-4d0b-8c71-e3b9d0a4f2c6
status: experimental
description: The method names, policy and roles Wiz published for a phishing-to-LLMjacking campaign. A removal of the domain restriction that no one approved is a confirmed compromise.
references:
  - https://www.wiz.io/blog/from-phishing-to-llmjacking
logsource:
  product: gcp
  service: gcp.audit
detection:
  policy:
    gcp.audit.method_name: 'SetOrgPolicy'
  domains:
    - 'allowedPolicyMemberDomains'
  roles:
    - 'roles/billing.admin'
    - 'roles/mcp.toolUser'
    - 'roles/ml.admin'
    - 'roles/recommender.billingAccountCudAdmin'
  condition: (policy and domains) or roles
falsepositives:
  - Approved administrator changes with a ticket
level: high
Splunk SPL — Google Cloud audit logs via the Splunk Add-on (sourcetype assumption: google:gcp:pubsub:message; reviewed, not executed)
index=* sourcetype="google:gcp:pubsub:message" ("data.protoPayload.methodName"="SetOrgPolicy" OR "data.protoPayload.methodName"="CreateServiceAccountKey" OR "data.protoPayload.requestMetadata.callerIp"="212.73[.]134[.]136" OR "allowedPolicyMemberDomains" OR "roles/billing.admin")
| table _time "data.protoPayload.methodName" "data.protoPayload.authenticationInfo.principalEmail" "data.protoPayload.requestMetadata.callerIp"
Datadog Logs — Google Cloud audit logs (attribute names vary by integration; remove the brackets; reviewed, not executed)
@network.client.ip:212.73[.]134[.]136 OR (*:"SetOrgPolicy" *:"allowedPolicyMemberDomains") OR *:"roles/billing.admin" OR *:"roles/mcp.toolUser"
If you see Do this
Activity from the listed address, or the domain restriction removed without approval Confirmed compromise under the defined response: revoke sessions, remove external members and keys, unlink foreign projects, dispute the charges.
New Gemini API enablement or service-account keys in old projects A lead. Ask the project owner; treat as compromise if no one made the change.
A known administrator granting roles/billing.admin through a change ticket Expected. Record it.
The script exits 3, or audit logs for the organization are not exported This is not a clean result. Admin Activity logs are on by default; export them before relying on the hunt.
No hits A good sign, not an exoneration. One address was published and the attackers moved to addresses in the victim's own country; phishing domains change; and a log search does not show charges already incurred. Check the billing report anyway.

6. CISA's catalog adds six: Plex Media Server, Siemens Software Center and SiteGuard Server Edition

Bottom line

Bottom line. CISA added six exploited flaws to its catalog on 20 October: four in Plex Media Server, one in Siemens Software Center and one in SiteGuard Server Edition.

  • Due dates: 23 October for Plex CVE-2026-96654 and CVE-2026-96656 and for SiteGuard CVE-2026-106931; 3 November for Plex CVE-2026-96652 and CVE-2026-96655 and for Siemens CVE-2026-110936.
  • Do now: apply the vendors' fixes; treat any internet-exposed Plex server as possibly compromised and hunt it.
  • Skip if: you run none of these three products.

Indicators

Type Indicator Where to look Source
IoC None published in the catalog entries — CISA catalog data, version 2026.10.20
IoA Requests to /video/:/transcode/universal carrying a full URL — the SSRF path CISA names for CVE-2026-96655 Reverse-proxy or web logs in front of Plex CISA (path); ours (the full-URL test)
IoA A protocol parameter carrying a full URL, sent with any X-Plex-Token — the SSRF CISA describes for CVE-2026-96652 Reverse-proxy or web logs CISA
IoA A DLL placed in a directory Siemens Software Center searches, then loaded by it EDR image-load events CISA description of CVE-2026-110936; ours (where to look)

What

So what

Now what — P → I (analysis)

Hunt pack — run it, then act on what it says

These hunts implement the request paths and parameters in CISA's catalog descriptions; the logic is our analysis. The bash script was executed against synthetic access logs (a hit with an encoded full URL, a clean log, a compressed log, an empty file and no arguments). The Sigma rule (the Plex path CISA names, against a generic web-server log source), KQL and Datadog queries were reviewed, not executed. We are not offering a Suricata rule, or any rule for SiteGuard: no request pattern or file name has been published for it. The Sigma rule converts with pySigma to Splunk, Kusto and Lucene. Adjust field and table names to your logging.

bash — reverse-proxy or web access logs in front of Plex (text or .gz); executed against synthetic data
#!/usr/bin/env bash
# Read-only. Usage: plex.sh <web-or-proxy-access-log>... (text or .gz)
# Flags requests to the transcode path named in CISA's entry for CVE-2026-96655.
# Exit: 0 scanned, none found | 1 found | 2 usage | 3 nothing readable
[ $# -ge 1 ] || { echo "usage: $0 <log>..." >&2; exit 2; }
pat='/video/:/transcode/universal|/video/%3A/transcode/universal'
scanned=0; hits=0
for f in "$@"; do
  [ -r "$f" ] && [ -s "$f" ] || { echo "unreadable or empty: $f" >&2; continue; }
  case "$f" in *.gz) c="zcat -f";; *) c="cat";; esac
  scanned=$((scanned+1)); n=$($c "$f" | grep -Eic -- "$pat"); hits=$((hits+n))
  [ "$n" -gt 0 ] && $c "$f" | grep -Ei -- "$pat" | grep -Ei 'https?(%3A|:)' | cut -c1-300
done
echo "scanned=$scanned hits=$hits (lines printed above carry a full URL, the stronger lead)"
[ $scanned -eq 0 ] && exit 3; [ $hits -gt 0 ] && exit 1; exit 0
Sigma — web-server or reverse-proxy logs in front of Plex (validated with pySigma; reviewed, not executed)
title: Plex Media Server transcode request carrying an outside URL (CVE-2026-96655 path)
id: 1e7d4b38-a5c9-4f62-b3e0-7c84d2f9a613
status: experimental
description: The SSRF path CISA names for CVE-2026-96655, with a full URL in the request. Followed by new files or processes on the Plex host, this is a confirmed compromise.
references:
  - https://github.com/cisagov/kev-data
logsource:
  category: webserver
detection:
  path:
    cs-uri-stem|contains:
      - '/video/:/transcode/universal'
      - '/video/%3A/transcode/universal'
  url:
    cs-uri-query|contains:
      - 'http://'
      - 'https://'
      - 'http%3A'
      - 'https%3A'
  condition: path and url
falsepositives:
  - Plex clients that pass full URLs for remote media; validate the source
level: medium
KQL — Microsoft Defender XDR advanced hunting, DeviceImageLoadEvents (process name for Siemens Software Center is an assumption; reviewed, not executed)
DeviceImageLoadEvents
| where Timestamp > ago(30d)
| where InitiatingProcessFolderPath has "Siemens" and InitiatingProcessFolderPath has "Software Center"
| where not(FolderPath startswith @"C:\Windows\") and not(FolderPath startswith @"C:\Program Files")
| project Timestamp, DeviceName, InitiatingProcessFileName, FileName, FolderPath, SHA256
Datadog Logs — reverse-proxy or web logs in front of Plex (reviewed, not executed)
*:"/video/:/transcode/universal" OR *:"/video/%3A/transcode/universal"
If you see Do this
A transcode or protocol request carrying an outside URL, then new files or processes on the host Confirmed compromise under the defined response: isolate, preserve, rotate tokens, rebuild.
Transcode requests with no outside URL Expected: that is normal playback.
A DLL loaded by Software Center from a user-writable folder A lead. Validate who placed it; treat as compromise if no one did.
The script exits 3, or Plex is reached directly without a proxy that logs This is not a clean result. Plex's own logs are the next place to look.
No hits A good sign, not an exoneration. Only the published paths were searched, encoded variants beyond the two included are possible, and a server reached without a logging proxy leaves nothing here. Patch by the due date anyway.

Making this the last time: controls that outlast these incidents

Bottom line

Bottom line. Three of today's items share one lesson: a trusted channel — a VPN gateway, a release download, a certificate chain — was the way in. The controls below hold even when the next flaw or key leak is unknown.

  • Do now: pick the one row that matches your biggest gap and assign an owner this week.
  • Skip if: every row is already in place and tested.
Control Why it matters here Do this Needs
Hypervisor management on its own network Item 2's pivot went from the VPN to vCenter Allow vCenter and ESXi management only from a privileged-access network, never from the VPN pool; enforce execInstalledOnly on every host Network change; vSphere admin
Pinned, attested release downloads Item 3's checksums.txt was replaced along with the binary Pin hashes in CI and verify vendor attestations (gh attestation verify) instead of the release's own checksum file CI change
Trust stores you can update in a day Item 4 left Go binaries and bundled CA files trusting a compromised chain Inventory every bundled CA file and Go build; make rebuilding them a routine job Build pipeline owner
Alerts on control removal Item 5's first move was deleting a domain restriction Alert on any change to organization policies and billing roles Cloud audit-log alerting

Sector signal — only what a source actually said

How this brief is put together

ATT&CK (ours unless noted): T1190 Exploit Public-Facing Application (items 1, 2, 6); T1133 External Remote Services (item 2); T1003 OS Credential Dumping (item 2); T1195.002 Compromise Software Supply Chain (item 3); T1552.001 Credentials in Files (item 3); T1553 Subvert Trust Controls (item 4); T1566 Phishing and T1078.004 Cloud Accounts (item 5); T1574.001 DLL Search Order Hijacking (item 6).

Threat Vector Management helps organizations and the MDR and SOC teams that defend them turn briefs like this into action — running a look-back hunt across the logs you already keep, and deciding what a clean result does and does not let you close. Start a conversation →

More editions: Threat Brief archive.

Threat Vector Management is not affiliated with any company operating under the name “ThreatVector.”


Sources

  1. Palo Alto Networks Unit 42 — Threat Brief: Active Exploitation of PAN-OS CVE-2026-0257, updated 19 and 20 Oct 2026
  2. Palo Alto Networks — advisory CVE-2026-0257, published 13 May 2026
  3. CISA — Known Exploited Vulnerabilities catalog data, catalog versions 2026.10.20 and 2026.10.21
  4. PHP — Security advisory: Critical remote code execution vulnerabilities, update now, 21 Oct 2026
  5. PHP — GitHub advisory GHSA-w8hw-w9fx-j79w, RCE via OOM corruption (CVE-2026-109618), 21 Oct 2026
  6. PHP — GitHub advisory GHSA-6wmf-4rv5-p3rp, RCE via stale global state (CVE-2026-109619), 21 Oct 2026
  7. Fastly — Proactive protection for PHP2Shell, CVE-2026-109618 and CVE-2026-109619, 21 Oct 2026
  8. Amazon Threat Intelligence — Amazon Threat Intelligence identifies PHP2Shell exploitation prior to public disclosure in MadPot, 21 Oct 2026; watchTowr — PHP2Shell: PHP Remote Code Execution Exploited, 21 Oct 2026; Akamai — Critical Remote Code Execution Vulnerabilities in PHP Core, 21 Oct 2026; AWS — Security Bulletin 2026-143-AWS: PHP web runtimes, 21 Oct 2026; AWS — Using AWS WAF to apply mitigations for PHP2Shell RCE vulnerabilities, 21 Oct 2026; CloudLinux — PHP CVE-2026-109618 and CVE-2026-109619: Imunify360 WAF rulesets, 21 Oct 2026, updated 22 Oct; Microsoft — Addressing PHP2Shell: upgrade guidance and Azure WAF mitigations, 21 Oct 2026; Microsoft — Azure WAF custom rules for PHP2Shell mitigation, 21 Oct 2026; Google Cloud — Responding to core PHP vulnerabilities CVE-2026-109618 and CVE-2026-109619, 21 Oct 2026; F5 — AI found it. AI is stopping it, 22 Oct 2026; Imperva — PHP2Shell: When PHP Runs Out of Memory at the Wrong Moment, 21 Oct 2026; Patchstack — Major security alert: PHP vulnerable to critical RCE, attacks ongoing, 21 Oct 2026; Tenable — php2shell FAQ, 21 Oct 2026; Wiz — PHP2Shell: AI uncovers critical RCE vulnerabilities affecting 70% of the Internet, 21 Oct 2026; Huntress — Rapid Response: php2shell, Leaked Critical PHP Vulnerabilities (CVE-2026-109618 & CVE-2026-109619), 21 Oct 2026
  9. OVHcloud CLI — GitHub issue 300, opened 19 Oct 2026
  10. SecurityWeek — Hijacked Developer Account Used to Plant Stealer in OVHcloud CLI, 21 Oct 2026
  11. OpenSourceMalware — GlassWorm hacks OVHcloud's CLI tool, Oct 2026
  12. Mozilla Security Blog — Protecting Firefox users following the compromise of eMudhra intermediate certificates, 20 Oct 2026
  13. The Hacker News — Eight eMudhra CA Keys Compromised, 20 Oct 2026
  14. Wiz — From Phishing to LLMjacking, 20 Oct 2026
  15. CVE record CVE-2026-96656
  16. SANS Internet Storm Center — Stormcast, Tuesday, October 20th, 2026, 20 Oct 2026

Provenance: compiled 21–22 October 2026 by Threat Vector Management from a sweep of vendor, government and researcher sources, with research and fact-checking support from Claude (Anthropic). Every CVE identifier, version string, score, date and indicator was checked against its cited source on the day of publication; the hunt logic is our analysis of those records.

Get the next one first

New Threat Briefs and Deep Dives, delivered to your feed reader the moment they publish. No sign-up, no email, no tracking.

Follow Insights