| ID | Technique | Tactic |
|---|---|---|
| T1059 | Command and Scripting Interpreter | Execution |
| T1190 | Exploit Public-Facing Application | Initial Access |
Detection: PTC Windchill GW READY OK Probe
Description
This analytic detects Windchill MethodServer log4j events that contain the CVE-2026-4681 exploitation probe run?c=echo%20GW_READY_OK.
PTC identifies GW_READY_OK and related run?c= activity as log indicators associated with Windchill and FlexPLM exploitation.
This behavior is significant because attackers use the probe to confirm that a staged gateway component is reachable before sending operating system commands through the same c= parameter.
Search
1`windchill_log4j`
2("GW_READY_OK" OR "run?c=echo%20GW_READY_OK" OR "c=echo%20GW_READY_OK")
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 query_param="c" AND match(query_value,"(?i)^echo(\s
36|20)+GW_READY_OK$")
37
38| eval src=src_ip, activity="gw_ready_ok_probe"
39
40
41| stats count min(_time) as firstTime
42 max(_time) as lastTime
43 values(log_level) as log_level
44 values(logger) as logger
45 values(http_method) as http_method
46 values(status) as status
47 values(uri_only) as uri_path
48 values(query_string) as query_string
49 by src activity query_param query_value
50
51
52| `security_content_ctime(firstTime)`
53
54| `security_content_ctime(lastTime)`
55
56| `ptc_windchill_gw_ready_ok_probe_filter`
Data Source
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| Windchill Log4j | Other | 'log4j' |
'not_applicable' |
Macros Used
| Name | Value |
|---|---|
| windchill_log4j | sourcetype=log4j |
| ptc_windchill_gw_ready_ok_probe_filter | search * |
ptc_windchill_gw_ready_ok_probe_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.
Known False Positives
This probe string is specific to the PTC-published Windchill exploitation indicators. False positives should be rare. Validate whether any internal testing, incident response activity, or vendor diagnostics intentionally generated GW_READY_OK requests.
Associated Analytic Story
Intermediate Findings
| Message | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| PTC Windchill GW READY OK exploitation probe 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