IEC-104 assessment: the protocol that trusts everyone equally¶

Or: How Ponder Discovered That Injecting Substation Readings Required Only a Curl Command
The protocol and its assumptions¶
IEC 60870-5-104, known in practice as IEC-104, is the standard protocol for communicating between substations and control centres across TCP/IP networks. It carries readings from field devices: breaker states, voltage measurements, current values, frequency. The control centre subscribes; the RTU transmits. Protection systems, operators, and automated switching logic all act on what they receive.
The protocol itself has no authentication mechanism. This is not an oversight. It was designed for a time when access to the substation network was itself the security control. If you could reach the RTU, you were authorised. The network was the wall.
The wall, Ponder observed, has since developed a number of unofficial doors.
The UU P&L substation RTU¶
The simulator includes substation-rtu, an IEC-104 RTU deployed in the Guild Quarter DMZ at 10.10.5.14. It
manages six datapoints representing the Dolly Sisters and Nap Hill feeder segment:
Id |
Name |
Value |
Unit |
|---|---|---|---|
1 |
feeder_a_voltage |
10.8 |
kV |
2 |
feeder_b_voltage |
11.1 |
kV |
3 |
load_current |
340.0 |
A |
4 |
frequency |
49.98 |
Hz |
5 |
breaker_a_state |
true |
closed |
6 |
breaker_b_state |
true |
closed |
The RTU exposes two interfaces: an IEC-104 protocol endpoint on port 2404, and a REST management API on port 8080. Both operate without authentication. The REST API was added by the vendor for commissioning; the IEC-104 endpoint is the live protocol channel. They share the same in-memory datapoint table.
What passive assessment reveals¶
The REST API is the starting point. From a read-only perspective:
curl http://10.10.5.14:8080/datapoints
This returns the full datapoint table without credentials. The pentester now knows the normal operating ranges for the Dolly Sisters and Nap Hill feeders: voltages around 10.8-11.1 kV, load current around 340 A, frequency near 50 Hz, both breakers closed.
That knowledge alone is useful for calibrating any subsequent action against current conditions. Injecting 10.79 kV produces a plausible reading. Injecting 0.0 kV produces a reading that warrants investigation from any operator paying attention.
Security implication: complete visibility into substation datapoints without authentication, and without speaking IEC-104 at all.
Testing write access in the simulator¶
On the simulator, the POST endpoint mutates a datapoint value and immediately fires a spontaneous IEC-104 update to any connected master:
# Inject a false frequency reading
curl -X POST http://10.10.5.14:8080/datapoints/4 \
-H 'Content-Type: application/json' \
-d '{"value": 47.2}'
A frequency of 47.2 Hz is below the under-frequency alarm threshold. Any SCADA system or protection relay subscribed to this RTU receives the injected value within one cycle and may act on it: raising an alarm, issuing a switching command, adjusting generation setpoints. None of those downstream systems has any means to distinguish a genuine reading from an injected one.
On production systems, this write path is strictly out of scope unless the engagement explicitly authorises write operations against live substations, the system is in a known safe state, and the operational consequences have been reviewed with the client beforehand.
The inconsistency test¶
A subtler test involves injecting operationally impossible readings:
# Set feeder A voltage to zero while the breaker state stays closed
curl -X POST http://10.10.5.14:8080/datapoints/1 \
-d '{"value": 0.0}'
A trained operator looking at the dashboard would notice: feeder A voltage is zero, but the breaker state shows closed. In a real system, a closed breaker with zero voltage means either a dead feeder or a measurement failure. A protection system with narrow rules might not catch this; it depends on whether the automation logic checks cross-consistency or only individual threshold breaches.
The value of this test is what it reveals about the downstream system’s intelligence. A SCADA dashboard that displays the impossibility without any alarm has monitoring logic less sophisticated than it appears.
What the testing revealed¶
The UU P&L substation RTU illustrates a pattern common in operational technology: a management API installed for convenience during commissioning, left open because removing access would require a site visit, and forgotten because the IEC-104 channel was the one that got monitored.
The protocol offers nothing in the way of access control. The REST API offers nothing either. Together they mean that any host reaching 10.10.5.14 can read live substation values and inject false ones into the SCADA master’s view, with no authentication, no logging, and no delay.
Ponder’s assessment note: “The interesting question is not whether you can inject false readings into an RTU. You can. The interesting question is whether anyone downstream will notice. The inconsistency test is the more useful of the two, because it tells you something about the detection capability you are working against, not just about the access you already have.”
Related runbooks (in the ICS Access SimLab, to be linked once migrated into this repository):
IEC-104 false readings runbook: step-by-step attack path with expected output
substation-rtu README: datapoint schema and API reference