Chapter 19 — OT, IoT and cyber-physical security: monitoring
Lesson map
Lesson 19 published. Map, example, EX055.
flowchart TD
N0["Learning outcomes"]
N1["19.1 Baselines"]
N2["19.2 Reading the alerts"]
N3["19.3 Triage with operations"]
N4["19.4 Tuning"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX055"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["19.1 Baselines"]
N2["19.2 Reading the alerts"]
N3["19.3 Triage with operations"]
N4["19.4 Tuning"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX055"]
[Learning outcomes]
|
v
[19.1 Baselines]
|
v
[19.2 Reading the alerts]
|
v
[19.3 Triage with operations]
|
v
[19.4 Tuning]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX055]
Learning outcomes
You will (1) build a baseline of normal communication; (2) detect new hosts against that baseline; (3) triage alerts with operations; and (4) tune monitoring to avoid alert fatigue.
19.1 Baselines
OT networks are repetitive: the same devices talk to the same partners on the same schedule. That makes a baseline — the set of hosts and flows seen over a representative period — a powerful detector. Anything new is worth a look. NIST SP 800-82r3 recommends monitoring tailored to OT's predictable traffic.
"""Lab 19: flag hosts not present in a 7-day baseline of synthetic flow records."""
baseline_days = {"HMI-C", "PLC-R1", "PLC-R2", "HIST", "GW-LOG"}
today = ["HMI-C", "PLC-R1", "HIST", "LAPTOP-V3", "GW-LOG", "LAPTOP-V3", "PLC-R2", "UNKNOWN-10.4.2.77"]
new = []
for h in today:
if h not in baseline_days and h not in new: new.append(h)
print("new talkers:", new)
print("events:", len(today), "unique hosts:", len(set(today)), "new:", len(new))
Run with python3 lab_talkers.py. Verified output:
new talkers: ['LAPTOP-V3', 'UNKNOWN-10.4.2.77']
events: 8 unique hosts: 7 new: 2
Priya's capture from SW-C supplied the baseline used in the lab: five hosts, HMI-C, PLC-R1, PLC-R2, HIST and GW-LOG, seen over seven days. Anything outside that set raises a new-talker alert, which is why the contractor's laptop and the dock printer both appear in the lab output.
19.2 Reading the alerts
LAPTOP-V3 appeared twice; UNKNOWN-10.4.2.77 once. The laptop is probably the contractor's (check the visit log). The unknown address is in no NCS subnet at all — that is more urgent, because it suggests a misconfigured device or a path the architecture does not include.
Both were resolved within an hour. The visit log showed the contractor on site with laptop V3 from 09:00 to 11:30, matching the alert times, so that alert was closed with the visit reference. The address 10.4.2.77 turned out to be a dock printer with an address from another site's plan.
19.3 Triage with operations
The analyst calls the facilities manager before acting: is a contractor on site? Did anyone add equipment? Operations context resolves most alerts in minutes. Only unexplained alerts escalate.
At NCS, both of the lab's new talkers were explained this way. The facilities manager's visit log showed the contractor on site with laptop V3 from 09:00 to 11:30, so that alert closed with the visit reference. The unknown 10.4.2.77 needed a walk to the dock, where a logistics printer was found in a camera-zone port. Neither required touching the control network. Had the visit log shown no contractor that morning, LAPTOP-V3 would have escalated at once.
19.4 Tuning
Expected changes — scheduled contractor visits, a new logger — should be added to the baseline through a change ticket, not silenced by a blanket rule. Review alert counts monthly; if most alerts are explained routine events, improve the change-ticket link rather than raising thresholds.
For NCS, contractor visits come with a ticket, so the visit-log link from Chapter 25's contractor pack lets LAPTOP-V3's appearance be matched automatically to an open ticket.
An alert with no matching ticket then goes to the security lead rather than being closed by the operator.
Worked example (synthetic NCS)
The visit log shows the contractor on site with laptop V3 from 09:00 to 11:30, matching the alert times. Priya closes that alert with the visit reference. The 10.4.2.77 address belongs to a dock printer installed by the logistics team with a static address from a different site's plan; it was plugged into a camera-zone port. It is moved, re-addressed and added to the inventory.
Synthetic case — Northgate Cold Storage. Hosts and the printer story are invented.
Errors and limits
A baseline captured while compromised treats the attacker as normal. Seven days may miss monthly activity.
Exercises
- EX055 — Extending the baseline. If LAPTOP-V3 is added to
baseline_days, what does the lab print as new talkers? Rubric: 3 = ['UNKNOWN-10.4.2.77'] and new: 1; 2 = list only; 1 = unchanged; 0 = none. - EX056 — Why the unknown address is urgent. Explain in two sentences. Rubric: 3 = outside any NCS subnet, implies unplanned path or misconfiguration; 2 = partial; 1 = vague; 0 = none.
- EX057 — Tuning without blinding. Propose how scheduled contractor visits should stop generating unexplained alerts. Rubric: 3 = visit ticket adds laptop to time-bounded allow-list/annotation; 2 = partial; 1 = ignore laptops; 0 = none.
Synthesis
Baselines turn OT's regularity into detection; triage with operations and change-linked tuning keep alerts meaningful.
Continue studying — chapter 19 of 30
← Chapter 18 (draft) · Course chapter index · Chapter 20 (draft) →