On Wednesday, the U.S. government issued an "active threat" warning: adversaries are using AI-generated reconnaissance and capability-development scripts to target Siemens S7 series Programmable Logic Controllers (PLCs) operating inside U.S. critical infrastructure. The scripts are deliberately disguised as legitimate monitoring tools — a tradecraft choice designed to blend into the routine polling and diagnostics traffic that OT engineers expect to see on plant networks.
This matters far beyond the immediate intrusion set. For 15+ years I've watched OT intrusions follow the same arc: quiet reconnaissance against PLCs, protocol fingerprinting, capability development, and then — sometimes months later — disruptive or destructive action. Stuxnet, Industroyer/CrashOverride, Triton/Trisis, and Industroyer2 all began with exactly this kind of patient, protocol-aware reconnaissance against engineering assets. The difference in 2026 is velocity and scale: AI code generation has collapsed the skill barrier for writing S7comm-aware tooling. An operator who couldn't tell a TSAP from a slot number can now generate functional PLC interrogation scripts in minutes, iterate them rapidly, and produce polymorphic variants that defeat hash- and signature-based detection.
If you operate energy, water, manufacturing, transportation, or building automation environments running Siemens S7-300, S7-400, S7-1200, or S7-1500 controllers, treat this as a priority threat-hunting trigger, not a news item to file away.
Technical Analysis
What's Actually Happening
Based on the government advisory, the activity has two operational phases:
- Reconnaissance: Scripts interrogate S7 PLCs to enumerate device identity, hardware/firmware revisions, module configuration, and — critically — the contents of data blocks and the presence of logic blocks (OBs, FBs, FCs, DBs). This is the attacker's equivalent of reading the plant's wiring diagram.
- Capability development: The tooling is being refined in the field — tested against live controllers, tuned, and re-deployed. That tells us the end goal is a matured toolkit, likely for future manipulation of ladder logic, setpoint changes, or safety-relevant process values.
Why S7 PLCs Are a Soft Target
The S7comm protocol (classic S7-300/400) and S7comm-Plus (S7-1200/1500) ride on TCP port 102 (ISO-TSAP). Key defensive facts every OT analyst should internalize:
- No authentication by default. Classic S7comm performs connection setup via COTP using TSAPs (e.g.,
01.00,03.00) that merely identify the rack/slot — they are not credentials. Anyone with network reachability can read from the PLC. - Read functions are unauthenticated. An attacker script can enumerate the PLC's order number, firmware version, and module list, and read data blocks, with nothing more than network access.
- Write and program functions are equally reachable unless the PLC is configured with a protection level (password) — and on S7-300/400 that protection is notoriously weak (replayable/derivable). S7-1200/1500 with current firmware offers stronger access protection, but it's frequently left disabled in the field.
- Plaintext protocol. Unless you've migrated to S7-1500 with TLS-secured HMI/engineering communication, S7 traffic is fully observable — which cuts both ways: defenders with protocol-aware monitoring can see everything too.
The "Disguised as Monitoring Tools" Angle
This is the crux of detection. Legitimate S7 polling comes from a known, finite set of sources: SCADA/HMI servers (WinCC, Ignition), historians, and engineering workstations running TIA Portal or Step 7. The malicious scripts mimic this pattern — periodic reads, modest rates, plausible function codes. Indicators that separate hostile reconnaissance from genuine monitoring:
- Source identity: Traffic from hosts that are not authorized SCADA/engineering assets — IT-side jump boxes, contractor laptops, recently connected devices.
- Python-based S7 libraries: Open-source tooling such as
python-snap7makes scripted S7 interaction trivial. A Python interpreter, compiled script, or PyInstaller-frozen executable initiating TCP/102 connections is a high-fidelity signal on most networks. - Enumeration behavior: Legitimate monitoring polls configured tags at steady intervals. Reconnaissance looks different — SZL (System Status List) reads for module identification, broad block enumeration, attempts to list/upload program blocks (functions that HMI polling almost never uses).
- Scale and sweep patterns: One host sequentially connecting to many PLCs across a subnet is not monitoring; it's mapping.
Exploitation Status
- Status: Confirmed active threat per U.S. government advisory (August 2026). Activity is ongoing against U.S. critical infrastructure.
- CVE: None assigned in the advisory — this is living-off-the-protocol abuse of S7comm's lack of authentication, not a memory-corruption bug. Do not expect a patch to fix this; the fix is architectural (segmentation, access protection, monitoring).
- CISA KEV: Not applicable — no CVE. CISA ICS advisories and the joint government warning are the authoritative references; monitor CISA ICS Advisories and Siemens ProductCERT for follow-on publications.
Detection & Response
The rules below are built around the behaviors described above: script interpreters and unsigned binaries initiating S7comm connections, and network patterns consistent with PLC enumeration rather than legitimate polling. Tune the authorized-source allowlists to your environment before deploying to production.
---
title: Script Interpreter Initiating Siemens S7comm Connection
description: Detects Python, PowerShell, Node, or other script interpreters making outbound connections to TCP/102 (ISO-TSAP/S7comm), consistent with AI-generated PLC reconnaissance scripts disguised as monitoring tools. Legitimate S7 polling originates from SCADA/HMI and engineering software, not generic interpreters.
references:
- https://thehackernews.com/2026/08/ai-generated-exploit-scripts-target.html
- https://attack.mitre.org/techniques/T0855/
author: Security Arsenal
date: 2026/08/08
status: experimental
logsource:
category: network_connection
product: windows
detection:
selection_port:
DestinationPort: 102
selection_interpreter:
Image|endswith:
- '\python.exe'
- '\pythonw.exe'
- '\python3.exe'
- '\powershell.exe'
- '\pwsh.exe'
- '\node.exe'
- '\wscript.exe'
- '\cscript.exe'
condition: selection_port and selection_interpreter
falsepositives:
- Custom OT integrations legitimately using python-snap7 on engineering workstations - verify and allowlist by host
tags:
- attack.discovery
- attack.t0855
- attack.t0846
level: high
---
title: Unsigned or Temp-Path Binary Connecting to S7 PLC Port
description: Detects executables launched from user-writable or temporary directories establishing connections to TCP/102, consistent with dropped AI-generated reconnaissance tooling packaged as standalone binaries to mimic monitoring software.
references:
- https://thehackernews.com/2026/08/ai-generated-exploit-scripts-target.html
- https://attack.mitre.org/techniques/T0855/
author: Security Arsenal
date: 2026/08/08
status: experimental
logsource:
category: network_connection
product: windows
detection:
selection_port:
DestinationPort: 102
selection_path:
Image|contains:
- '\AppData\Local\Temp\'
- '\AppData\Roaming\'
- '\Users\Public\'
- '\ProgramData\'
- '\Downloads\'
- '\Desktop\'
condition: selection_port and selection_path
falsepositives:
- Rare - legitimate S7 software (TIA Portal, WinCC, snap7-based tools) runs from Program Files; investigate any hit
tags:
- attack.discovery
- attack.t0855
level: high
---
title: Host Sweeping Multiple S7 PLCs on Port 102
description: Detects a single source host initiating connections to multiple distinct destinations on TCP/102 within a short window, indicating PLC network mapping rather than configured monitoring which targets a fixed device list.
references:
- https://thehackernews.com/2026/08/ai-generated-exploit-scripts-target.html
- https://attack.mitre.org/techniques/T0846/
author: Security Arsenal
date: 2026/08/08
status: experimental
logsource:
category: network_connection
product: windows
detection:
selection:
DestinationPort: 102
condition: selection
falsepositives:
- SCADA servers and historians legitimately poll many PLCs - allowlist known OT servers by source IP/host before deployment
tags:
- attack.discovery
- attack.t0846
level: medium
The third rule intentionally requires aggregation logic in your SIEM (e.g., threshold: >5 distinct DestinationIp per SourceIp in 10 minutes) — Sigma's network_connection category provides the raw events; apply the count correlation in Sentinel/Splunk/Elastic rather than disabling the rule as noise.
// Hunt: S7comm (TCP/102) connections from non-engineering processes or unusual sources
// Tune the AuthorizedS7Sources dynamic list to your SCADA/HMI/historian/TIA hosts before production use
let AuthorizedS7Sources = dynamic(["10.10.20.15", "10.10.20.16"]); // replace with your OT polling servers
DeviceNetworkEvents
| where TimeGenerated > ago(24h)
| where RemotePort == 102
| extend IsInterpreter = InitiatingProcessFileName has_any ("python", "pythonw", "powershell", "pwsh", "node", "wscript", "cscript")
| extend IsUserPath = InitiatingProcessFolderPath has_any ("\\AppData\\", "\\Users\\Public\\", "\\Temp\\", "\\Downloads\\", "\\Desktop\\")
| extend IsAuthorized = LocalIP in (AuthorizedS7Sources)
| extend SuspicionScore = toint(IsInterpreter) + toint(IsUserPath) + toint(not(IsAuthorized))
| project TimeGenerated, DeviceName, LocalIP, RemoteIP, RemotePort,
InitiatingProcessFileName, InitiatingProcessCommandLine,
InitiatingProcessFolderPath, IsInterpreter, IsUserPath, IsAuthorized, SuspicionScore
| order by SuspicionScore desc, TimeGenerated desc;
// Sweep detection: one host touching many PLCs in a short window
DeviceNetworkEvents
| where TimeGenerated > ago(1h)
| where RemotePort == 102
| summarize DistinctPLCs = dcount(RemoteIP), PLCList = make_set(RemoteIP, 50),
FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
by DeviceName, LocalIP, InitiatingProcessFileName
| where DistinctPLCs >= 5
| order by DistinctPLCs desc;
// Syslog/CEF path for firewall or OT IDS (Zeek/Suricata) telemetry ingested into Sentinel
CommonSecurityLog
| where TimeGenerated > ago(24h)
| where DestinationPort == 102
| summarize Connections = count(), DistinctSources = dcount(SourceIP), Sources = make_set(SourceIP, 25)
by DestinationIP, DeviceVendor, DeviceProduct
| order by Connections desc;
-- Velociraptor hunt artifact: identify live connections and processes
-- touching Siemens S7comm (TCP/102) across Windows endpoints
-- Artifact: Windows.Hunt.S7commRecon
-- Part 1: Live connections to/from TCP 102 with owning process
SELECT Pid, Name, Path, CommandLine,
Laddr.IP AS LocalIP, Laddr.Port AS LocalPort,
Raddr.IP AS RemoteIP, Raddr.Port AS RemotePort,
Status AS ConnStatus
FROM netstat()
WHERE (RemotePort = 102 OR LocalPort = 102)
AND Status =~ 'ESTABLISHED|SYN'
-- Part 2: Correlate with full process detail and flag interpreters/unsigned paths
SELECT Pid, Name, Exe, CommandLine, Username, CreateTime,
Authenticode.FileName AS SignedBinary,
Authenticode.Status AS SignatureStatus
FROM pslist()
WHERE Name =~ '(?i)python|powershell|pwsh|node|wscript|cscript'
OR Exe =~ '(?i)AppData|Users\\\\Public|Temp|Downloads|Desktop'
OR CommandLine =~ '(?i)snap7|s7comm|tsap|102'
-- Part 3: Stage suspicious S7 tooling dropped to disk
SELECT FullPath, Size, Mtime, Ctime
FROM glob(globs='C:/Users/*/{AppData,Downloads,Desktop}/**/*.exe')
WHERE Mtime > now() - 604800 -- written in the last 7 days
Run Part 1 and Part 2 as a joined hunt on engineering workstations, jump hosts, and any Windows systems with Layer 2/3 reachability into the OT VLAN. A python.exe or recently-dropped unsigned binary holding an ESTABLISHED session to TCP/102 on an S7 subnet is a stop-and-investigate finding in almost every environment.
Immediate IR Actions if You Find a Hit
- Isolate the source host from OT reachability (NAC quarantine or switch ACL) — do not power it off; you want memory for the AI-generated tooling, which is forensically valuable (prompt artifacts, comments, and code style can support attribution).
- Preserve the PLC side: capture the controller's diagnostic buffer and communication logs before they roll. On S7-1500, pull the diagnostic buffer via TIA Portal or web server interface immediately.
- Determine what was read or written. If any program blocks (OB/FB/FC) were uploaded or downloaded, treat the controller as potentially compromised: compare running logic against the last known-good offline project archive, block by block.
- Check protection levels. If the PLC had no read/write protection configured, assume full logic visibility for the adversary.
Remediation
There is no patch for this campaign — the "vulnerability" is unauthenticated protocol reachability. Remediation is architectural. Prioritize in this order:
1. Enforce Purdue Segmentation and Conduits (This Week)
- TCP/102 should be reachable only from an explicit allowlist: SCADA servers, historians, and designated engineering workstations. Everything else — corporate IT, guest, contractor networks — denied by default.
- Deploy or tighten stateful firewall/ACL rules at the Level 2/3 boundary. Log and alert on denied 102 attempts; reconnaissance will trip these.
- Remove dual-homed hosts bridging IT and OT. Audit for unauthorized routers, Wi-Fi bridges, and cellular modems on control networks.
2. Harden the Controllers
# S7 Exposure Audit and Windows Firewall Hardening
# Run on engineering workstations, jump hosts, and SCADA servers (as Administrator)
# Purpose: inventory who on this host talks to TCP/102, and restrict outbound
# S7comm to authorized processes only.
# --- Step 1: Audit current and historical S7 connections ---
$report = "$env:ProgramData\S7_Audit_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
Get-NetTCPConnection -RemotePort 102 -ErrorAction SilentlyContinue |
ForEach-Object {
$proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
[PSCustomObject]@{
Time = Get-Date
RemoteIP = $_.RemoteAddress
State = $_.State
ProcessName = $proc.ProcessName
ProcessPath = $proc.Path
PID = $_.OwningProcess
}
} | Export-Csv $report -NoTypeInformation
Write-Host "[+] S7 connection audit written to $report" -ForegroundColor Green
# --- Step 2: Inventory Python installs and snap7 usage (common recon tooling) ---
$pyTools = @()
Get-ChildItem "C:\Users\*\AppData\Local\Programs\Python","C:\Python*" -Directory -ErrorAction SilentlyContinue |
ForEach-Object { $pyTools += $_.FullName }
$snap7 = Get-ChildItem "C:\" -Recurse -Filter "snap7*.dll" -ErrorAction SilentlyContinue -Depth 4 |
Select-Object -ExpandProperty FullName
Write-Host "[i] Python installs found: $($pyTools -join '; ')"
Write-Host "[!] snap7 libraries found (review for legitimacy): $($snap7 -join '; ')" -ForegroundColor Yellow
# --- Step 3: Block outbound TCP/102 except from authorized S7 applications ---
# Replace paths below with your actual WinCC/TIA/SCADA executables
$allowedApps = @(
"C:\Program Files\Siemens\Automation\Portal V18\Bin\Siemens.Simatic.*.exe",
"C:\Program Files (x86)\Siemens\WinCC\bin\CCProjectMgr.exe"
)
# Default-deny outbound 102 (adjust rule scope to your OT VLANs, e.g. -RemoteAddress 10.20.0.0/16)
New-NetFirewallRule -DisplayName "OT-Deny-Outbound-S7comm-Default" `
-Direction Outbound -Protocol TCP -RemotePort 102 `
-Action Block -Profile Any -Enabled True
foreach ($app in $allowedApps) {
if (Test-Path (Split-Path $app -Parent)) {
New-NetFirewallRule -DisplayName "OT-Allow-S7comm-$([IO.Path]::GetFileNameWithoutExtension($app))" `
-Direction Outbound -Protocol TCP -RemotePort 102 -Program $app `
-Action Allow -Profile Any -Enabled True
}
}
Write-Host "[+] Outbound S7comm restricted to allowlisted applications" -ForegroundColor Green
# --- Step 4: Enable firewall logging for denied 102 attempts (feeds your SIEM) ---
Set-NetFirewallProfile -Profile Domain,Private,Public `
-LogBlocked True -LogFileName "%systemroot%\system32\LogFiles\Firewall\pfirewall.log" `
-LogMaxSizeKilobytes 32767
- Enable access protection on every S7 CPU. For S7-1500/1200, configure "Full access protection (no legacy support)" and require passwords for HMI/engineering access per the Siemens Industrial Security guidelines. For S7-300/400, set write protection at minimum and plan migration — the legacy protection is bypassable.
- Disable unused services on the CPU (web server, OPC UA, PUT/GET if not required). Note: PUT/GET access is required by many legacy HMIs — where it isn't, disable it; it is the primary read/write vector these scripts abuse.
- Update CPU firmware to current Siemens releases per Siemens ProductCERT advisories — recent S7-1500 firmware adds improved integrity checks and security event logging.
3. Deploy Protocol-Aware OT Monitoring (This Quarter)
- Passive ICS IDS (Zeek with the ICSNPP S7comm analyzer, Suricata with ET ICS rules, or commercial platforms like Claroty/Nozomi/Dragos) at the Level 2 aggregation switch via SPAN/TAP. Alert specifically on: SZL/module identification reads from non-engineering hosts, block upload/download functions, and any S7 setup from a new source MAC/IP pair.
- Baseline your legitimate polling cadence now — you cannot detect reconnaissance that mimics monitoring if you don't know what normal monitoring looks like.
4. Governance and Threat-Intel Actions
- Review the U.S. government advisory and any associated CISA ICS advisory; subscribe to CISA ICS alerts and Siemens ProductCERT feeds.
- Brief your OT engineering team: reconnaissance disguised as monitoring means their tools and their credentials are the cover story. Enforce MFA and just-in-time access on engineering workstations; no standing OT access from IT-side accounts.
- Add "unexpected S7comm source" to your incident response playbooks with the isolation and PLC-forensics steps above.
Closing Assessment
The headline here isn't that attackers found a new bug — it's that AI-assisted tooling has industrialized OT reconnaissance. Scripts that once required deep S7comm expertise are now commodity artifacts, re-generated on demand, which means hash-based detection is dead for this threat class. Behavior is the durable signal: who is talking to your PLCs, from what process, doing what functions, at what cadence. If you can answer those four questions continuously, this campaign is detectable today. If you can't, that visibility gap is your real vulnerability — close it before the reconnaissance phase matures into something worse.
Related Resources
Security Arsenal Managed SOC Services AlertMonitor Platform Book a SOC Assessment soc-mdr Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.