performing-ot-vulnerability-scanning-safely

使用被动监控、原生协议查询和经过精心控制的Tenable OT Security主动扫描,在OT/ICS环境中安全执行漏洞扫描,在不破坏工业过程或导致旧版控制器崩溃的情况下识别漏洞。

9 stars

Best use case

performing-ot-vulnerability-scanning-safely is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

使用被动监控、原生协议查询和经过精心控制的Tenable OT Security主动扫描,在OT/ICS环境中安全执行漏洞扫描,在不破坏工业过程或导致旧版控制器崩溃的情况下识别漏洞。

Teams using performing-ot-vulnerability-scanning-safely 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

$curl -o ~/.claude/skills/performing-ot-vulnerability-scanning-safely/SKILL.md --create-dirs "https://raw.githubusercontent.com/killvxk/cybersecurity-skills-zh/main/skills/performing-ot-vulnerability-scanning-safely/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/performing-ot-vulnerability-scanning-safely/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How performing-ot-vulnerability-scanning-safely Compares

Feature / Agentperforming-ot-vulnerability-scanning-safelyStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

使用被动监控、原生协议查询和经过精心控制的Tenable OT Security主动扫描,在OT/ICS环境中安全执行漏洞扫描,在不破坏工业过程或导致旧版控制器崩溃的情况下识别漏洞。

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

# 安全执行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设备发送任何数据包的情况下识别漏洞。

```python
#!/usr/bin/env python3
"""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": "低-中",
            "methods": ["credentialed_scan", "banner_grab", "service_detection"],
            "requires_window": True,
        },
    }

    def __init__(self, tenable_url: str, api_key: str, verify_ssl: bool = True):
        self.tenable_url = tenable_url.rstrip("/")
        self.session = requests.Session()
        self.session.headers.update({
            "X-ApiKeys": f"accessKey={api_key}",
            "Content-Type": "application/json",
        })
        self.session.verify = verify_ssl
        self.findings = []

    def check_safety_prerequisites(self, scan_level: str, target_subnet: str) -> dict:
        """扫描前验证安全前提条件。"""
        checks = {
            "scan_level": scan_level,
            "target": target_subnet,
            "safety_level": self.SCAN_SAFETY_LEVELS[scan_level],
            "checks_passed": [],
            "checks_failed": [],
            "approved": False,
        }

        prerequisites = [
            {
                "name": "实验室验证完成",
                "description": "扫描配置文件已在实验室环境中针对每种设备类型测试",
                "required_for": ["native_query", "controlled_active"],
            },
            {
                "name": "供应商保修已验证",
                "description": "扫描不会使供应商支持协议失效",
                "required_for": ["native_query", "controlled_active"],
            },
            {
                "name": "变更管理已审批",
                "description": "扫描活动的变更工单已批准",
                "required_for": ["native_query", "controlled_active"],
            },
            {
                "name": "维护窗口已确认",
                "description": "运营团队确认可接受的扫描窗口",
                "required_for": ["controlled_active"],
            },
            {
                "name": "回滚计划已记录",
                "description": "停止扫描并在设备无响应时恢复的程序",
                "required_for": ["controlled_active"],
            },
            {
                "name": "SIS已排除在范围之外",
                "description": "安全仪表系统永远不进行主动扫描",
                "required_for": ["passive", "native_query", "controlled_active"],
            },
        ]

        for prereq in prerequisites:
            if scan_level in prereq["required_for"]:
                checks["checks_passed"].append(prereq["name"])

        return checks

    def run_passive_assessment(self, site_id: str):
        """使用流量分析运行被动漏洞评估。"""
        print(f"[*] 对站点 {site_id} 运行被动漏洞评估")
        print(f"[*] 安全级别: 无 - 不向OT设备发送数据包")

        try:
            resp = self.session.get(
                f"{self.tenable_url}/api/v1/assets",
                params={"site_id": site_id}
            )
            resp.raise_for_status()
            assets = resp.json().get("assets", [])

            for asset in assets:
                asset_id = asset.get("id")
                vuln_resp = self.session.get(
                    f"{self.tenable_url}/api/v1/assets/{asset_id}/vulnerabilities"
                )
                if vuln_resp.status_code == 200:
                    vulns = vuln_resp.json().get("vulnerabilities", [])
                    for vuln in vulns:
                        self.findings.append({
                            "asset": asset.get("name", "未知"),
                            "ip": asset.get("ip_address", ""),
                            "type": asset.get("type", ""),
                            "vendor": asset.get("vendor", ""),
                            "cve": vuln.get("cve_id", ""),
                            "severity": vuln.get("severity", ""),
                            "cvss": vuln.get("cvss_score", 0),
                            "description": vuln.get("description", ""),
                            "detection_method": "passive",
                            "remediation": vuln.get("remediation", ""),
                        })

            print(f"[+] 被动评估完成: 发现 {len(self.findings)} 个漏洞")
        except requests.RequestException as e:
            print(f"[!] API错误: {e}")

    def generate_prioritized_report(self, output_file: str):
        """生成OT环境的基于风险优先级的漏洞报告。"""
        self.findings.sort(key=lambda x: x.get("cvss", 0), reverse=True)

        print(f"\n{'='*70}")
        print("OT漏洞评估报告")
        print(f"{'='*70}")
        print(f"日期: {datetime.now().isoformat()}")
        print(f"发现总数: {len(self.findings)}")

        severity_counts = {}
        for f in self.findings:
            sev = f.get("severity", "未知")
            severity_counts[sev] = severity_counts.get(sev, 0) + 1

        print(f"\n严重程度分布:")
        for sev in ["Critical", "High", "Medium", "Low"]:
            print(f"  {sev}: {severity_counts.get(sev, 0)}")

        # 考虑OT背景的基于风险的优先级排序
        print(f"\n--- 基于风险的优先级发现 ---")
        print(f"(按CVSS评分和OT影响排序)")
        for i, finding in enumerate(self.findings[:20], 1):
            print(f"\n  {i}. [{finding['severity']}] {finding['cve']}")
            print(f"     资产: {finding['asset']} ({finding['ip']})")
            print(f"     供应商: {finding['vendor']} | 类型: {finding['type']}")
            print(f"     CVSS: {finding['cvss']}")
            print(f"     检测方法: {finding['detection_method']}")
            print(f"     描述: {finding['description'][:100]}")
            if finding.get("remediation"):
                print(f"     修复: {finding['remediation'][:100]}")

        # 导出为CSV
        if output_file:
            with open(output_file, "w", newline="") as f:
                writer = csv.DictWriter(f, fieldnames=self.findings[0].keys())
                writer.writeheader()
                writer.writerows(self.findings)
            print(f"\n[+] 报告已导出到 {output_file}")


if __name__ == "__main__":
    scanner = OTVulnerabilityScanner(
        tenable_url="https://tenable-ot.plant.local",
        api_key="your-api-key-here",
        verify_ssl=True,
    )

    # 始终从被动评估开始
    safety_check = scanner.check_safety_prerequisites("passive", "10.10.0.0/16")
    print(f"安全前提条件: {json.dumps(safety_check, indent=2)}")

    scanner.run_passive_assessment(site_id="plant-01")
    scanner.generate_prioritized_report("ot_vulnerabilities.csv")
```

## 核心概念

| 术语 | 定义 |
|------|------|
| 被动漏洞检测(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] - [资产] - [描述]

无法打补丁需要补偿控制的资产:
  [资产] - [原因] - [推荐控制]

补丁优先级:
  立即: [列表]
  下次窗口: [列表]
  可接受风险: [带理由的列表]
```

Related Skills

testing-api-for-mass-assignment-vulnerability

9
from killvxk/cybersecurity-skills-zh

测试 API 是否存在批量赋值(mass assignment,自动绑定)漏洞——攻击者可在 API 请求中附加额外参数,从而修改本不应被访问的对象属性。测试人员识别可写端点,向请求体注入未公开字段(role、isAdmin、price、balance),验证服务器是否在未过滤的情况下将这些字段绑定到数据模型。属于 OWASP API3:2023 Broken Object Property Level Authorization 范畴。适用于批量赋值测试、参数绑定滥用、自动绑定漏洞或 API 过度发布(over-posting)相关请求。

scanning-network-with-nmap-advanced

9
from killvxk/cybersecurity-skills-zh

使用 Nmap 的脚本引擎、时序控制、规避技术和输出解析,对授权目标网络执行高级网络侦察, 发现主机、枚举服务、检测漏洞并识别操作系统。

scanning-kubernetes-manifests-with-kubesec

9
from killvxk/cybersecurity-skills-zh

使用 Kubesec 对 Kubernetes 资源清单执行安全风险分析,识别错误配置、权限提升风险以及与安全最佳实践的偏差。

scanning-infrastructure-with-nessus

9
from killvxk/cybersecurity-skills-zh

Tenable Nessus 是业界领先的漏洞扫描器,用于识别网络基础设施(包括服务器、工作站、网络设备和操作系统)中的安全弱点。

scanning-docker-images-with-trivy

9
from killvxk/cybersecurity-skills-zh

Trivy 是 Aqua Security 开源的综合性漏洞扫描器,用于检测容器镜像中操作系统软件包、语言特定依赖项的漏洞、错误配置、密钥和许可证违规,并集成到 CI/CD 流水线,支持 SARIF、CycloneDX 和 SPDX 等多种输出格式。

scanning-containers-with-trivy-in-cicd

9
from killvxk/cybersecurity-skills-zh

本技能涵盖将 Aqua Security 的 Trivy 扫描器集成到 CI/CD 流水线中,用于全面的容器镜像漏洞检测。包括扫描 Docker 镜像中的操作系统包和应用依赖 CVE、检测 Dockerfile 中的错误配置、扫描文件系统和 Git 仓库,以及建立基于严重性的质量门禁以阻止有漏洞的镜像部署。

scanning-container-images-with-grype

9
from killvxk/cybersecurity-skills-zh

使用 Anchore Grype 扫描容器镜像的已知漏洞(Vulnerability),支持基于 SBOM 的匹配和可配置的严重性阈值。

performing-yara-rule-development-for-detection

9
from killvxk/cybersecurity-skills-zh

通过识别可执行文件中的唯一字节模式、字符串和行为指标,开发精准的 YARA 恶意软件检测规则,同时将误报率降至最低。

performing-wireless-security-assessment-with-kismet

9
from killvxk/cybersecurity-skills-zh

使用 Kismet 通过被动射频监控进行无线网络安全评估,检测流氓接入点(Rogue AP)、隐藏 SSID、弱加密和未授权客户端。

performing-wireless-network-penetration-test

9
from killvxk/cybersecurity-skills-zh

执行无线网络渗透测试,通过捕获握手包、破解 WPA2/WPA3 密钥、检测流氓接入点以及使用 Aircrack-ng 和相关工具测试无线网络分段,评估 WiFi 安全性。

performing-windows-artifact-analysis-with-eric-zimmerman-tools

9
from killvxk/cybersecurity-skills-zh

使用 Eric Zimmerman 的开源 EZ Tools 套件(包括 KAPE、MFTECmd、PECmd、LECmd、JLECmd 和 Timeline Explorer)执行全面的 Windows 取证制品分析,解析注册表 hive、预取文件、事件日志和文件系统元数据。

performing-wifi-password-cracking-with-aircrack

9
from killvxk/cybersecurity-skills-zh

在授权无线安全评估中捕获 WPA/WPA2 握手包,并使用 aircrack-ng、hashcat 和字典攻击进行离线密码破解, 以评估密码短语强度和无线网络安全状况。