feat(pipeline): PLC/SPS control-logic security scanner (IEC 61131-3) (#162)
CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 3s
CI / Deploy Agent (push) Successful in 3m48s
CI / Deploy Dashboard (push) Successful in 2m51s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2m2s
CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 3s
CI / Deploy Agent (push) Successful in 3m48s
CI / Deploy Dashboard (push) Successful in 2m51s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2m2s
This commit was merged in pull request #162.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
(*
|
||||
* Demo PLC program — pump-station control (IEC 61131-3 Structured Text).
|
||||
*
|
||||
* Deliberately vulnerable, for the compliance-scanner PLC control-logic demo.
|
||||
* Each issue below is flagged by pipeline::plc::rules.
|
||||
*)
|
||||
|
||||
FUNCTION_BLOCK PumpStationCtrl
|
||||
VAR_INPUT
|
||||
OperatorCmd : INT; (* HMI command index — untrusted *)
|
||||
FlowSetpoint : REAL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
PumpSpeed : REAL;
|
||||
Fault : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
HmiPassword : STRING := 'admin123'; (* hardcoded + default credential *)
|
||||
ApiKey : STRING := 'sk_live_9c1f2a'; (* hardcoded secret *)
|
||||
PumpProfiles : ARRAY[0..7] OF REAL;
|
||||
Safety_Enable : BOOL := TRUE;
|
||||
Watchdog_Kick : INT := 1;
|
||||
MeasuredFlow : REAL;
|
||||
ScaleFactor : REAL;
|
||||
i : INT;
|
||||
END_VAR
|
||||
|
||||
(* Operator can index the profile table with an unvalidated command. *)
|
||||
PumpSpeed := PumpProfiles[OperatorCmd];
|
||||
|
||||
(* Divisor is a live process value that can read zero on a stopped line. *)
|
||||
ScaleFactor := FlowSetpoint / MeasuredFlow;
|
||||
|
||||
(* Safety interlock disabled straight from application logic. *)
|
||||
IF OperatorCmd = 99 THEN
|
||||
Safety_Enable := FALSE;
|
||||
Watchdog_Kick := 0;
|
||||
END_IF;
|
||||
|
||||
(* Unauthenticated Modbus/TCP link on the cleartext OT port. *)
|
||||
Modbus_TCP_Connect(IP := '10.10.5.20', PORT := 502, AUTH := FALSE, PASSWORD := 'plc');
|
||||
|
||||
(* Unstructured jump around the fault handler. *)
|
||||
IF MeasuredFlow > 1000.0 THEN
|
||||
JMP trip;
|
||||
END_IF;
|
||||
|
||||
(* A correctly guarded division — must NOT be flagged. *)
|
||||
IF ScaleFactor <> 0.0 THEN
|
||||
PumpSpeed := PumpSpeed / ScaleFactor;
|
||||
END_IF;
|
||||
|
||||
RETURN;
|
||||
trip:
|
||||
Fault := TRUE;
|
||||
PumpSpeed := 0.0;
|
||||
END_FUNCTION_BLOCK
|
||||
Reference in New Issue
Block a user