Article Banner

Hunting AI-Generated Attacks on Water Sector OT

Water and wastewater systems face a growing wave of attacks that reach the industrial equipment running treatment plants and pumping stations. In 2026, federal agencies warned that attackers now use artificial intelligence to build the tools for these intrusions, lowering the skill and time once needed to interfere with critical equipment. The activity targets systems that were connected to the internet with little or no protection.

Think of it like a burglar who no longer needs to pick locks by hand because a machine now cuts a perfect key in minutes. The same shortcut lets less skilled attackers reach equipment that controls water pressure, chemical dosing, and safety limits. Because these systems were built for reliability rather than defense, harmful commands can look like normal activity.

When attackers reach this equipment, they can lock out the operators who run it, change how it behaves, or shut it down. Recent incidents forced communities to issue boil water notices, switch to manual operation, and manage loss of water pressure and flooding. Small utilities with limited staff and budget face the greatest risk, because a single exposed device can disrupt service for an entire community.

Hunting Controls & Observations

This analysis draws on two 2026 government advisories. The first, from NSA, CISA, FBI, DOE, and EPA, documents an active threat that uses AI-generated scripts to reach Internet-exposed Siemens S7 Series programmable logic controllers (PLCs). The second, from CISA with the FBI and EPA, documents a disruptive campaign in which threat actors reached Internet-exposed PLCs at US water utilities, changed device passwords and addresses to lock out operators, and modified controller logic. This activity extends a documented pattern of attacks against water-sector operational technology, including the IRGC-linked CyberAv3ngers campaign that deployed the IOCONTROL cyberweapon, covered in an earlier Focused Hunts analysis. The 2026 lockout campaign and the Siemens S7 activity carry no formal attribution.

Organizations can detect this activity through multiple telemetry sources:

  • Network & OT Controls: ICS-aware monitoring (industrial protocol inspection for S7comm, Modbus, and EtherNet/IP), boundary firewall and NetFlow logs at the IT/OT interface, and traffic to TCP port 102
  • Endpoint Controls: Engineering workstation EDR/XDR and Sysmon (Event 1 process creation, Event 7 image load), plus PowerShell and Python execution logs
  • Identity & Access Controls: Remote-access and VPN authentication logs, jump-host session records, and PLC or HMI credential-change events

Behavioral Indicators of Attack

The following observable behaviors distinguish this activity from routine operations:

  • Industrial-protocol connections to controllers on TCP port 102 from hosts that are not designated engineering workstations
  • Write operations to controller data blocks or changes to ladder logic outside approved maintenance windows
  • Python or other scripting engines loading the snap7 communication library on engineering workstations
  • Sequential scanning of OT network ports, or matches against Internet scanning services used to locate exposed controllers
  • Controller configuration changes, including password changes and IP address changes that disconnect or lock out operators
  • Connections to controllers from external or non-allowlisted source addresses, including undocumented cellular modem paths
  • Unknown binaries that masquerade as legitimate OT monitoring or engineering software
  • Sudden loss of operator visibility or control, unexpected controller stops, or communication loss with field devices

MITRE ATT&CK Tactics and Techniques

The Siemens S7 advisory maps the activity to the following Enterprise and ICS techniques, listed in kill chain order:

Controls' Observables

Detection opportunities organize by control category. Because operational technology traffic is highly predictable, deviations from an established baseline carry strong signal.

Network & OT Controls

  • S7comm activity from unexpected sources: Connections to controllers on TCP port 102 from hosts outside the engineering workstation set, or outside maintenance windows.
    Related MITRE Techniques: T0821, T1596.005
    Detection Difficulty: MEDIUM
  • Unauthorized write and program operations: Write commands to data blocks, program downloads, and ladder logic changes that do not correlate with a change ticket.
    Related MITRE Techniques: T0821, T0834
    Detection Difficulty: MEDIUM
  • External access to OT ports: Sessions to industrial protocol ports (S7comm 102, Modbus 502, EtherNet/IP 44818) from public or non-allowlisted addresses, including cellular modem paths.
    Related MITRE Techniques: T1596.005, T1694
    Detection Difficulty: LOW

Endpoint Controls

  • Industrial library loaded by a scripting engine: Python or other interpreters importing the snap7 library on engineering workstations, a hallmark of the AI-generated tooling.
    Related MITRE Techniques: T0834, T1588.007
    Detection Difficulty: LOW
  • Masquerading OT tools: Unknown or unsigned binaries presenting themselves as monitoring or engineering software.
    Related MITRE Techniques: T0849
    Detection Difficulty: MEDIUM

Identity & Access Controls

  • Controller credential changes: Password changes on PLCs or HMIs, especially those that precede a loss of operator access.
    Related MITRE Techniques: T1694, T0821
    Detection Difficulty: LOW
  • Access with default or weak credentials: Successful sessions to controllers that rely on default or minimally configured authentication.
    Related MITRE Techniques: T1694
    Detection Difficulty: MEDIUM

Insights and Recommendation

Organizations affected by this activity face operator lockout, manipulation of physical processes, and service disruption. Recent water utility incidents produced boil water notices, forced manual operation, and caused loss of water pressure and flooding. AI-assisted tooling raises the stakes by allowing less experienced threat actors to produce working exploitation scripts quickly, which widens the pool of capable attackers targeting small and mid-sized utilities.

Security teams should remove controllers from the public Internet and require a VPN or gateway with strong authentication for all remote access, which directly counters the exposure both advisories describe. Baseline normal S7comm and other industrial-protocol traffic so that connections from non-engineering hosts and off-hours write operations stand out (T0821, T0834). Enable password protection and replace default credentials on every controller to remove the insecure-credential path (T1694), and monitor engineering workstations for scripting engines that load the snap7 library (T1588.007). Maintain offline, verified backup images of controller configurations and ladder logic so operators can restore quickly after a lockout, and rehearse manual operation for critical processes.

Source and Credits

This summary is based on the joint advisory from NSA, CISA, FBI, DOE, and EPA, "Defending Against an Active Threat to Siemens S7 Series PLCs" (AA26-231A), published on August 19, 2026.

It is corroborated by CISA's alert, with the FBI (PSA260730) and EPA, "CISA Urges Water and Wastewater Systems Sector to Protect OT Against Activity Targeting PLCs," published on July 30, 2026.

Related Focused Hunts coverage of the IRGC-linked CyberAv3ngers campaign and the IOCONTROL cyberweapon is available in "CyberAv3ngers: IOCONTROL Water OT Attacks."

Threat Hunting IOCs & Queries

Neither advisory published file hashes, command-and-control domains, or attacker IP addresses. Detection should rely on the behavioral queries below rather than static indicators. The following artifacts provide context for tuning those queries.

Known Indicators and Artifacts

  • Tooling libraries: snap7.dll and python-snap7, a legitimate open-source S7 communication library abused to build exploitation tools
  • Protocol and port: S7comm over TCP port 102; commonly co-exposed OT ports include Modbus TCP 502 and EtherNet/IP 44818
  • Affected controllers: Siemens S7-200, S7-300, S7-400, S7-1200, and S7-1500 families (per AA26-231A); Rockwell Automation Allen-Bradley MicroLogix 1400 (per the July 30 CISA alert)
  • Discovery infrastructure: Internet scanning services such as Censys and ZoomEye, used to locate exposed controllers
  • Note: Indicators are current as of the source publication dates. Threat actors rotate infrastructure and tooling; behavioral detection is more durable than static matching.

Anomalous S7comm Connections From Non-Engineering Sources

Behavior Targeted: Detects industrial-protocol connections to controllers on TCP port 102 from hosts that are not designated engineering workstations, the primary signal of unauthorized controller access.
MITRE ATT&CK: T0821, T1596.005, T1694
Expected Results: Sessions to PLC IP addresses on port 102 originating from unexpected hosts or user accounts, often clustered in time.
False Positive Likelihood: MEDIUM
Tuning Guidance: List your engineering workstations and jump hosts in a Splunk lookup (ot_engineering_hosts.csv, field ip), replace the KQL process allowlist with your approved engineering and HMI software, and add a maintenance-window filter to surface off-hours activity.

Splunk SPL Query

| tstats summariesonly=false count values(All_Traffic.dest_ip) AS plc_targets
    min(_time) AS first_seen max(_time) AS last_seen
    from datamodel=Network_Traffic.All_Traffic
    where earliest=-7d All_Traffic.dest_port=102
        NOT [| inputlookup ot_engineering_hosts.csv | rename ip AS All_Traffic.src_ip | fields All_Traffic.src_ip]
    by All_Traffic.src_ip
| rename All_Traffic.* AS *
| where count > 1
| sort - count
| convert ctime(first_seen) ctime(last_seen)

Microsoft KQL Query (Defender/Sentinel)

DeviceNetworkEvents
| where Timestamp > ago(7d)
| where RemotePort == 102
| where InitiatingProcessFileName !in~ ("tia_portal.exe", "s7oiehsx64.exe")
| summarize Count = count(), PLCs = make_set(RemoteIP), FirstSeen = min(Timestamp), LastSeen = max(Timestamp)
    by DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName
| where Count > 1
| order by Count desc

Note: These queries were generated with AI assistance. Test thoroughly in your environment before production use.

AI-Generated Tooling Loading the snap7 Library

Behavior Targeted: Detects scripting engines importing the snap7 library on engineering workstations, a hallmark of the AI-generated tools that mimic legitimate S7 monitoring software.
MITRE ATT&CK: T0834, T1588.007, T0849
Expected Results: Python or similar interpreters loading a snap7 module or DLL on hosts and accounts that are not part of a sanctioned OT automation project.
False Positive Likelihood: LOW
Tuning Guidance: Cross-reference the loading process and account against approved OT automation; pair with command-line hunting for script context.

Splunk SPL Query

index=windows (source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" OR source="WinEventLog:Microsoft-Windows-Sysmon/Operational") EventCode=7
    earliest=-7d ImageLoaded="*snap7*"
| stats count values(Image) AS loading_process min(_time) AS first_seen max(_time) AS last_seen by Computer, User
| sort - count
| convert ctime(first_seen) ctime(last_seen)

Microsoft KQL Query (Defender/Sentinel)

DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where FileName has "snap7" or FolderPath has "snap7"
| summarize Count = count(), Loaders = make_set(InitiatingProcessFileName), FirstSeen = min(Timestamp)
    by DeviceName, InitiatingProcessAccountName
| order by Count desc

Note: These queries were generated with AI assistance. Test thoroughly in your environment before production use.

Controller Program, Credential, or Address Changes and Operator Lockout

Behavior Targeted: Detects controller configuration events forwarded by OT sensors or syslog, including program downloads, credential or IP address changes, and loss of operator connectivity, matching the water utility lockout campaign.
MITRE ATT&CK: T0821, T1694
Expected Results: Program or logic changes, password changes, or address changes on controllers that do not correlate with an authorized maintenance activity.
False Positive Likelihood: LOW to MEDIUM
Tuning Guidance: Point the search at the index or table that receives your OT sensor or PLC syslog (Nozomi, Claroty, or similar), map the message keywords to that sensor's taxonomy, and correlate with change tickets to clear authorized maintenance.

Splunk SPL Query

index=ot earliest=-14d
    ("program download" OR "logic change" OR "password change" OR "ip address change" OR "config change" OR "controller stop")
| stats count values(_raw) AS messages min(_time) AS first_seen max(_time) AS last_seen by host, sourcetype
| sort - first_seen
| convert ctime(first_seen) ctime(last_seen)

Microsoft KQL Query (Defender/Sentinel)

Syslog
| where TimeGenerated > ago(14d)
| where SyslogMessage has_any ("program download", "logic change", "password change", "ip address change", "config change", "controller stop")
| summarize Count = count(), Messages = make_set(SyslogMessage), FirstSeen = min(TimeGenerated)
    by Computer, HostIP
| order by FirstSeen desc

Note: These queries were generated with AI assistance. Test thoroughly in your environment before production use.

Externally Sourced Access to OT Controllers

Behavior Targeted: Detects sessions to OT controller ports from external or non-allowlisted source addresses, including cellular modem paths, the Internet exposure both campaigns exploit.
MITRE ATT&CK: T1596.005, T1694
Expected Results: Public or non-internal source addresses connecting to industrial protocol ports, which should be near zero in a segmented network.
False Positive Likelihood: MEDIUM
Tuning Guidance: Both queries read perimeter firewall logs (the CIM Network_Traffic data model in Splunk, CommonSecurityLog in Sentinel). Ports shown are S7comm (102), Modbus (502), EtherNet/IP (44818), and DNP3 (20000); keep only the industrial ports you operate and replace the internal ranges with your actual OT ranges.

Splunk SPL Query

| tstats summariesonly=false count values(All_Traffic.dest_port) AS ot_ports values(All_Traffic.dest_ip) AS plc_targets
    min(_time) AS first_seen max(_time) AS last_seen
    from datamodel=Network_Traffic.All_Traffic
    where earliest=-7d All_Traffic.dest_port IN (102, 502, 44818, 20000)
    by All_Traffic.src_ip
| rename All_Traffic.* AS *
| where NOT (cidrmatch("10.0.0.0/8", src_ip) OR cidrmatch("172.16.0.0/12", src_ip) OR cidrmatch("192.168.0.0/16", src_ip))
| iplocation src_ip
| sort - count
| convert ctime(first_seen) ctime(last_seen)

Microsoft KQL Query (Defender/Sentinel)

CommonSecurityLog
| where TimeGenerated > ago(7d)
| where DestinationPort in (102, 502, 44818, 20000)
| where isnotempty(SourceIP) and not(ipv4_is_private(SourceIP))
| summarize Count = count(), Ports = make_set(DestinationPort), Targets = make_set(DestinationIP, 50),
    FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DeviceVendor
| order by Count desc

Note: These queries were generated with AI assistance. Test thoroughly in your environment before production use.

Back to Hunting off the Red