Oracle PeopleSoft CVE-2026-35273 – Renewed Mass Exploitation With WAF Bypass

Threat Overview

Google Threat Intelligence Group and Mandiant reported on September 25, 2026 that UNC6240, associated with ShinyHunters, resumed mass exploitation of CVE-2026-35273 against Oracle PeopleSoft. The actor bypassed literal-path WAF rules by encoding the leading P in /PSEMHUB/ as /%50SEMHUB/, then abused Java deserialization in the Environment Management Hub servlet for unauthenticated remote code execution. Observed outcomes include fileless command execution, JSP/JSPX web shells, a trojanized signed installer delivering the SIDEEYE backdoor, Neo-reGeorg tunneling, MeshCentral persistence, credential access, lateral movement, and data-theft extortion. Oracle confirms that PeopleTools 8.61 and 8.62 are affected and that exploitation does not require authentication.

References

Impacted Systems

  • Vendor/product: Oracle PeopleSoft Enterprise PeopleTools 8.61 and 8.62; PeopleSoft Enterprise Applications using affected PeopleTools may also be exposed.
  • Platform: PeopleSoft Internet Architecture hosted on Oracle WebLogic on Windows or Linux.
  • Component: Environment Management Hub (PSEMHUB) servlet/application.
  • Deployment: On-premises or self-managed PeopleSoft environments; Internet-reachable PIA/EMHub endpoints are highest risk.
  • Prerequisite: No authentication is required. Exploitation uses crafted serialized Java objects sent to the PSEMHUB hub servlet.
  • Exposure: /PSEMHUB/ or encoded/non-normalized variants reachable through a WAF, reverse proxy, load balancer, or directly.
  • Fixed state: Apply Oracle’s out-of-band Security Alert patch and mitigation guidance. Earlier unsupported releases were not tested and Oracle says they are likely affected.
  • Useful unaffected distinction: Standard PIA user sessions do not require public exposure of EMHub or the Integration Broker listening connector.

Why this matters

The campaign moved from targeted zero-day use to renewed multi-sector mass exploitation and demonstrated that common literal-string WAF blocks can be bypassed. PeopleSoft often holds payroll, HR, student, financial, and identity data, making successful exploitation a direct route to high-impact data theft and extortion.

Exploitation Status

  • Vendor-confirmed vulnerability: Oracle confirms unauthenticated RCE in PeopleTools 8.61 and 8.62 and recommends immediate mitigation.
  • Researcher-confirmed exploitation: Mandiant/GTIG observed renewed mass exploitation by UNC6240, with web shells on dozens of systems across higher education, technology, IT services, healthcare, agriculture, transportation, and government.
  • Observed behavior: bursts of POST requests to /%50SEMHUB/hub, fileless shells spawned by Java, x.jsp, u.jsp, u2.jsp, tunnel.jsp, tunnel.jspx, Ple64.exe, SIDEEYE traffic to 162.219.30.165 on TCP 3333/3334, and MeshAgent infrastructure.

What this hunt looks for

The queries cover available Microsoft Sentinel telemetry for encoded PSEMHUB requests, known web-shell paths and hashes, Java-spawned shells, post-exploitation tooling, known network indicators, new outbound destinations, staging/archive behavior, and fallback raw logs.

Required logs

Conclusions are limited to data sources and retention available in Microsoft Sentinel. Relevant visibility requires WAF/reverse-proxy or WebLogic access logs, Defender for Endpoint or comparable endpoint telemetry, Syslog/SecurityEvent collection, and network-device or flow logs. Fileless execution will not appear in file-only searches. Absence of matching activity does not confirm absence of exploitation on unmonitored nodes or in non-ingested logs.

1. First Pass – PSEMHUB Exploitation and Encoded WAF-Bypass Requests

union isfuzzy=true
(
    AzureDiagnostics
    | where TimeGenerated >= ago(30d)
    | extend Request=tostring(coalesce(column_ifexists("originalRequestUriWithArgs_s", ""), column_ifexists("requestUri_s", ""), column_ifexists("requestUri_d", ""), column_ifexists("Message", "")))
    | project TimeGenerated, SourceIP=tostring(column_ifexists("clientIp_s", "")), Host=tostring(column_ifexists("host_s", "")), Request, Action=tostring(column_ifexists("action_s", "")), SourceTable="AzureDiagnostics"
),
(
    CommonSecurityLog
    | where TimeGenerated >= ago(30d)
    | extend Request=strcat(tostring(RequestMethod), " ", tostring(RequestURL), " ", tostring(Message))
    | project TimeGenerated, SourceIP, Host=DestinationHostName, Request, Action=DeviceAction, SourceTable="CommonSecurityLog"
),
(
    Syslog
    | where TimeGenerated >= ago(30d)
    | project TimeGenerated, SourceIP="", Host=Computer, Request=SyslogMessage, Action="", SourceTable="Syslog"
)
| where Request matches regex @"(?i)/(?:%[0-9a-f]{2}|p)semhub/(?:hub|[^ ?]+\.(?:jsp|jspx))"
| project TimeGenerated, SourceTable, SourceIP, Host, Request, Action
| order by TimeGenerated desc

2. Burst POST Requests to PSEMHUB Hub Servlet

union isfuzzy=true
(
    AzureDiagnostics
    | where TimeGenerated >= ago(30d)
    | extend SourceIP=tostring(column_ifexists("clientIp_s", "")), Method=tostring(column_ifexists("httpMethod_s", "")), URI=tostring(coalesce(column_ifexists("originalRequestUriWithArgs_s", ""), column_ifexists("requestUri_s", ""))), Host=tostring(column_ifexists("host_s", ""))
),
(
    CommonSecurityLog
    | where TimeGenerated >= ago(30d)
    | extend SourceIP=tostring(SourceIP), Method=tostring(RequestMethod), URI=tostring(RequestURL), Host=tostring(DestinationHostName)
)
| where Method =~ "POST"
| where URI matches regex @"(?i)/(?:%[0-9a-f]{2}|p)semhub/hub"
| summarize Requests=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), URIs=make_set(URI, 20) by SourceIP, Host, bin(TimeGenerated, 5m)
| where Requests >= 3
| order by Requests desc

3. Java or WebLogic Spawning Command Shells

DeviceProcessEvents
| where TimeGenerated >= ago(30d)
| where InitiatingProcessFileName in~ ("java.exe", "java", "javaw.exe")
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "sh", "bash", "dash", "ksh")
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, SHA256
| order by TimeGenerated desc

4. PeopleSoft Web-Shell and Backdoor File Artifacts

let KnownHashes = dynamic(["48b4a0827da7bbfce9fb52464f8a659dea7a035189c52c506c0bfb4b1c3fe494","2bee941fb40519d0d1ec52bd79a8f63fc65aac6455c8f2d6b668e3360dfdb5d7","419c571ee38b7e7266d130c4b6bbc4dd0ef44d6e5f3bc02cc2cf73b762f07c86","ba14419beb2ec0bb94cab6298c14d7fb3e1d819366fe378290c0c2a4d97f7e07","3ba215692665513abfffd4e815c5c45f2d41e5dcc4283a2a3b740930c5c417c3"]);
DeviceFileEvents
| where TimeGenerated >= ago(30d)
| where FolderPath contains "PSEMHUB.war" or FolderPath contains "PORTAL.war" or SHA256 in~ (KnownHashes)
| where FileName in~ ("x.jsp", "u.jsp", "u2.jsp", "tunnel.jsp", "tunnel.jspx", "Ple64.exe") or FileName endswith ".jsp" or FileName endswith ".jspx" or SHA256 in~ (KnownHashes)
| project TimeGenerated, DeviceName, ActionType, FolderPath, FileName, SHA256, InitiatingProcessAccountName, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by TimeGenerated desc

5. Known Campaign Network Indicators

let KnownIPs = dynamic(["5.199.162.157","104.219.234.138","162.219.30.165"]);
let KnownDomains = dynamic(["winmanage-me.network","azurenetfiles.net","microsoft-entra.net","enroll.azuredevice.cloud"]);
union isfuzzy=true
(
    DeviceNetworkEvents
    | where TimeGenerated >= ago(30d)
    | where RemoteIP in (KnownIPs) or RemoteUrl has_any (KnownDomains)
    | project TimeGenerated, DeviceName, RemoteIP, RemoteUrl, RemotePort, InitiatingProcessAccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, SourceTable="DeviceNetworkEvents"
),
(
    CommonSecurityLog
    | where TimeGenerated >= ago(30d)
    | where DestinationIP in (KnownIPs) or DestinationHostName has_any (KnownDomains) or RequestURL has_any (KnownDomains)
    | project TimeGenerated, DeviceName=SourceHostName, RemoteIP=DestinationIP, RemoteUrl=coalesce(DestinationHostName, RequestURL), RemotePort=DestinationPort, InitiatingProcessAccountName=SourceUserName, InitiatingProcessFileName="", InitiatingProcessCommandLine="", SourceTable="CommonSecurityLog"
)
| order by TimeGenerated desc

6. SIDEEYE Control and Data Ports

union isfuzzy=true
(
    DeviceNetworkEvents
    | where TimeGenerated >= ago(30d)
    | where RemotePort in (3333, 3334)
    | project TimeGenerated, DeviceName, LocalIP, RemoteIP, RemotePort, InitiatingProcessFileName, InitiatingProcessCommandLine, SourceTable="DeviceNetworkEvents"
),
(
    CommonSecurityLog
    | where TimeGenerated >= ago(30d)
    | where DestinationPort in (3333, 3334)
    | project TimeGenerated, DeviceName=SourceHostName, LocalIP=SourceIP, RemoteIP=DestinationIP, RemotePort=DestinationPort, InitiatingProcessFileName="", InitiatingProcessCommandLine="", SourceTable="CommonSecurityLog"
)
| order by TimeGenerated desc

7. MeshAgent and Neo-reGeorg Follow-On Activity

union isfuzzy=true
(
    DeviceProcessEvents
    | where TimeGenerated >= ago(30d)
    | where FileName has_any ("meshagent", "meshctrl") or ProcessCommandLine has_any ("meshagent", "meshcentral", "Neo-reGeorg", "tunnel.jsp", "tunnel.jspx")
    | project TimeGenerated, DeviceName, EvidenceType="Process", AccountName, FileName, FolderPath, ProcessCommandLine, SHA256
),
(
    DeviceFileEvents
    | where TimeGenerated >= ago(30d)
    | where FileName has_any ("meshagent", "meshagent.msh", "meshagent.db", "tunnel.jsp", "tunnel.jspx")
    | project TimeGenerated, DeviceName, EvidenceType="File", AccountName=InitiatingProcessAccountName, FileName, FolderPath, ProcessCommandLine=InitiatingProcessCommandLine, SHA256
)
| order by TimeGenerated desc

8. Archive Creation and Transfer Utilities on PeopleSoft/WebLogic Hosts

DeviceProcessEvents
| where TimeGenerated >= ago(30d)
| where InitiatingProcessFileName in~ ("java.exe", "java", "cmd.exe", "sh", "bash") or InitiatingProcessCommandLine has_any ("PeopleSoft", "WebLogic", "PSEMHUB")
| where FileName in~ ("tar", "tar.exe", "zstd", "zstd.exe", "rsync", "rsync.exe", "sshpass", "sshpass.exe", "curl", "curl.exe") or ProcessCommandLine has_any (".tar.gz", ".zst", "rsync", "sshpass", "/dev/tcp")
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by TimeGenerated desc

9. Rare Outbound Destinations From Known PeopleSoft Hosts

let PeopleSoftDevices = dynamic(["REPLACE_WITH_PEOPLESOFT_HOST"]);
let BaselineStart = ago(30d);
let RecentStart = ago(7d);
let Baseline = DeviceNetworkEvents
| where TimeGenerated between (BaselineStart .. RecentStart)
| where DeviceName in~ (PeopleSoftDevices)
| where isnotempty(RemoteIP)
| summarize by DeviceName, RemoteIP, RemotePort;
DeviceNetworkEvents
| where TimeGenerated >= RecentStart
| where DeviceName in~ (PeopleSoftDevices)
| where isnotempty(RemoteIP)
| join kind=leftanti Baseline on DeviceName, RemoteIP, RemotePort
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Connections=count(), URLs=make_set(RemoteUrl, 20), Processes=make_set(InitiatingProcessFileName, 20) by DeviceName, RemoteIP, RemotePort
| order by Connections desc

Detection Notes

  • Queries 1 and 2 are the highest-signal network hunts. Defenders must normalize URL paths; matching only literal /PSEMHUB/ misses the documented bypass.
  • Query 3 detects both fileless and web-shell execution when endpoint process telemetry exists.
  • Hash-only detection is insufficient because minor JSP changes alter hashes; path, parent-process, and behavior searches are more durable.
  • Query 9 requires confirmed PeopleSoft hostnames to replace the placeholder.
  • Load-balanced deployments require review of every WebLogic node. Repeated exploit requests may intentionally reach multiple backend nodes.
  • AzureDiagnostics field availability varies by WAF connector and resource type. Adjust the URI, method, host, and client-IP columns to the deployed schema.
  • Expected noise includes legitimate EMHub administration, approved JSP deployment, authorized MeshCentral use, and routine Java child processes; validate against change records and server roles.