No IPs, No Signatures: Detecting Water-System Attack Behavior with Zeek and Suricata
Attacks against water and wastewater systems pulled a lot of attention this summer, and the conversation that followed went where it usually goes. What were the indicators? Which IPs should we block? Is there a signature yet?
Those are reasonable questions. They’re just the ones with the shortest shelf life. Most of the behavior involved in attacks on water systems can be caught without a single attacker IP address or malware signature, and that’s the part worth spending time on.
Indicators are perishable by design. An IP gets burned and rotated. A binary gets recompiled and the hash changes. Infrastructure gets stood up faster than anyone can publish a list. If your detection strategy depends on someone else naming the bad thing first, you’re always arriving after the fact.
Behavior moves a lot slower. An attacker who wants to affect a physical process has to do certain things, and those things look different from normal operations whether or not anyone has named the campaign.
What it actually looks like on the wire
Strip away attribution and tooling, and intrusions in an OT environment tend to leave a similar shape:
- Remote access software showing up on a segment where it has never run before
- A host speaking Modbus, DNP3, S7comm, or EtherNet/IP to a controller it has never spoken to
- Write function codes from a device whose entire history is read-only polling
- Engineering workstation protocols crossing a boundary they were never supposed to cross
- Credentials moving in cleartext to an HMI from outside the process network
- A session to a controller at 2am on a Sunday, when the plant runs on a schedule everyone knows
None of that requires knowing who the attacker is. It requires knowing what your environment normally does.
Where Zeek fits
Zeek isn’t a signature engine, and that’s exactly why it’s useful here. It’s a protocol analyzer that writes down what happened. Who talked to what, when, over which protocol, for how long, and what was asked for.
That record is what makes behavioral detection possible. A new source and destination pair talking an industrial protocol is trivially visible in connection logs. A function code that has never appeared between two specific devices is visible if you’re parsing the protocol rather than just counting bytes. With ICS protocol parsers in place, “this PLC just received a write from a host that has only ever read from it” becomes a question you can ask of your data instead of a thing you hope someone wrote a rule for.
The other advantage is retrospective. When new reporting lands, a Zeek deployment lets you go back through months of logs and ask whether the behavior described was ever present in your environment. Signature-only approaches can’t answer that question about the past.
Where Suricata fits
This isn’t a case for dropping signatures. Suricata is very good at the things signatures are good at: known exploit attempts, protocol anomalies, traffic that is unambiguously malformed. When someone throws a public exploit at an exposed device, you want that caught immediately and by name.
The two work better stacked than either does alone. Suricata tells you something known-bad just happened. Zeek tells you what that host has been doing for the last ninety days, who else it talked to, and whether this was the first time or the fortieth. One gives you the alert. The other gives you the story around it.
OT predictability is an asset
Enterprise networks are noisy. People install things, travel, spin up services, and generally make baselining a moving target.
Process networks are not like that. A treatment facility runs a defined set of devices, speaking a defined set of protocols, on something close to a fixed schedule, for years. That determinism is usually discussed as a constraint, because you can’t patch aggressively and you can’t scan without care. It’s also the single best detection asset the sector has. When normal is genuinely narrow, deviation means something.
Somebody still has to make the call
Here’s where this stops being a tooling conversation.
A write to a controller is not inherently an attack. It might be scheduled maintenance. It might be an integrator doing exactly what someone asked them to do that morning. A new remote access session might be a vendor with a work order behind it.
Detection logic can surface all of it. What detection logic cannot do is know whether it was supposed to happen. That requires someone who knows the environment, can pick up the phone, and can find out whether the change was approved before deciding whether it matters.
This is why our Managed SOC is built around analysts rather than around escalation queues. When something starts to drift in an environment where the consequence is physical, the useful question isn’t how quickly an alert fires. It’s how quickly the right person sees it and understands what they’re looking at.
A wiped controller doesn’t come with a decryption key. The systems that keep a process safe don’t get a maintenance window after the fact. When the target is the process instead of the data, waiting hours for someone to review an alert isn’t a strategy.
If you want the longer view of the threat landscape in this sector, we covered it in Protecting Water Systems: A Look at Cyber and Physical Threats in the WWS Sector. For how we think about modeling these environments without touching production, see The Future of OT Security Isn’t Louder Scanning. It’s Smarter Modeling.
And if you’d like to talk about what this looks like in your environment, our Managed Zeek IDS and Managed Services teams are happy to walk through it.
