performing-s7comm-protocol-security-analysis
对西门子SIMATIC S7 PLC使用的S7comm和S7CommPlus协议进行安全分析,识别漏洞,包括重放攻击、完整性绕过、未授权的CPU停止命令以及针对S7-300、S7-400、S7-1200和S7-1500控制器弱点的程序下载操控。
Best use case
performing-s7comm-protocol-security-analysis is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
对西门子SIMATIC S7 PLC使用的S7comm和S7CommPlus协议进行安全分析,识别漏洞,包括重放攻击、完整性绕过、未授权的CPU停止命令以及针对S7-300、S7-400、S7-1200和S7-1500控制器弱点的程序下载操控。
Teams using performing-s7comm-protocol-security-analysis should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/performing-s7comm-protocol-security-analysis/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How performing-s7comm-protocol-security-analysis Compares
| Feature / Agent | performing-s7comm-protocol-security-analysis | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
对西门子SIMATIC S7 PLC使用的S7comm和S7CommPlus协议进行安全分析,识别漏洞,包括重放攻击、完整性绕过、未授权的CPU停止命令以及针对S7-300、S7-400、S7-1200和S7-1500控制器弱点的程序下载操控。
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 执行S7comm协议安全分析
## 适用场景
- 评估西门子SIMATIC S7 PLC环境的安全态势时
- 为针对S7-300/400/1200/1500控制器的S7comm攻击构建检测规则时
- 对西门子Step 7/TIA Portal通信进行安全审计时
- 调查疑似对西门子PLC程序的未授权访问时
- 评估S7CommPlus完整性机制及其绕过可能性时
**不适用于**未经授权和测试计划扫描生产西门子PLC(可能导致控制器崩溃)、非西门子协议分析(Modbus请参见detecting-modbus-command-injection-attacks),或在生产环境中修改PLC程序。
## 前置条件
- 对S7comm通信网段(TCP端口102)的网络访问
- 带有S7comm解析器的Wireshark或带有S7comm协议分析器的Zeek
- 安全测试的授权访问(切勿在没有授权的情况下扫描生产PLC)
- 了解范围内的西门子PLC型号和固件版本
- 理解S7comm协议结构(COTP、S7 PDU、功能码)
## 工作流程
### 步骤 1:分析S7comm流量并识别漏洞
```python
#!/usr/bin/env python3
"""S7comm协议安全分析器。
分析西门子S7comm协议流量,识别安全
漏洞、未授权访问模式以及针对SIMATIC S7 PLC的
潜在攻击指示符。
"""
import struct
import sys
import json
from collections import defaultdict
from datetime import datetime
from typing import Dict, List, Optional
try:
from scapy.all import rdpcap, IP, TCP
except ImportError:
print("请安装scapy: pip install scapy")
sys.exit(1)
# S7comm ROSCTR(PDU类型)定义
S7_ROSCTR = {
0x01: "Job(请求)",
0x02: "Ack",
0x03: "Ack_Data(响应)",
0x07: "Userdata",
}
# S7comm功能码
S7_FUNCTIONS = {
0x00: "CPU服务",
0x04: "读取变量",
0x05: "写入变量",
0x1A: "请求下载(程序)",
0x1B: "下载块",
0x1C: "下载结束",
0x1D: "开始上传(读取程序)",
0x1E: "上传块",
0x1F: "上传结束",
0x28: "PI服务(启动/停止CPU)",
0x29: "PLC停止",
0xF0: "建立通信",
}
# 安全相关的关键操作
CRITICAL_FUNCTIONS = {0x1A, 0x1B, 0x1C, 0x28, 0x29, 0x05}
PROGRAM_FUNCTIONS = {0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}
class S7commSecurityFinding:
"""表示S7comm流量中的安全发现。"""
def __init__(self, severity: str, finding_type: str, src_ip: str,
dst_ip: str, function: str, description: str,
cve: str = "", recommendation: str = ""):
self.timestamp = datetime.now().isoformat()
self.severity = severity
self.finding_type = finding_type
self.src_ip = src_ip
self.dst_ip = dst_ip
self.function = function
self.description = description
self.cve = cve
self.recommendation = recommendation
class S7commAnalyzer:
"""分析S7comm协议流量中的安全漏洞。"""
def __init__(self):
self.findings: List[S7commSecurityFinding] = []
self.sessions: Dict[str, dict] = defaultdict(lambda: {
"packets": 0,
"functions_seen": set(),
"writes": 0,
"program_downloads": 0,
"cpu_commands": 0,
"first_seen": None,
"last_seen": None,
})
self.authorized_engineering: set = set()
self.packet_count = 0
def set_authorized_stations(self, ips: List[str]):
"""设置授权工程师工作站IP列表。"""
self.authorized_engineering = set(ips)
def parse_s7comm(self, payload: bytes) -> Optional[dict]:
"""从TCP有效载荷解析S7comm协议数据。"""
# TPKT报头: version(1) + reserved(1) + length(2)
if len(payload) < 4:
return None
tpkt_version = payload[0]
if tpkt_version != 3:
return None
tpkt_length = struct.unpack(">H", payload[2:4])[0]
# COTP报头紧跟TPKT之后
if len(payload) < 7:
return None
cotp_length = payload[4]
cotp_type = payload[5]
# S7comm在COTP之后开始
s7_offset = 4 + 1 + cotp_length
if len(payload) < s7_offset + 10:
return None
# S7comm报头
protocol_id = payload[s7_offset]
if protocol_id != 0x32: # S7comm魔术字节
return None
rosctr = payload[s7_offset + 1]
redundancy = struct.unpack(">H", payload[s7_offset + 2:s7_offset + 4])[0]
pdu_ref = struct.unpack(">H", payload[s7_offset + 4:s7_offset + 6])[0]
param_length = struct.unpack(">H", payload[s7_offset + 6:s7_offset + 8])[0]
data_length = struct.unpack(">H", payload[s7_offset + 8:s7_offset + 10])[0]
result = {
"rosctr": rosctr,
"rosctr_name": S7_ROSCTR.get(rosctr, f"未知 (0x{rosctr:02x})"),
"pdu_ref": pdu_ref,
"param_length": param_length,
"data_length": data_length,
}
# 从参数中解析功能码
param_offset = s7_offset + 10
if rosctr in (0x01, 0x03) and param_length > 0 and len(payload) > param_offset:
func_code = payload[param_offset]
result["function_code"] = func_code
result["function_name"] = S7_FUNCTIONS.get(func_code, f"未知 (0x{func_code:02x})")
return result
def analyze_packet(self, pkt):
"""分析数据包中的S7comm安全问题。"""
self.packet_count += 1
if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
return
tcp = pkt[TCP]
if tcp.dport != 102 and tcp.sport != 102:
return
payload = bytes(tcp.payload)
if not payload:
return
s7 = self.parse_s7comm(payload)
if not s7:
return
src_ip = pkt[IP].src
dst_ip = pkt[IP].dst
session_key = f"{src_ip}->{dst_ip}"
session = self.sessions[session_key]
session["packets"] += 1
if session["first_seen"] is None:
session["first_seen"] = float(pkt.time)
session["last_seen"] = float(pkt.time)
func_code = s7.get("function_code")
if func_code is not None:
session["functions_seen"].add(func_code)
# 检查1:未授权工程师工作站
if tcp.dport == 102 and func_code in CRITICAL_FUNCTIONS:
if self.authorized_engineering and src_ip not in self.authorized_engineering:
self.findings.append(S7commSecurityFinding(
severity="CRITICAL",
finding_type="UNAUTHORIZED_ENGINEERING_ACCESS",
src_ip=src_ip, dst_ip=dst_ip,
function=s7.get("function_name", "未知"),
description=(
f"来自未授权源 {src_ip} 的关键S7comm操作。"
f"功能: {s7.get('function_name')}。只有授权的TIA Portal "
f"工作站才能发出这些命令。"
),
recommendation="在工业防火墙处阻止未授权源。调查源主机是否被攻陷。",
))
# 检查2:CPU停止命令
if func_code == 0x29:
session["cpu_commands"] += 1
self.findings.append(S7commSecurityFinding(
severity="CRITICAL",
finding_type="CPU_STOP_COMMAND",
src_ip=src_ip, dst_ip=dst_ip,
function="PLC CPU停止 (0x29)",
description=f"已向 {dst_ip} 处的PLC发送CPU停止命令。这会停止PLC程序执行。",
cve="MITRE T0881 — 服务停止",
recommendation="验证这是否是授权的维护操作。如果不是,立即隔离源。",
))
# 检查3:程序下载
if func_code in (0x1A, 0x1B, 0x1C):
session["program_downloads"] += 1
self.findings.append(S7commSecurityFinding(
severity="CRITICAL",
finding_type="PROGRAM_DOWNLOAD",
src_ip=src_ip, dst_ip=dst_ip,
function=s7.get("function_name", "下载"),
description=(
f"向 {dst_ip} 执行PLC程序下载操作。"
f"这修改了PLC上运行的控制逻辑。"
),
cve="MITRE T0843 — 程序下载",
recommendation="对照变更管理记录验证。与已知良好的程序备份进行比对。",
))
# 检查4:写入变量操作
if func_code == 0x05:
session["writes"] += 1
# 检查5:程序上传(PLC代码泄露)
if func_code in (0x1D, 0x1E, 0x1F):
self.findings.append(S7commSecurityFinding(
severity="HIGH",
finding_type="PROGRAM_UPLOAD_EXFILTRATION",
src_ip=src_ip, dst_ip=dst_ip,
function=s7.get("function_name", "上传"),
description=f"从 {dst_ip} 进行PLC程序上传(读取)。源 {src_ip} 正在提取PLC控制逻辑。",
recommendation="验证这是否是授权的维护操作。未授权的上传表示侦察行为。",
))
def check_known_vulnerabilities(self):
"""基于观察到的行为检查已知的西门子S7漏洞。"""
vuln_checks = [
{
"name": "S7-300/400重放攻击漏洞",
"cve": "CVE-2019-13945",
"description": "S7-300/400 PLC缺乏对S7comm会话的完整性检查,允许重放攻击",
"affected": "S7-300、S7-400(所有固件版本)",
"severity": "HIGH",
},
{
"name": "S7CommPlus完整性绕过",
"cve": "研究发现(Biham等人)",
"description": "S7CommPlusV3完整性机制可被能够观察到一个合法会话的攻击者绕过",
"affected": "S7-1200(< V4.5)、S7-1500(< V2.9)",
"severity": "HIGH",
},
{
"name": "不可修补的硬件信任根",
"cve": "CVE-2022-38773",
"description": "硬件漏洞允许绕过受保护的引导程序并持久修改固件",
"affected": "S7-1500(特定硬件版本)",
"severity": "CRITICAL",
},
{
"name": "通过端口102的远程DoS",
"cve": "CVE-2019-10929",
"description": "TCP端口102上的特制数据包可以远程崩溃S7 PLC",
"affected": "S7-300、S7-400、S7-1200、S7-1500(特定固件)",
"severity": "HIGH",
},
]
return vuln_checks
def generate_report(self):
"""生成综合S7comm安全分析报告。"""
print(f"\n{'='*70}")
print("S7COMM协议安全分析报告")
print(f"{'='*70}")
print(f"分析时间: {datetime.now().isoformat()}")
print(f"已分析数据包: {self.packet_count}")
print(f"S7comm会话: {len(self.sessions)}")
print(f"安全发现: {len(self.findings)}")
print(f"\n--- 会话摘要 ---")
for key, session in self.sessions.items():
funcs = [S7_FUNCTIONS.get(f, f"0x{f:02x}") for f in session["functions_seen"]]
print(f"\n {key}")
print(f" 数据包: {session['packets']}")
print(f" 功能: {', '.join(funcs)}")
print(f" 写入次数: {session['writes']}")
print(f" 程序下载次数: {session['program_downloads']}")
print(f" CPU命令次数: {session['cpu_commands']}")
if self.findings:
print(f"\n--- 安全发现 ---")
for f in self.findings:
print(f"\n [{f.severity}] {f.finding_type}")
print(f" 源: {f.src_ip} -> {f.dst_ip}")
print(f" 功能: {f.function}")
print(f" 详情: {f.description}")
if f.cve:
print(f" 参考: {f.cve}")
if f.recommendation:
print(f" 措施: {f.recommendation}")
print(f"\n--- 已知漏洞评估 ---")
for vuln in self.check_known_vulnerabilities():
print(f"\n [{vuln['severity']}] {vuln['name']}")
print(f" CVE: {vuln['cve']}")
print(f" 受影响: {vuln['affected']}")
print(f" 详情: {vuln['description']}")
if __name__ == "__main__":
analyzer = S7commAnalyzer()
analyzer.set_authorized_stations(["10.10.2.50", "10.10.2.51"])
if len(sys.argv) >= 2:
print(f"[*] 正在分析捕获文件: {sys.argv[1]}")
packets = rdpcap(sys.argv[1])
for pkt in packets:
analyzer.analyze_packet(pkt)
analyzer.generate_report()
else:
print("用法: python s7comm_analyzer.py <capture.pcap>")
print(" 分析S7comm流量中的安全漏洞")
```
## 核心概念
| 术语 | 定义 |
|------|------|
| S7comm | 西门子专有协议,用于通过TCP端口102与SIMATIC S7 PLC通信,基于COTP/TPKT协议栈 |
| S7CommPlus | S7comm的增强版本,用于S7-1200/1500,具有完整性保护机制 |
| ROSCTR | S7comm报头中的远程操作服务控制字段,指示PDU类型(Job、Ack、Ack_Data、Userdata) |
| TIA Portal | 全集成自动化门户(Totally Integrated Automation Portal)——西门子用于编程S7 PLC的工程软件 |
| CPU停止(0x29) | 停止PLC程序执行的S7comm功能,是一种关键的拒绝服务操作 |
| 程序下载(0x1A) | 启动向PLC传输新控制逻辑的S7comm功能,代表最高风险操作 |
## 常见场景
### 场景:未授权PLC程序修改
**背景**:Dragos传感器对来自非授权TIA Portal工程师工作站IP地址的S7comm程序下载流量发出警报。
**方法**:
1. 捕获完整的S7comm会话进行取证分析
2. 识别源主机并确定其是否被攻陷或为恶意设备
3. 将当前PLC程序与最后一个已知良好备份进行对比
4. 检查PLC CPU模式是否发生变化(运行→停止→编程)
5. 如果程序被修改,从已验证的备份中恢复
6. 调查攻击链——攻击者如何到达S7comm网段
7. 在所有PLC上实施S7comm访问保护(知识保护、访问密码)
**注意事项**:S7-300/400 PLC没有密码学完整性保护——任何能够到达TCP端口102的设备都可以发送命令。不要仅依赖PLC密码,因为它们在S7comm中以明文传输(非S7CommPlus)。网络分段是主要防御手段。
## 输出格式
```
S7COMM安全分析报告
===================================
日期: YYYY-MM-DD
范围: [已分析的网段]
会话清单:
工程师工作站: [数量和IP]
通信中的PLC: [数量和IP]
未授权源: [数量]
关键发现:
CPU停止命令: [数量]
程序下载: [来自未授权源的数量]
重放攻击可能性: [评估]
漏洞评估:
S7-300/400(无完整性保护): [受影响PLC数量]
S7-1200/1500(S7CommPlus): [固件评估]
适用的已知CVE: [列表]
建议:
1. [最高优先级修复措施]
2. [网络分段改进]
3. [监控增强]
```Related Skills
triaging-security-incident
使用 NIST SP 800-61r3 和 SANS PICERL 框架对安全事件进行初始分类,确定严重性、范围和所需响应行动。 按类型对事件分类,根据业务影响分配优先级,并路由到相应的响应团队。适用于事件分类、 安全告警分类、严重性评估、事件优先级排序或初始事件分析等请求场景。
triaging-security-incident-with-ir-playbook
使用结构化 IR Playbook 对安全事件进行分类和优先排序,确定严重性、分配响应团队并启动适当的响应程序。
triaging-security-alerts-in-splunk
在 Splunk Enterprise Security 中对安全告警进行分类,通过 SPL 查询和事件审查(Incident Review) 仪表板对重要事件进行严重性分类、调查、关联相关遥测并做出升级或关闭决策。 适用于 SOC 分析师需要处理关联搜索产生的告警队列、确定调查优先级, 或需要为交接给二/三级分析师记录分类决策时。
testing-websocket-api-security
测试 WebSocket API 实现中的安全漏洞,包括 WebSocket 升级时缺少身份认证、跨站 WebSocket 劫持(Cross-Site WebSocket Hijacking,CSWSH)、通过 WebSocket 消息进行的注入攻击、输入校验不足、通过消息泛洪实施拒绝服务,以及通过 WebSocket 帧造成的信息泄露。测试人员使用 Burp Suite 拦截 WebSocket 握手和消息,构造恶意 payload,并测试 WebSocket 通道上的授权绕过。适用于 WebSocket 安全测试、WS 渗透测试、CSWSH 攻击或实时 API 安全评估相关请求。
testing-jwt-token-security
在安全测试活动中,评估 JSON Web Token(JWT)实现中的密码学弱点、算法混淆攻击和授权绕过漏洞。
testing-api-security-with-owasp-top-10
使用自动化和手工测试技术,针对 OWASP API 安全 Top 10 风险对 REST 和 GraphQL API 端点进行系统性评估。
performing-yara-rule-development-for-detection
通过识别可执行文件中的唯一字节模式、字符串和行为指标,开发精准的 YARA 恶意软件检测规则,同时将误报率降至最低。
performing-wireless-security-assessment-with-kismet
使用 Kismet 通过被动射频监控进行无线网络安全评估,检测流氓接入点(Rogue AP)、隐藏 SSID、弱加密和未授权客户端。
performing-wireless-network-penetration-test
执行无线网络渗透测试,通过捕获握手包、破解 WPA2/WPA3 密钥、检测流氓接入点以及使用 Aircrack-ng 和相关工具测试无线网络分段,评估 WiFi 安全性。
performing-windows-artifact-analysis-with-eric-zimmerman-tools
使用 Eric Zimmerman 的开源 EZ Tools 套件(包括 KAPE、MFTECmd、PECmd、LECmd、JLECmd 和 Timeline Explorer)执行全面的 Windows 取证制品分析,解析注册表 hive、预取文件、事件日志和文件系统元数据。
performing-wifi-password-cracking-with-aircrack
在授权无线安全评估中捕获 WPA/WPA2 握手包,并使用 aircrack-ng、hashcat 和字典攻击进行离线密码破解, 以评估密码短语强度和无线网络安全状况。
performing-web-cache-poisoning-attack
在授权安全测试期间,通过未纳入缓存键的头部和参数毒化缓存响应,利用 Web 缓存机制向其他用户投递恶意内容。