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.
Search
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
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
| ID |
Technique |
Tactic |
| T1005 |
Data from Local System |
Collection |
| T1059 |
Command and Scripting Interpreter |
Execution |
| T1190 |
Exploit Public-Facing Application |
Initial Access |
Exploitation
Installation
Delivery
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
| 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