feat(ics): dynamic Modbus/TCP probe for PLC/SPS devices (#148)
CI / Check (pull_request) Failing after 4m3s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped

Adds the first dynamic dimension to PLC/SPS targets: probe the running device
over industrial protocols, complementing the static control-logic rules.

- New ScanType::IcsProbe (+ phase), offered for PlcSps with a reachable endpoint
  (opt-in / default-off).
- pipeline::ics::modbus — a minimal, read-only Modbus/TCP client: issues Read
  Holding Registers + Read Device Identification, never writes to the live
  process. Detects an endpoint that answers unauthenticated Modbus and reads its
  device identity (vendor/product/revision).
- pipeline::ics::probe_target — emits findings: `ics-modbus-exposed` (Critical,
  CWE-306 — Modbus/TCP has no auth/encryption by protocol design) and
  `ics-device-disclosure` (Low, CWE-200). Targets the Modbus port (502) of the
  target's Live URL, independent of any WebVisu HTTP port.
- orchestrator: a PLC/SPS target runs the ICS probe when planned (alongside the
  control-logic scan and DAST).

Unit-tested against an in-process mock Modbus server + endpoint-parsing and
device-id parsing tests. Docs: new "Dynamic testing — ICS protocol probe" section.

First increment of #148 (soft-PLC + industrial-protocol probing); OPC UA /
EtherNet-IP and the OpenPLC soft-PLC harness (orca-infra) follow. Tracker #167.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-07-16 18:05:34 +02:00
co-authored by Claude Opus 4.8
parent a3f3f1d4f5
commit 5e8250f7e9
8 changed files with 428 additions and 1 deletions
+5
View File
@@ -24,6 +24,9 @@ pub enum ScanType {
MobileStatic,
/// Static analysis of a container image.
ContainerScan,
/// Dynamic probing of a running PLC/SPS device over industrial protocols
/// (Modbus/TCP, OPC UA, …) for exposed/unauthenticated control access.
IcsProbe,
}
impl std::fmt::Display for ScanType {
@@ -43,6 +46,7 @@ impl std::fmt::Display for ScanType {
Self::PlcControlLogic => write!(f, "plc_control_logic"),
Self::MobileStatic => write!(f, "mobile_static"),
Self::ContainerScan => write!(f, "container_scan"),
Self::IcsProbe => write!(f, "ics_probe"),
}
}
}
@@ -76,6 +80,7 @@ pub enum ScanPhase {
LlmTriage,
IssueCreation,
DastScanning,
IcsProbe,
Completed,
}
+6
View File
@@ -251,6 +251,12 @@ pub fn rules_for(target_type: TargetType) -> Vec<ScanRule> {
"Dynamic scan of the running device (WebVisu / exposed services)",
RunningUrl,
),
ScanRule::new(
ScanType::IcsProbe,
false,
"Probe the running device over industrial protocols (Modbus/TCP, …)",
RunningUrl,
),
]
}
}