Detection: PTC Windchill Gateway Command Execution

Description

This analytic detects Windchill MethodServer log4j events showing suspicious c= command execution or p= file read parameters sent to Windchill gateway paths associated with CVE-2026-4681 exploitation. PTC identifies run?c=, run?p=, .jsp?c=, and .jsp?p= request patterns as indicators to monitor during Windchill and FlexPLM exploitation response. Successful activity may allow an unauthenticated attacker to execute operating system commands or read files through a weaponized gateway or JSP component.

 1`windchill_log4j`
 2("WindchillGW/GW/run" OR "WindchillAuthGW/GW/run" OR "/GW/run?" OR "run?c=" OR "run?p=" OR ".jsp?c=" OR ".jsp?p=" OR "dpr_")
 3
 4| rex field=_raw "^(?:[^:\r\n]+:)?(?<log_ts>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2},\d{3})\s+(?<log_level>\w+)\s+\[(?<thread>[^\]]+)\]\s+(?<logger>\S+)\s+-\s+(?<payload>.*)$"
 5
 6| search logger IN ("wt.servlet.ServletRequestMonitor.request", "wt.method.MethodContextMonitor.contexts.servletRequest")
 7
 8| rex field=payload "^(?<event_ts>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\.\d{3})\s+(?<event_tz>[+\-]\d{4}),\s+(?<rest>.*)$"
 9
10| eval parts=split(rest,", ")
11
12| eval event_type=case(logger="wt.servlet.ServletRequestMonitor.request","servlet_request",logger="wt.method.MethodContextMonitor.contexts.servletRequest","method_context_servlet_request",true(),"other")
13
14| eval src_ip=case(event_type="servlet_request",mvindex(parts,2),event_type="method_context_servlet_request",mvindex(parts,5))
15
16| eval uri_path=case(event_type="servlet_request",mvindex(parts,3),event_type="method_context_servlet_request",mvindex(parts,8))
17
18| eval query_string=if(event_type="servlet_request",mvindex(parts,4),null())
19
20| eval http_method=if(event_type="servlet_request",mvindex(parts,5),null())
21
22| eval status=if(event_type="servlet_request",tonumber(mvindex(parts,6)),null())
23
24| rex field=uri_path "^(?<uri_only>[^\?]+)(?:\?(?<uri_query>.*))?$"
25
26| eval query_string=if(query_string="-",null(),query_string)
27
28| eval query_string=coalesce(query_string,uri_query)
29
30| rex field=query_string "(?i)(?:^
31|&)(?<query_param>[cp])=(?<query_value>[^&]*)"
32
33| eval query_param=lower(query_param), query_value=urldecode(replace(query_value,"\+","%20"))
34
35| where isnotnull(uri_only) AND isnotnull(query_param)
36
37| where (match(uri_only,"(?i)(^
38|/)GW/run$") OR match(uri_only,"(?i)/servlet/(WindchillGW
39|WindchillAuthGW)/GW/run$") OR match(uri_only,"(?i)(^
40|/)dpr_[0-9a-f]{8}\.jsp$")) AND (query_param="c" OR query_param="p")
41
42| where NOT (query_param="c" AND match(query_value,"(?i)^echo(\s
43|20)+GW_READY_OK$"))
44
45| eval activity=case(query_param="c","command_execution_parameter",query_param="p","file_read_parameter",true(),"unknown")
46
47| eval src=src_ip
48
49
50| stats count min(_time) as firstTime
51              max(_time) as lastTime
52              values(log_level) as log_level
53              values(logger) as logger
54              values(http_method) as http_method
55              values(status) as status
56              values(uri_only) as uri_path
57              values(query_string) as query_string
58  by src activity query_param query_value
59
60
61| `security_content_ctime(firstTime)`
62
63| `security_content_ctime(lastTime)`
64
65| `ptc_windchill_gateway_command_execution_filter`

Data Source

Name Platform Sourcetype Source
Windchill Log4j Other 'log4j' 'not_applicable'

Macros Used

Name Value
security_content_ctime convert timeformat="%Y-%m-%dT%H:%M:%S" ctime($field$)
ptc_windchill_gateway_command_execution_filter search *
ptc_windchill_gateway_command_execution_filter is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.

Annotations

CVE

Default Configuration

This detection is configured by default in Splunk Enterprise Security to run with the following settings:

Setting Value
Disabled true
Cron Schedule 0 * * * *
Earliest Time -70m@m
Latest Time -10m@m
Schedule Window auto
Creates Finding (Notable) No
Creates Intermediate Finding (Risk Event) Yes
Anomaly detections generate Intermediate Findings (Risk Events). They do not generate a Finding (Notable) directly.

Implementation

To implement this analytic, ingest PTC Windchill MethodServer log4j logs into Splunk with sourcetype log4j. Update the windchill_log4j macro to include the appropriate index constraints for your environment. The analytic expects log entries from the wt.servlet.ServletRequestMonitor.request and wt.method.MethodContextMonitor.contexts.servletRequest loggers and parses embedded servlet URI, query parameter, source IP, HTTP method, and status fields.

Known False Positives

Requests to GW/run or randomly named dpr_<8 hex>.jsp files with c= or p= parameters should not be expected during normal Windchill operation. Validate whether red-team testing, vulnerability scanning, or incident response replay generated the activity before closing as benign.

Associated Analytic Story

Intermediate Findings

Message Entity Field Entity Type Risk Score
Potential PTC Windchill gateway command or file read activity detected from $src$. src system 20

Threat Objects

Field Type
src ip_address

References

Detection Testing

Test Type Status Dataset Source Sourcetype
Validation Passing N/A N/A N/A
Unit Passing Dataset not_applicable log4j
Integration ✅ Passing Dataset not_applicable log4j

Replay any dataset to Splunk Enterprise by using our replay.py tool or the UI. Alternatively you can replay a dataset into a Splunk Attack Range


Source: GitHub | Version: 1