The National Security Agency, in coordination with CISA, has published advisory AA26-231a warning of an active, ongoing threat to Siemens S7 Series programmable logic controllers (PLCs). This is not a theoretical risk bulletin — it reflects observed adversary activity against operational technology (OT) environments, and the advisory is explicit that the targeting extends beyond Siemens to PLC ecosystems broadly. If you operate S7-300, S7-400, S7-1200, or S7-1500 controllers — or any PLC platform — this advisory applies to you.
PLCs sit at the bottom of the Purdue model, directly controlling physical processes: valves, motors, conveyor systems, safety interlocks. A compromised PLC is not a data-loss event — it is a physical-consequence event. Attackers who gain write access to an S7 controller can modify ladder logic, alter setpoints, force I/O states, and degrade or destroy the physical process the controller governs. The Stuxnet lesson is now fifteen years old, and the tradecraft it pioneered against S7 hardware has diffused into commodity adversary toolkits.
This post breaks down the advisory from a defender's perspective and gives you concrete detection logic, hunting queries, and hardening steps you can execute this week.
Technical Analysis
What the Advisory Tells Us
AA26-231a does not center on a single new vulnerability — it describes active targeting of the S7 platform as a system, exploiting the architectural reality that legacy S7 environments were designed for reliability, not adversarial conditions. The threat model the advisory addresses includes:
- Internet-exposed PLCs. Shodan and Censys have indexed exposed S7 devices for years. An S7 PLC reachable from the public internet on TCP/102 (ISO-TSAP / S7comm) can be interrogated, and depending on firmware and protection level, written to — with no authentication beyond the protocol's rudimentary access levels on older units.
- Unpatched firmware. Siemens has issued a long train of security advisories for the S7 family covering authentication bypass, denial of service, and memory corruption flaws in the S7comm and S7comm-Plus protocol stacks. Operators running controllers years behind on firmware are carrying known-exploitable risk.
- Weak or absent access controls. S7 protection levels (read/write protection, know-how protection) are frequently left at defaults. Engineering workstations with TIA Portal or STEP 7 often hold standing credentials and unrestricted network paths to the control layer.
- Unsigned, unmonitored ladder logic. The S7 protocol permits program upload and download from any host that can reach TCP/102 and pass the protection level. Most environments have zero integrity monitoring on PLC logic blocks — an attacker can modify a block and no alarm fires anywhere.
- Flat network architecture. The single most common enabling condition: IT and OT on a converged or lightly segmented network, letting an initial IT foothold (phishing, VPN compromise) pivot directly to the control layer.
Attack Chain — Defender's View
A typical intrusion path against an S7 environment looks like this:
- Initial access — internet-exposed PLC (direct), or IT network compromise followed by lateral movement through weak segmentation.
- Discovery — scanning for TCP/102 listeners; S7comm handshake reveals CPU model, firmware version, module identification, and protection level without authentication on legacy hardware.
- Engineering function abuse — from a compromised or rogue host, the adversary performs legitimate protocol operations: reading the program (upload), halting the CPU (STOP), or writing modified logic (download). Tools that implement S7comm client functions are openly available.
- Persistence in the process — modified Organization Blocks (OB1) or Data Blocks execute attacker logic every scan cycle. Because the change lives on the controller, IT-side remediation does not evict it.
- Impact — forced outputs, altered setpoints, CPU in STOP, or logic bombs keyed to process conditions.
Exploitation Status
CISA and NSA characterize this as an active threat — ongoing targeting, not a proof-of-concept scenario. The advisory's framing ("Defending Against an Active Threat") and the joint-agency authorship signal observed, current adversary operations. Treat this as an assumed-compromise hunting exercise, not a patch-and-forget ticket.
Detection & Response
A hard truth first: detection of S7 manipulation is largely a network-side discipline. PLCs don't run EDR. Your visibility comes from OT network monitoring, firewall logs, span-port/PCAP inspection, and the engineering workstations that legitimately talk to controllers. The detections below are built on that reality.
Sigma Rules
These rules target the Windows-side observables an OT SOC can actually collect — Sysmon network connections to the S7 service from unexpected processes or hosts, and suspicious handling of Siemens engineering project files.
---
title: Unexpected Process Connecting to S7 PLC Service (TCP 102)
id: 3f9c1a72-8b44-4d5e-9a21-7c6e2f0b1d34
status: experimental
description: Detects network connections to TCP port 102 (ISO-TSAP/S7comm) initiated by processes other than authorized Siemens engineering software. Legitimate S7 communication originates from TIA Portal, STEP 7, WinCC, or approved drivers on designated engineering workstations and HMIs. Any other process reaching port 102 may indicate rogue S7 client tooling or lateral movement toward the control layer.
references:
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa26-231a
- https://attack.mitre.org/techniques/T0883/
author: Security Arsenal
date: 2026/08/24
tags:
- attack.impact
- attack.t0883
- attack.t0865
logsource:
category: network_connection
product: windows
detection:
selection:
DestinationPort: 102
Initiated: 'true'
filter_authorized_engineering:
Image|endswith:
- '\S7tohttp.exe'
- '\S7tgtopx.exe'
- '\siemens.automation.portal.exe'
- '\S7epa.exe'
- '\rtserver.exe'
- '\CCAgent.exe'
condition: selection and not filter_authorized_engineering
falsepositives:
- Custom or third-party SCADA/HMI drivers not in the authorized list - tune the filter to your environment's approved engineering software baseline
level: high
---
title: Siemens TIA Portal or STEP 7 Project File Access by Unusual Process
id: 8d2e5b19-3c71-4f68-b5a4-9e1d7a3c5f82
status: experimental
description: Detects read or write access to Siemens automation project files (.ap*, .zap*, .s7p, .s7s, .awl) by processes outside the Siemens engineering suite. Adversaries staging logic modifications or exfiltrating control logic will touch these artifacts from non-engineering tooling such as archivers, scripts, or exfiltration utilities.
references:
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa26-231a
- https://attack.mitre.org/techniques/T0802/
author: Security Arsenal
date: 2026/08/24
tags:
- attack.collection
- attack.t0802
- attack.t0813
logsource:
category: file_event
product: windows
detection:
selection:
TargetFilename|endswith:
- '.s7p'
- '.s7s'
- '.awl'
- '.ap16'
- '.ap17'
- '.ap18'
- '.zap16'
- '.zap17'
- '.zap18'
filter_engineering_software:
Image|contains:
- '\Siemens\'
- '\Automation\'
condition: selection and not filter_engineering_software
falsepositives:
- Backup or DLP agents reading project directories - allowlist by process hash after validation
level: medium
KQL — Microsoft Sentinel / Defender
This hunt assumes you ingest firewall/OT sensor logs via CEF/Syslog and/or have Defender for Endpoint on engineering workstations and HMIs. It builds a communication baseline against TCP/102 and surfaces any source host talking to PLCs that is not a known engineering asset — the highest-signal behavioral indicator for rogue S7 client activity. Replace the watchlist name with your own inventory of authorized OT hosts.
let AuthorizedOT = externaldata(HostIP: string)
[@"https://raw.githubusercontent.com/your-org/ot-inventory/main/authorized_engineering_hosts.csv"]
with (format="csv", ignoreFirstRecord=true);
let AuthorizedIPs = toscalar(AuthorizedOT | summarize make_set(HostIP));
union isfuzzy=true
(CommonSecurityLog
| where DestinationPort == 102
| extend SrcIP = SourceIP, DstIP = DestinationIP, EvTime = TimeGenerated,
Detail = strcat(DeviceVendor, " ", DeviceProduct)),
(DeviceNetworkEvents
| where RemotePort == 102
| extend SrcIP = LocalIP, DstIP = RemoteIP, EvTime = TimeGenerated,
Detail = strcat(InitiatingProcessFileName, " (", InitiatingProcessAccountName, ")"))
| where not(SrcIP in (AuthorizedIPs))
| summarize FirstSeen = min(EvTime), LastSeen = max(EvTime),
ConnectionCount = count(), Sources = dcount(SrcIP),
Processes = make_set(Detail, 10)
by SrcIP, DstIP
| order by LastSeen desc
Run this daily against a maintained watchlist. In a properly segmented OT network, the result set should be empty — any row is a priority-one investigation.
Velociraptor VQL
Use this artifact on engineering workstations and jump hosts to enumerate live connections to the S7 service and attribute them to processes — useful both for hunting and for validating your authorized-software baseline.
-- Hunt: Enumerate active connections to S7 PLC service (TCP 102) with owning process
LET conns = SELECT Pid, Name, Family, Type, Status,
Laddr.IP AS LocalIP, Laddr.Port AS LocalPort,
Raddr.IP AS RemoteIP, Raddr.Port AS RemotePort
FROM netstat()
WHERE RemotePort = 102
SELECT c.Pid, c.Name AS ProcessName, c.Status,
c.LocalIP, c.LocalPort, c.RemoteIP, c.RemotePort,
p.Exe AS ProcessPath, p.CommandLine, p.Username
FROM conns AS c
LEFT JOIN pslist(pid = c.Pid) AS p ON true
Hardening / Verification Script
This PowerShell script is built for Windows-based OT DMZ hosts, engineering workstations, and jump servers. It (1) audits for outbound connections to TCP/102 from non-approved processes, (2) inventories local listening services that should not be exposed, and (3) verifies that Windows Firewall blocks inbound TCP/102 from untrusted subnets. Run it elevated and adapt the allowlist variables to your environment.
#Requires -RunAsAdministrator
# Security Arsenal - S7 PLC Exposure & Segmentation Audit (ref: CISA AA26-231a)
$ApprovedS7Processes = @('S7tgtopx','S7tohttp','siemens.automation.portal','rtserver','CCAgent')
$OTSubnetPattern = '^(10\.20\.|192\.168\.10\.)' # TODO: replace with your OT VLAN CIDRs
$ReportPath = "$env:TEMP\S7_Audit_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
"=== S7 PLC Audit - $(Get-Date) - Host: $env:COMPUTERNAME ===" | Out-File $ReportPath
# 1) Outbound connections to TCP/102 - flag non-approved processes
"`n[1] Outbound S7 (TCP/102) connections by process:" | Out-File $ReportPath -Append
Get-NetTCPConnection -State Established -RemotePort 102 -ErrorAction SilentlyContinue |
ForEach-Object {
$proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
$status = if ($proc.ProcessName -in $ApprovedS7Processes) { 'APPROVED' } else { '*** INVESTIGATE ***' }
"$status $($proc.ProcessName) (PID $($_.OwningProcess)) -> $($_.RemoteAddress):102" |
Out-File $ReportPath -Append
}
# 2) Check firewall posture: is inbound TCP/102 blocked except from OT subnets?
"`n[2] Firewall rules referencing TCP/102:" | Out-File $ReportPath -Append
$rules = Get-NetFirewallPortFilter -Protocol TCP -ErrorAction SilentlyContinue |
Where-Object { $_.LocalPort -eq 102 -or $_.RemotePort -eq 102 } |
ForEach-Object { $_ | Get-NetFirewallRule }
if (-not $rules) {
"NO firewall rules govern TCP/102 - creating DENY-ALL inbound rule for TCP/102." |
Out-File $ReportPath -Append
New-NetFirewallRule -DisplayName "OT-S7-Block-Inbound-TCP102" -Direction Inbound `
-Protocol TCP -LocalPort 102 -Action Block -Profile Any -Enabled True
"Rule 'OT-S7-Block-Inbound-TCP102' created." | Out-File $ReportPath -Append
} else {
$rules | Format-Table DisplayName, Direction, Action, Enabled -AutoSize |
Out-String | Out-File $ReportPath -Append
}
# 3) Local listeners that suggest unnecessary exposure
"`n[3] Local listeners on OT-relevant ports (102, 80, 443, 502):" | Out-File $ReportPath -Append
Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue |
Where-Object { $_.LocalPort -in 102,80,443,502 } |
ForEach-Object {
$proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
"LISTEN $($_.LocalAddress):$($_.LocalPort) - $($proc.ProcessName) (PID $($_.OwningProcess))" |
Out-File $ReportPath -Append
}
Write-Host "Audit complete. Report: $ReportPath"
Remediation
The advisory's mitigation list is your prioritized work plan. Sequence matters — do them in this order:
- Inventory every S7 controller. You cannot protect what you have not cataloged. Build an authoritative asset list: CPU model (S7-300/400/1200/1500), firmware version, IP address, physical location, process criticality, and network path. Cross-check against passive OT monitoring data — shadow PLCs and forgotten spares on the network are common findings.
- Apply critical Siemens security patches and firmware updates. Pull current firmware from the Siemens Industry Online Support portal and map your fleet against Siemens ProductCERT advisories. Schedule within approved maintenance windows, but treat internet-reachable or flat-network controllers as emergency-change candidates.
- Remove internet accessibility — today. Audit external perimeter, VPN concentrators, remote-access brokers, and vendor support tunnels for any path to TCP/102 or PLC web interfaces. Nothing in the control layer should be routable from the internet, full stop. Remote engineering access belongs behind a hardened jump host with MFA in the OT DMZ.
- Strengthen access controls. Enforce S7 protection levels (read/write password protection at minimum; know-how protection on intellectual-property-bearing blocks) per the Siemens S7-1200/1500 security guidelines. On the network side, restrict TCP/102 to an explicit allowlist of engineering workstations and HMIs — default-deny everything else.
- Monitor for unauthorized activity. Deploy passive OT network monitoring with S7comm/S7comm-Plus protocol dissection (Zeek with an S7 parser, or a commercial OT IDS). Alert on program upload/download function codes, PLC STOP commands, and any S7 session from a non-baselined host.
- Harden services, protocols, and ladder logic integrity. Disable unused PLC services (web server, SNMP, Telnet/FTP on legacy CPs). Establish a ladder logic integrity baseline: perform authorized program uploads, hash every block (OB, FB, FC, DB), store hashes offline, and re-verify on a schedule and after any alert. A changed block hash with no corresponding change ticket is a compromise indicator.
- Hunt for compromise indicators. Use the KQL and VQL above. Look for: S7 sessions from IT subnets, engineering software running outside maintenance windows, new user accounts or services on engineering workstations, and unexplained PLC mode transitions (RUN → STOP → RUN) in diagnostic buffer logs.
Reporting: If you identify suspected compromise of control system assets, report to CISA via the incident reporting portal or central@cisa.gov, and engage Siemens ProductCERT. Given the joint NSA/CISA authorship, defense-industrial-base and critical infrastructure operators should treat reporting expectations as elevated.
The Broader Lesson
CISA is unusually direct here: this campaign is bigger than Siemens. Rockwell, Schneider, Mitsubishi, and every other PLC vendor's installed base shares the same structural weaknesses — unauthenticated legacy protocols, infrequent firmware cycles, flat networks, and no logic-integrity monitoring. The controls above are vendor-portable. If you operate any PLC fleet, run this playbook now, not after your sector's variant of this advisory lands.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.