| name | performing-ot-vulnerability-scanning-safely |
| description | 使用被动监控、原生协议查询和经过精心控制的Tenable OT Security主动扫描,在OT/ICS环境中安全执行漏洞扫描,在不破坏工业过程或导致旧版控制器崩溃的情况下识别漏洞。
|
| domain | cybersecurity |
| subdomain | ot-ics-security |
| tags | ["ot-security","ics","vulnerability-scanning","tenable","nessus","passive-scanning","risk-management","nist"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
安全执行OT漏洞扫描
适用场景
- 在带有旧版控制器的OT环境中进行漏洞评估时
- 在不影响过程可用性的情况下实施持续漏洞监控时
- 准备需要漏洞数据的IEC 62443或NERC CIP合规审计时
- 评估OT资产的基于风险的补丁优先级时
- 验证补偿控制措施是否保护了未打补丁的ICS设备时
不适用于对生产PLC进行激进主动扫描(可能导致旧版控制器崩溃)、在OT网络上使用标准Nessus配置文件进行IT漏洞扫描,或对生产OT系统进行渗透测试(参见performing-ics-penetration-testing)。
前置条件
- Tenable OT Security(原Tenable.ot/Indegy)或同等OT安全扫描平台
- 在OT网段SPAN/TAP上部署的被动监控传感器
- 在生产使用前针对每种设备类型经实验室测试验证的扫描配置文件
- 任何主动扫描的变更管理审批和维护窗口
- 供应商保修验证,确认扫描不会使支持协议失效
工作流程
步骤 1:部署被动漏洞检测
被动监控在不向OT设备发送任何数据包的情况下识别漏洞。
"""OT安全漏洞扫描协调器。
协调被动监控、原生协议查询和精心控制的主动扫描,
在不破坏工业运营的情况下进行OT漏洞评估。
"""
import json
import csv
import sys
from datetime import datetime
from typing import Dict, List, Optional
try:
import requests
except ImportError:
print("安装requests: pip install requests")
sys.exit(1)
class OTVulnerabilityScanner:
"""安全OT漏洞扫描协调器。"""
SCAN_SAFETY_LEVELS = {
"passive": {
"description": "仅观察网络流量,对设备零风险",
"risk_level": "无",
"methods": ["流量指纹", "协议分析", "版本检测"],
"requires_window": False,
},
"native_query": {
"description": "使用原生工业协议查询设备",
"risk_level": "极低",
"methods": ["modbus_device_id", "s7_szl_read", "cip_identity", "bacnet_whois"],
"requires_window": True,
},
"controlled_active": {
"description": "使用OT安全配置文件进行标准漏洞检查",
"risk_level": ,
: [, , ],
: ,
},
}
():
.tenable_url = tenable_url.rstrip()
.session = requests.Session()
.session.headers.update({
: ,
: ,
})
.session.verify = verify_ssl
.findings = []
() -> :
checks = {
: scan_level,
: target_subnet,
: .SCAN_SAFETY_LEVELS[scan_level],
: [],
: [],
: ,
}
prerequisites = [
{
: ,
: ,
: [, ],
},
{
: ,
: ,
: [, ],
},
{
: ,
: ,
: [, ],
},
{
: ,
: ,
: [],
},
{
: ,
: ,
: [],
},
{
: ,
: ,
: [, , ],
},
]
prereq prerequisites:
scan_level prereq[]:
checks[].append(prereq[])
checks
():
()
()
:
resp = .session.get(
,
params={: site_id}
)
resp.raise_for_status()
assets = resp.json().get(, [])
asset assets:
asset_id = asset.get()
vuln_resp = .session.get(
)
vuln_resp.status_code == :
vulns = vuln_resp.json().get(, [])
vuln vulns:
.findings.append({
: asset.get(, ),
: asset.get(, ),
: asset.get(, ),
: asset.get(, ),
: vuln.get(, ),
: vuln.get(, ),
: vuln.get(, ),
: vuln.get(, ),
: ,
: vuln.get(, ),
})
()
requests.RequestException e:
()
():
.findings.sort(key= x: x.get(, ), reverse=)
()
()
()
()
()
severity_counts = {}
f .findings:
sev = f.get(, )
severity_counts[sev] = severity_counts.get(sev, ) +
()
sev [, , , ]:
()
()
()
i, finding (.findings[:], ):
()
()
()
()
()
()
finding.get():
()
output_file:
(output_file, , newline=) f:
writer = csv.DictWriter(f, fieldnames=.findings[].keys())
writer.writeheader()
writer.writerows(.findings)
()
__name__ == :
scanner = OTVulnerabilityScanner(
tenable_url=,
api_key=,
verify_ssl=,
)
safety_check = scanner.check_safety_prerequisites(, )
()
scanner.run_passive_assessment(site_id=)
scanner.generate_prioritized_report()
核心概念
| 术语 | 定义 |
|---|
| 被动漏洞检测(Passive Vulnerability Detection) | 通过分析镜像流量识别漏洞,而不向OT设备发送任何数据包 |
| 原生协议查询(Native Protocol Query) | 使用工业协议(Modbus FC43、S7 SZL Read、CIP Get Attribute)安全提取设备信息 |
| OT安全扫描配置文件(OT-Safe Scan Profile) | 设计并经实验室测试以避免工业控制器崩溃的漏洞扫描器配置 |
| 补偿控制(Compensating Control) | 保护未打补丁OT资产的替代安全措施(防火墙DPI、网络隔离) |
| OT背景中的CVSS | 标准CVSS评分,针对OT影响进行调整,考虑安全、可用性和物理后果 |
| Tenable OT Security | 使用被动和基于原生协议检测的专用OT漏洞管理平台 |
输出格式
OT漏洞评估报告
=====================================
日期: YYYY-MM-DD
范围: [网段]
方法: [被动/原生查询/受控主动]
漏洞摘要:
严重: [数量]
高: [数量]
中: [数量]
低: [数量]
主要风险发现:
1. [CVE] - [CVSS] - [资产] - [描述]
无法打补丁需要补偿控制的资产:
[资产] - [原因] - [推荐控制]
补丁优先级:
立即: [列表]
下次窗口: [列表]
可接受风险: [带理由的列表]