| ID | Technique | Tactic |
|---|---|---|
| T1005 | Data from Local System | Collection |
| T1059 | Command and Scripting Interpreter | Execution |
| T1190 | Exploit Public-Facing Application | Initial Access |
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
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| Windchill Log4j | Other | 'log4j' |
'not_applicable' |
Macros Used
| Name | Value |
|---|---|
| windchill_log4j | sourcetype=log4j |
| 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 |
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