October 23, 2026

Threat Brief: Critical Vulnerabilities in PHP: CVE-2026-109618, CVE-2026-109619 (Updated October 23)

CVE-2026-109618 and CVE-2026-109619 are Critical vulnerabilities in PHP, a scripting language used globally for web servers and CMS systems.

Threat Brief: Critical Vulnerabilities in PHP: CVE-2026-109618, CVE-2026-109619 (Updated October 23)

Executive Summary

Unit 42 is aware of two critical vulnerabilities in PHP: CVE-2026-109618 and CVE-2026-109619. Both are remote code execution (RCE) vulnerabilities rated as 9.2 (CVSS 4.0). The vulnerabilities are being referred to as PHP2Shell. We encourage reviewing the PHP Group’s security advisory and patching guidance.

PHP is widely used across web servers and content management systems globally. We recommend assessing your exposure to these vulnerabilities and patching immediately.

Unit 42 has seen proof of concept of these vulnerabilities. At least one European government has taken its website offline as a precaution.

Palo Alto Networks has evaluated our product portfolio regarding this issue. Refer to our security advisory for the most up to date details.

  • CVE-2026-109618involves a remote code execution vulnerability where handling out-of-memory errors via longjmp() leaves request memory uninitialized due to improper control flow management, allowing attackers to reliably achieve RCE using out-of-memory (OOM) triggers.
  • CVE-2026-109619describes a remote code execution vulnerability where longjmp() fatal error handling leaves global memory pointing to freed memory regions. These regions can later be read or branched on during subsequent requests, enabling attackers to execute arbitrary code.

Unit 42 researchers also observed attackers using agentic AI attack platforms for post-exploitation activity. In one case, the attackers targeted a government entity in Europe and within two hours of the initial exploitation they had successfully accessed password hashes and multi-factor authentication secrets. They also established an NT LAN Manager (NTLM)-relay tunnel into Active Directory and attempted Domain Admin privilege escalation.

We observed an attacker enumerating the compromised endpoint. The commands and behavioral markers used in the attack are strong indicators of an agentic attacker. Each command batch is wrapped in section-header delimiters, such as ==SHELLUSER== and ==PASSWD==. These delimiters produce machine-parseable output for an AI model to read. We also noted the use of the short, serially spaced tasks and quick pivots after failures. Figure 1 shows the commands that were executed, as seen in Cortex XDR.

A flowchart illustrating a multi-step cybersecurity breach. It details steps including reconnaissance of an SQL database, targeting password storage, and accessing LDAP configuration files. Notes highlight aspects like authentication database recon and DC hunting for administrator accounts.

At the time of publication, Palo Alto Networks Cortex Xpanse has identified the presence of over 22.6 million exposed instances potentially vulnerable to CVE-2026-109618 and CVE-2026-109619 based on our telemetry.

Palo Alto Networks customers receive protections from and mitigations for CVE-2026-109618 and CVE-2026-109619 in the following ways:

Palo Alto Networks also recommends assessing your exposure to these vulnerabilities and patching immediately.

Organizations can access tailored adversary intelligence, direct analyst consultations, and specialized exposure tracking through Unit 42 Threat Intel Services and our Deep and Dark Web Service.

The Unit 42 Incident Response team can also be engaged to help with a compromise or to provide a proactive assessment to lower your risk.

Vulnerabilities Discussed
, CVE-2026-109618, CVE-2026-109619PHP2Shell

Unit 42 Managed Threat Hunting Queries

The Unit 42 Managed Threat Hunting team continues to track any attempts to exploit these CVEs across our customers, using Cortex XDR and the XQL queries below. Cortex XDR customers can also use these XQL queries to search for signs of exploitation.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

// Description: This query attempts to identify post-exploitation command execution within the context of a PHP web server or worker process.

// Notes: 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. This query may also produce false positive findings depending on the specific web applications running. We recommend validating if any identified activity is expected for the web applications running on systems.

config case_sensitive = false

| dataset = xdr_data

| filter event_type = ENUM.PROCESS and event_sub_type = ENUM.PROCESS_START and action_process_image_name != null

| fields _time, agent_hostname, agent_id, event_id, actor_effective_username, actor_process_image_name, actor_process_command_line, action_process_image_name, action_process_image_path, action_process_image_command_line, causality_actor_process_image_name, causality_actor_process_command_line

// Lowercase fields once

| alter

    actor_effective_username = lowercase(actor_effective_username),

    actor_process_image_name = lowercase(actor_process_image_name),

    actor_process_command_line = lowercase(actor_process_command_line),

    action_process_image_name = lowercase(action_process_image_name),

    action_process_image_path = lowercase(action_process_image_path),

    action_process_image_command_line = lowercase(action_process_image_command_line),

    causality_actor_process_image_name = lowercase(causality_actor_process_image_name)

// Anchor: PHP web worker (or the launcher that started it) as causality, PHP worker as direct parent,

// a shell directly under an IIS worker, or the web service account outside an interactive login session

| filter causality_actor_process_image_name ~= “^(?:apache2|httpd|apachectl|php-fpm[0-9.]*|php-cgi[0-9.]*(?:.cagefs)?|php-fcgi|sw-engine(?:-fpm)?|frankenphp|lsphp[0-9]*|lshttpd|litespeed|xampp-control|wampmanager|laragon|de.appsolute.mampprohelper)(?:.exe)?$”

    or actor_process_image_name ~= “^(?:apache2|httpd|php-fpm[0-9.]*|php-cgi[0-9.]*(?:.cagefs)?|php-fcgi|sw-engine(?:-fpm)?|frankenphp|lsphp[0-9]*|lshttpd|litespeed)(?:.exe)?$”

    or (causality_actor_process_image_name = “w3wp.exe” and actor_process_image_name in (“cmd.exe”, “powershell.exe”, “pwsh.exe”))

    or (actor_effective_username ~= “(?:^|[^a-z0-9_-])(?:www-data|apache|nginx|wwwrun|iusr)$”

        and coalesce(causality_actor_process_image_name, “”) !~= “^(?:sshd(?:-session)?|screen|tmux|login|mosh-server|dropbear)$”)

    or actor_effective_username contains “iis apppool”

// Known-benign workloads (monitoring plugins, hosting control panels) and commands launched directly by CDK Drive DMS scripts

| filter action_process_image_command_line !~= “(?:/usr/lib(?:64)?/nagios/plugins/|/usr/local/cpanel/|/usr/local/psa/|/opt/psa/|/usr/local/directadmin/|/usr/local/ispconfig/|/usr/local/virtualizor/|richdocumentscode|phpsysinfo|librenms|zabbix)”

    and coalesce(actor_process_command_line, “”) !~= “^(?:S+s+)?(?:/adp/(?:bin|3party|etc)/|/local/bin/uminfo)”

// Phusion Passenger app spawns run id/uname/env from their spawn helpers

| filter coalesce(action_process_image_command_line, “”) !~= “^(?:/usr/bin/)?(?:id(?:s+-[a-z]+)?|uname(?:s+-[a-z]+)?|hostname|env)$|passenger-configs+system-metrics”

    or lowercase(coalesce(actor_process_command_line, “”)) !~= “passengeragents+spawn-|spawn(?:preparer|envsetupper)shell|/helper-scripts/rack-preloader.rb|passenger_ruby_wrapper|phusion_passenger”

// RHEL-family /etc/profile runs these in every bash login shell

| filter coalesce(action_process_image_command_line, “”) !~= “^/usr/bin/(?:ids+-[ug]n|hostname)$”

    or lowercase(coalesce(actor_process_command_line, “”)) !~= “^(?:S*/)?bashs+-[a-z]*l|^-bash$”

// parsed_lookup: the tool is the first command of its parent “sh -c” and its output is piped into a text filter (scripted lookup)

| alter tool = replace(action_process_image_name, “.exe”, “”),

    shell_first_cmd = arrayindex(regextract(coalesce(actor_process_command_line, “”), “^-?(?:S*/)?(?:ba|da|k)?shs+-cs+(S+)”), 0)

| alter parsed_lookup = if(arrayindex(regextract(coalesce(shell_first_cmd, “”), “([^/]+)$”), 0) = tool

        and actor_process_command_line ~= “^-?(?:S*/)?(?:ba|da|k)?shs+-cs+[^;&|]+|s*(?:e?grep|awk|cut|sed|wc|head|tail|sort|tr)b”, 1, 0)

// Signals – one event can carry several

| alter signals = concat(

    // SCORED – host/user/network/container recon, excluding scripted lookups (distinct tools are counted later)

    if(parsed_lookup = 0 and (tool in (“whoami”, “hostname”, “hostnamectl”, “ifconfig”, “netstat”, “ss”, “arp”, “route”, “w”, “who”, “last”, “lastlog”, “getent”, “lsb_release”, “lscpu”, “printenv”, “env”, “getcap”, “capsh”, “systeminfo”, “ipconfig”, “nltest”, “tasklist”, “quser”, “qwinsta”)

        or (tool = “uname” and action_process_image_command_line ~= “bunames+(?:-[a-z]*[arv]|–all|–kernel-)”)

        or (tool = “id” and action_process_image_command_line !~= “bids+-[ugnrz]+b”)

        or (tool = “ip” and action_process_image_command_line ~= “bips+(?:-[a-z0-9]+s+)*(?:a|addr|address|r|route|n|neigh|link)b”)

        or (tool = “ps” and action_process_image_command_line ~= “bpss+(?:-?aux|-ef|-eb|axjf|-auxf)”)

        or (tool in (“net”, “net1”) and action_process_image_command_line ~= “bnet1?(?:.exe)?s+(?:user|group|localgroup|accounts|view|share)b”)

        or (tool = “cat” and action_process_image_command_line ~= “/etc/(?:passwd|shadow|group|issue|os-release|hosts|hostname|resolv.conf|crontab|sudoers)|/proc/(?:version|net/|(?:self|[0-9]+)/(?:cgroup|mountinfo))|/.dockerenv”)

        or (tool = “find” and action_process_image_command_line ~= “-perms+(?:-4000|-u=s|/4000|-2000)”)

        or (tool = “sudo” and action_process_image_command_line ~= “bsudos+-lb”)), “recon,”, “”),

    // SCORED – payload transfer to a file (curl with an output file, wget not to stdout), excluding /dev/null and localhost

    if(((tool = “curl” and action_process_image_command_line ~= “s(?:-[a-z]*ob|–outputb|–remote-name)|>s*S”)

            or (tool = “wget” and action_process_image_command_line !~= “s-[a-z]*os*-(?:s|$)|–output-document=-|–spider”)

            or (tool in (“tftp”, “fetch”) and action_process_image_command_line ~= “(?:https?|ftp|tftp)://|s-[a-z]*o(?:s|-|$)”)

            or (tool = “certutil” and action_process_image_command_line ~= “urlcache|verifyctl”)

            or (tool = “bitsadmin” and action_process_image_command_line contains “/transfer”)

            or (tool in (“powershell”, “pwsh”) and action_process_image_command_line ~= “downloadstring|downloadfile|invoke-webrequest|biwrb|net.webclient|start-bitstransfer”))

        and action_process_image_command_line !~= “-os*/dev/null|–output-document=/dev/null|://(?:localhost|127.0.0.1|[::1])?[:/]”, “download,”, “”),

    // SCORED – chmod making a file in a tmp-class directory executable

    if(tool = “chmod” and action_process_image_command_line ~= “bchmods+(?:-[a-z]+s+)*(?:[0-7]?(?:[1357][0-7]{2}|[0-7][1357][0-7]|[0-7]{2}[1357])|[ugoa,+=rwst-]*[+=][rwst]*x[ugoa,+=rwxst-]*)s” and action_process_image_command_line ~= “s/(?:tmp|var/tmp|dev/shm|run/shm)/”, “staging,”, “”),

    // STANDALONE – binary executed from a writable/memory-backed dir, or from a deleted/memfd image

    if(action_process_image_path ~= “^/(?:tmp|var/tmp|dev/shm|run/shm|run/user)/|^/proc/(?:self|[0-9]+)/fd/|^/memfd:|(deleted)s*$”, “writable_exec,”, “”),

    // STANDALONE – reverse/bind shell constructs

    if(action_process_image_command_line ~= “/dev/(?:tcp|udp)/|(?:^|[s;&|(/])(?:nc|ncat|netcat)(?:.[a-z]+)?s+(?:S+s+){0,6}?(?:-[a-z]{0,3}[ec]|–exec|–sh-exec)s+S*(?:sh|bash|cmd|python[0-9.]*|perl)b|bsocatb[^;&|]{0,80}exec:|bmkfifob|b(?:ba|da|z|a)?shs+-ib|socket.socket(|fsockopen(|bpty.spawn(“, “revshell,”, “”),

    // STANDALONE – remote content piped straight into an interpreter

    if(action_process_image_command_line ~= “(?:curl|wget|fetch)b[^|]*|s*(?:/S*/)?(?:(?:ba|da|z|a)?sh|python[23]?|perl|php)b”, “pipe_to_shell,”, “”),

    // SCORED – encoded/obfuscated execution

    if(action_process_image_command_line ~= “base64s+(?:-d|–decode)|frombase64string|-e(?:nc|ncodedcommand)?s+[a-z0-9+/]{40,}|echos+[a-z0-9+/]{40,}|bopenssls+(?:encb[^|;]*s-db|base64s+-db)|bxxds+(?:-[a-z]+s+)*-[a-z]*r”, “encoded,”, “”),

    // SCORED – persistence / backgrounding (crontab edits, authorized_keys writes, new users, nohup/setsid of tmp-class binaries or shells,

    // scheduled tasks, Run keys, systemd units, chattr +i)

    if((tool = “crontab” and action_process_image_command_line !~= “bcrontabs+-ls*$”)

        or (action_process_image_command_line ~= “(?:>>?s*|btees+(?:-as+)?|b(?:cp|mv|install|ln)s+(?:-S+s+)*S+s+)S*authorized_keys”

            and action_process_image_command_line !~= “bcps+S*/.ssh/id_[a-z0-9]+.pubs+S*/.ssh/authorized_keys”)

        or action_process_image_command_line ~= “b(?:useradd|adduser)b|b(?:nohup|setsid)s+(?:-S+s+)*(?:./|/(?:tmp|var/tmp|dev/shm|run/shm)/|(?:ba|da|z)?shs+-[ci]b)|schtaskss+/create|currentversion.runb|bsystemctls+(?:–users+)?enableb|.config/systemd/user/|/etc/systemd/system/|bchattrs++[a-z]*i”, “persistence,”, “”),

    // SCORED – inline interpreter one-liners, excluding PHP version/feature probes and Ruby gem-path probes

    if(action_process_image_command_line ~= “(?:^|[^a-z0-9._-])(?:python[23]?(?:.[0-9]+)?s+-c|perls+-e|rubys+-e|node(?:js)?s+-e|luas+-e|php[0-9.]*s+-r)b”

        and action_process_image_command_line !~= “phpversion(|php_version|date(‘t’)|function_exists(|extension_loaded(|gem.path”, “interpreter,”, “”),

    // SCORED – cloud/container credential and secret access (credential files, env-var names, instance metadata service, .env reads)

    if(action_process_image_command_line ~= “.aws/(?:credentials|config)|aws_secret_access_key|aws_session_token|/.azure/|azure_client_secret|identity_endpoint|/.config/gcloud/|application_default_credentials.json|/secrets/kubernetes.io/serviceaccount|/run/secrets/|/.docker/config.json|169.254.169.254|metadata.google.internal|/proc/(?:self|[0-9]+)/environ|b(?:cat|head|tail|less|more|strings|grep)b[^|;]*.envb”, “cred_access,”, “”)

  )

| filter signals != “”

| alter recon_tool = if(signals contains “recon”, tool, null)

// Group per host, PHP worker and account in 1-hour buckets

| bin _time span = 1h

| comp count() as events,

        count_distinct(recon_tool) as recon_tool_count,

        values(recon_tool) as recon_tools,

        values(signals) as signals,

        values(action_process_image_command_line) as action_process_image_command_line,

        values(actor_process_command_line) as actor_process_command_line,

        values(causality_actor_process_command_line) as causality_actor_process_command_line,

        first(event_id) as event_id

    by _time, agent_id, agent_hostname, causality_actor_process_image_name, actor_effective_username

| alter all_signals = arraystring(signals, “,”)

// Threshold: any standalone signal, OR 3+ distinct recon tools, OR recon plus a follow-on scored signal

| filter all_signals ~= “revshell|pipe_to_shell|writable_exec”

    or recon_tool_count >= 3

    or (recon_tool_count >= 1 and all_signals ~= “download|staging|encoded|persistence|interpreter|cred_access”)

1

2

3

4

5

6

7

8

9

10

11

12

// Description: This query identifies potential inbound exploitation attempts from publicly routed IP addresses using Palo Alto Networks NGFW Threat Logs.

config case_sensitive = false

| dataset = panw_ngfw_threat_raw

| filter sub_type = “vulnerability”

| filter to_zone !~= “internet|untrust|outside|external|wan”

| filter not (incidr(source_ip, “10.0.0.0/8”) or incidr(source_ip, “172.16.0.0/12”) or incidr(source_ip, “192.168.0.0/16”))

| filter to_string(threat_id) contains “543004” or threat_name ~= “php|multipart|upload.progress|longjmp|CVE-2026-10961[89]”

| comp count() as hits, count_distinct(source_ip) as sources, values(source_ip) as source_ips, values(action) as actions,

       values(severity) as severities, min(_time) as first_seen, max(_time) as last_seen

    by threat_name, threat_id, dest_ip, nat_dest, dest_port, to_zone

| sort desc hits

Palo Alto Networks Product Protections for CVE-2026-109618 and CVE-2026-109619

Palo Alto Networks customers can leverage several product protections and updates to identify and defend against these vulnerabilities.

Organizations can access tailored adversary intelligence, direct analyst consultations, and specialized exposure tracking through Unit 42 Threat Intel Services and its Deep and Dark Web Service.

If you think you might have been compromised or have an urgent matter, get in touch with the Unit 42 Incident Response team or call:

  • North America: Toll Free: +1 (866) 486-4842 (866.4.UNIT42)
  • UK: +44.20.3743.3660
  • Europe and Middle East: +31.20.299.3130
  • Asia: +65.6983.8730
  • Japan: +81.50.1790.0200
  • Australia: +61.2.4062.7950
  • India: 000 800 050 45107
  • South Korea: +82.080.467.8774

Cortex XDR and XSIAM

Cortex XDR and XSIAM help protect against post-exploitation activities using the multi-layer protection approach. provide multilayered protection against post-exploitation activities. Cortex XDR also provides visibility into installed software across endpoints and servers, including on-premises and legacy environments, to help security teams identify systems running vulnerable PHP versions and prioritize remediation.

Cortex Cloud and Prisma Cloud

Cortex Cloud and Prisma Cloud help identify vulnerable PHP versions across code, registry images and runtime instances. Cortex Cloud’s Supply Chain Attacks Portal helps teams identify affected assets and take action to prevent vulnerable components from being reintroduced. Additionally, Cortex CLI integrates into CI/CD pipelines to scan images and enforce policies that block vulnerable images before they reach registries and runtime environments.

Cortex Xpanse

Cortex Xpanse can identify exposed devices on the public internet and escalate these findings to defenders. Customers can enable alerting on this risk by ensuring that the PHP Attack Surface Rule is enabled. Identified findings can either be viewed in the Threat Response Center or in the incident view of Expander. These findings are also available for Cortex XSIAM customers who have purchased the ASM module.

Next-Generation Firewall

Next-Generation Firewall with the following security subscriptions can help block the attacks:

Additional Resources

Updated October 21, 2026, at 9:30 a.m. PT to add Palo Alto Networks security advisory, update links in additional resources, and update product protection section.

Updated October 21, 2026, at 1:00 p.m. PT to update the product protection section. 

Updated October 22, 2026, at 4:30 p.m. PT to add additional product protection information for Advanced Threat Prevention, Cortex Cloud, and Prisma Cloud and make light copyedits.  

Updated October 23, 2026, at 12:30 p.m. PT to add details on agentic AI post-exploitation activity and Managed Threat Hunting queries.

Originally published on Unit 42