securing-historian-server-in-ot-environment

本技能涵盖在OT环境中加固和保护过程历史数据服务器(OSIsoft PI、Honeywell PHD、GE Proficy、AVEVA Historian)。涉及跨Purdue模型各层级的网络部署、历史数据服务器接口的访问控制、通过数据二极管或PI-to-PI连接器在DMZ中进行数据复制、历史数据查询中的SQL注入防护,以及用于安全分析、法规报告和过程优化的过程数据完整性保护。

9 stars

Best use case

securing-historian-server-in-ot-environment is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

本技能涵盖在OT环境中加固和保护过程历史数据服务器(OSIsoft PI、Honeywell PHD、GE Proficy、AVEVA Historian)。涉及跨Purdue模型各层级的网络部署、历史数据服务器接口的访问控制、通过数据二极管或PI-to-PI连接器在DMZ中进行数据复制、历史数据查询中的SQL注入防护,以及用于安全分析、法规报告和过程优化的过程数据完整性保护。

Teams using securing-historian-server-in-ot-environment 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/securing-historian-server-in-ot-environment/SKILL.md --create-dirs "https://raw.githubusercontent.com/killvxk/cybersecurity-skills-zh/main/skills/securing-historian-server-in-ot-environment/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/securing-historian-server-in-ot-environment/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How securing-historian-server-in-ot-environment Compares

Feature / Agentsecuring-historian-server-in-ot-environmentStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

本技能涵盖在OT环境中加固和保护过程历史数据服务器(OSIsoft PI、Honeywell PHD、GE Proficy、AVEVA Historian)。涉及跨Purdue模型各层级的网络部署、历史数据服务器接口的访问控制、通过数据二极管或PI-to-PI连接器在DMZ中进行数据复制、历史数据查询中的SQL注入防护,以及用于安全分析、法规报告和过程优化的过程数据完整性保护。

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环境中部署新历史数据服务器并从一开始进行安全配置时
- 在安全评估将现有历史数据服务器识别为高风险目标后对其进行加固时
- 设计通过DMZ进行历史数据复制的架构以供IT访问过程数据时
- 实施访问控制以防止未授权修改历史过程数据时
- 调查疑似历史数据服务器入侵或数据完整性问题时

**不适用于**没有OT数据的纯IT数据库安全(参见通用数据库加固)、实时SCADA数据传输安全(参见detecting-attacks-on-scada-systems),或历史数据服务器的选型和容量规划决策。

## 前置条件

- 历史数据服务器平台(OSIsoft PI、Honeywell PHD、GE Proficy、AVEVA Historian)已安装并运行
- 按Purdue模型将历史数据服务器置于第3层(站点运营)的网络分段
- 了解数据流:现场设备 -> PLC -> OPC服务器 -> 历史数据服务器
- 历史数据服务器管理凭据访问权限
- 用于面向IT的数据复制的DMZ基础设施

## 工作流程

### 步骤 1:审计当前历史数据服务器安全配置

评估历史数据服务器当前的安全态势,包括网络暴露、认证和访问控制。

```python
#!/usr/bin/env python3
"""历史数据服务器安全审计工具。

评估过程历史数据服务器的安全配置,
包括网络暴露、认证、访问控制
和数据完整性保护。
"""

import json
import socket
import ssl
import subprocess
import sys
from dataclasses import dataclass, field, asdict
from datetime import datetime


@dataclass
class AuditFinding:
    finding_id: str
    severity: str
    category: str
    title: str
    detail: str
    remediation: str


class HistorianSecurityAudit:
    """OT历史数据服务器安全审计。"""

    def __init__(self, historian_ip, historian_type="PI"):
        self.ip = historian_ip
        self.type = historian_type
        self.findings = []
        self.counter = 1

    def check_network_exposure(self):
        """检查历史数据服务器暴露的网络服务。"""
        print(f"[*] 正在检查网络暴露: {self.ip}")

        # 常见历史数据服务器端口
        ports_to_check = {
            5450: ("PI Data Archive", "PI SDK/API连接"),
            5457: ("PI AF Server", "PI资产框架"),
            5459: ("PI Notifications", "PI通知服务"),
            443: ("HTTPS", "PI Vision / Web API"),
            80: ("HTTP", "未加密Web界面"),
            1433: ("MS SQL Server", "直接数据库访问"),
            5432: ("PostgreSQL", "直接数据库访问"),
            3389: ("RDP", "远程桌面"),
            135: ("RPC", "Windows RPC"),
            445: ("SMB", "Windows文件共享"),
            8080: ("HTTP Alt", "备用Web界面"),
        }

        exposed = []
        for port, (service, desc) in ports_to_check.items():
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(3)
                result = sock.connect_ex((self.ip, port))
                sock.close()
                if result == 0:
                    exposed.append({"port": port, "service": service, "description": desc})
            except Exception:
                pass

        # 标记不必要的暴露服务
        for svc in exposed:
            if svc["port"] in (80, 135, 445, 3389):
                self.findings.append(AuditFinding(
                    finding_id=f"HIST-{self.counter:03d}",
                    severity="high",
                    category="网络暴露",
                    title=f"不必要的服务暴露: {svc['service']}(端口 {svc['port']})",
                    detail=f"端口 {svc['port']}({svc['description']})在历史数据服务器上可访问",
                    remediation=f"禁用 {svc['service']} 或通过主机防火墙限制访问",
                ))
                self.counter += 1

        if any(s["port"] == 80 for s in exposed):
            self.findings.append(AuditFinding(
                finding_id=f"HIST-{self.counter:03d}",
                severity="high",
                category="加密",
                title="历史数据服务器Web界面在未加密的HTTP上",
                detail="端口80(HTTP)已开放,在明文中暴露凭据和数据",
                remediation="将HTTP重定向到HTTPS;禁用端口80",
            ))
            self.counter += 1

        return exposed

    def check_authentication(self):
        """检查历史数据服务器认证配置。"""
        print(f"[*] 正在检查认证配置")

        # 检查PI Trust认证是否仍然启用(旧版,不安全)
        # PI Trust允许基于IP的认证,无需凭据
        checks = [
            {
                "check": "PI Trust认证",
                "risk": "PI Trust允许仅基于IP地址的连接,无需凭据",
                "severity": "critical",
                "remediation": "将所有PI Trust连接迁移到Windows集成安全",
            },
            {
                "check": "默认piadmin账户",
                "risk": "默认PI管理员账户可能使用默认或弱密码",
                "severity": "critical",
                "remediation": "禁用piadmin;使用带PI映射的命名Windows账户",
            },
            {
                "check": "PI SDK匿名访问",
                "risk": "可能允许匿名PI SDK连接",
                "severity": "high",
                "remediation": "要求所有PI SDK连接进行认证",
            },
        ]

        for check in checks:
            self.findings.append(AuditFinding(
                finding_id=f"HIST-{self.counter:03d}",
                severity=check["severity"],
                category="认证",
                title=f"检查: {check['check']}",
                detail=check["risk"],
                remediation=check["remediation"],
            ))
            self.counter += 1

    def check_data_integrity(self):
        """检查数据完整性保护。"""
        print(f"[*] 正在检查数据完整性保护")

        integrity_checks = [
            AuditFinding(
                finding_id=f"HIST-{self.counter:03d}",
                severity="high",
                category="数据完整性",
                title="验证历史数据修改审计跟踪",
                detail="对历史过程数据的修改应记录修改前后的值",
                remediation="为所有数据修改启用PI审计跟踪;限制编辑权限",
            ),
            AuditFinding(
                finding_id=f"HIST-{self.counter + 1:03d}",
                severity="medium",
                category="数据完整性",
                title="验证备份完整性和恢复测试",
                detail="历史数据服务器备份应定期测试恢复能力",
                remediation="实施自动备份验证,每季度进行恢复测试",
            ),
        ]
        self.findings.extend(integrity_checks)
        self.counter += len(integrity_checks)

    def generate_report(self):
        """生成历史数据服务器安全审计报告。"""
        report = []
        report.append("=" * 70)
        report.append("历史数据服务器安全审计报告")
        report.append(f"目标: {self.ip} ({self.type})")
        report.append(f"日期: {datetime.now().isoformat()}")
        report.append("=" * 70)

        for sev in ["critical", "high", "medium", "low"]:
            findings = [f for f in self.findings if f.severity == sev]
            if findings:
                report.append(f"\n--- {sev.upper()} ({len(findings)}) ---")
                for f in findings:
                    report.append(f"  [{f.finding_id}] {f.title}")
                    report.append(f"    {f.detail}")
                    report.append(f"    修复: {f.remediation}")

        return "\n".join(report)


if __name__ == "__main__":
    target = sys.argv[1] if len(sys.argv) > 1 else "10.30.1.50"
    audit = HistorianSecurityAudit(target, "PI")
    audit.check_network_exposure()
    audit.check_authentication()
    audit.check_data_integrity()
    print(audit.generate_report())
```

### 步骤 2:加固历史数据服务器

根据供应商安全指南和IEC 62443要求应用安全加固。

```powershell
# OSIsoft PI服务器加固脚本(Windows)
# 基于OSIsoft安全最佳实践指南

# 1. 禁用PI Trust认证 — 迁移到Windows集成安全
# 在PI SMT(系统管理工具)中:
# 安全 > 映射和信任 > 删除所有Trust条目
# 改为创建Windows组的PI映射

# 2. 禁用默认piadmin账户
# 在PI SMT中: 安全 > 身份、用户和组
# 将piadmin账户设置为禁用

# 3. 为PI服务器配置Windows防火墙
New-NetFirewallRule -DisplayName "PI Data Archive" -Direction Inbound `
    -Protocol TCP -LocalPort 5450 -Action Allow `
    -RemoteAddress "10.30.0.0/16","10.20.0.0/16" `
    -Description "仅允许来自OT区域的PI SDK连接"

New-NetFirewallRule -DisplayName "PI AF Server" -Direction Inbound `
    -Protocol TCP -LocalPort 5457 -Action Allow `
    -RemoteAddress "10.30.0.0/16" `
    -Description "允许来自运营区域的PI AF连接"

New-NetFirewallRule -DisplayName "PI Vision HTTPS" -Direction Inbound `
    -Protocol TCP -LocalPort 443 -Action Allow `
    -RemoteAddress "172.16.0.0/16" `
    -Description "仅允许来自DMZ的PI Vision HTTPS"

# 阻止HTTP(强制使用HTTPS)
New-NetFirewallRule -DisplayName "Block HTTP" -Direction Inbound `
    -Protocol TCP -LocalPort 80 -Action Block

# 仅允许从授权源进行RDP
New-NetFirewallRule -DisplayName "RDP Restrict" -Direction Inbound `
    -Protocol TCP -LocalPort 3389 -Action Allow `
    -RemoteAddress "10.30.1.100" `
    -Description "仅允许从管理跳板机进行RDP"

# 4. 启用Windows审计策略以符合CIP-007要求
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Account Lockout" /success:enable /failure:enable
auditpol /set /subcategory:"File System" /success:enable /failure:enable
auditpol /set /subcategory:"Registry" /success:enable /failure:enable

# 5. 配置PI审计跟踪以确保数据完整性
# 在PI SMT中: 审计 > 启用安全变更审计
# 为以下项启用审计: 点创建/删除、数据编辑、安全变更
```

### 步骤 3:实施通过DMZ的安全数据复制

配置通过DMZ的历史数据复制,使用PI-to-PI接口或数据二极管为IT提供对过程数据的访问,而无需暴露OT历史数据服务器。

```yaml
# 历史数据服务器DMZ复制架构
#
# OT历史数据服务器(第3层)--> 数据二极管 --> DMZ历史数据服务器(第3.5层)<-- 企业网络(第4层)
#
# 关键原则:企业用户永远不直接连接到OT历史数据服务器。
# 数据单向从OT流向DMZ。

architecture:
  ot_historian:
    location: "第3层 — 站点运营"
    server: "PI-OT-01 (10.30.1.50)"
    role: "从OPC服务器和PLC收集原始数据"
    access: "仅限OT操作员和工程师"

  data_diode:
    location: "第3层和第3.5层之间"
    device: "Waterfall Security单向网关"
    direction: "OT -> DMZ(物理强制单向)"
    protocol: "PI-to-PI复制协议"

  dmz_historian:
    location: "第3.5层 — DMZ"
    server: "PI-DMZ-01 (172.16.1.50)"
    role: "用于企业访问的OT历史数据服务器只读镜像"
    access: "企业用户通过PI Vision(HTTPS)"
    data_delay: "近实时(通常5-30秒延迟)"

  enterprise_access:
    method: "DMZ历史数据服务器上的PI Vision Web应用程序"
    authentication: "带MFA的Windows集成安全"
    protocol: "HTTPS(TLS 1.2+)"
    restrictions:
      - "对过程数据的只读访问"
      - "不具备向OT历史数据服务器写回的能力"
      - "不允许直接数据库查询 — 仅通过PI Vision API"
      - "不活跃30分钟后会话超时"
```

## 核心概念

| 术语 | 定义 |
|------|------|
| 过程历史数据服务器(Process Historian) | 以高频率(亚秒到秒级)从工业控制系统收集、存储和提供时间序列过程数据的服务器 |
| PI Trust | 基于IP地址/主机名的旧版OSIsoft PI认证方法;不安全,应迁移到Windows集成安全 |
| 数据二极管(Data Diode) | 硬件强制的单向网关,确保历史数据仅从OT流向DMZ,防止反向访问 |
| PI-to-PI接口(PI-to-PI Interface) | OSIsoft复制机制,在服务器之间同步PI数据,用于DMZ数据镜像 |
| 审计跟踪(Audit Trail) | 历史数据服务器功能,记录对历史数据的所有修改,包含修改前后的值、用户身份和时间戳 |
| 标签安全(Tag Security) | PI中基于每个标签的访问控制,决定哪些用户/应用程序可以读取或写入特定过程数据点 |

## 工具和系统

- **OSIsoft PI Server**: AVEVA(原OSIsoft)开发的行业领先过程历史数据服务器,在90%以上的大型工业设施中使用
- **AVEVA Historian**: 具有类SQL查询界面的过程数据时间序列数据库
- **Waterfall Security**: 用于单向历史数据复制的硬件数据二极管
- **PI Vision**: 基于Web的PI数据可视化工具,部署在DMZ中供企业访问

## 输出格式

```
历史数据服务器安全评估报告
=====================================
历史数据服务器: [类型和版本]
服务器: [主机名/IP]
网络区域: [Purdue层级]

认证:
  PI Trust条目: [N](应为0)
  默认账户: [启用/禁用]
  Windows认证: [启用/禁用]

网络暴露:
  开放端口: [列表]
  不必要的服务: [列表]

数据完整性:
  审计跟踪: [启用/禁用]
  备份已测试: [日期]

DMZ复制:
  方法: [PI-to-PI / 数据二极管 / VPN]
  方向: [单向 / 双向]
```

Related Skills

securing-serverless-functions

9
from killvxk/cybersecurity-skills-zh

本技能涵盖 AWS Lambda、Azure Functions 和 Google Cloud Functions 等无服务器计算平台的安全加固,涉及最小权限 IAM 角色、依赖漏洞扫描、密钥管理集成、输入验证、函数 URL 认证以及运行时监控,以防范注入攻击、凭证窃取和供应链攻击。

securing-remote-access-to-ot-environment

9
from killvxk/cybersecurity-skills-zh

本技能涵盖为操作员、工程师和供应商实施OT/ICS环境的安全远程访问,同时防止可能危害工业运营的未授权访问。涉及跳板服务器架构、多因素认证、会话记录、特权访问管理、供应商远程访问控制,以及符合IEC 62443和NERC CIP-005远程访问要求。

securing-kubernetes-on-cloud

9
from killvxk/cybersecurity-skills-zh

本技能涵盖通过实施 Pod 安全标准(Pod Security Standards)、网络策略、工作负载身份、RBAC 权限控制、镜像准入控制和运行时安全监控,对 EKS、AKS 和 GKE 上的托管 Kubernetes 集群进行加固。涉及云平台特定安全功能,包括 EKS 的 IRSA、GKE 的工作负载身份(Workload Identity)以及 AKS 的托管身份(Managed Identity)。

securing-helm-chart-deployments

9
from killvxk/cybersecurity-skills-zh

通过验证 Chart 完整性、扫描模板中的错误配置并在 Kubernetes 发布中强制执行安全上下文,保护 Helm Chart 部署安全。

securing-github-actions-workflows

9
from killvxk/cybersecurity-skills-zh

本技能涵盖加固 GitHub Actions 工作流以防范供应链攻击、凭据盗窃和权限提升。 内容包括将 action 固定到 SHA 摘要、最小化 GITHUB_TOKEN 权限、防止机密泄露、 防止工作流表达式中的脚本注入,以及为工作流变更实施必要的审阅者机制。

securing-container-registry-with-harbor

9
from killvxk/cybersecurity-skills-zh

Harbor 是一个开源容器镜像仓库,提供安全功能包括漏洞扫描(集成 Trivy)、镜像签名(Notary/Cosign)、RBAC、内容信任策略(Content Trust)、复制和审计日志。配置这些功能以强制执行镜像来源验证、防止有漏洞镜像部署并维护仓库访问控制。

securing-container-registry-images

9
from killvxk/cybersecurity-skills-zh

通过使用 Trivy 和 Grype 实施漏洞扫描、使用 Cosign 和 Sigstore 强制执行镜像签名、配置镜像仓库访问控制,以及构建阻止部署未扫描或未签名镜像的 CI/CD 流水线,来保护容器仓库(Container Registry)中的镜像安全。

securing-aws-iam-permissions

9
from killvxk/cybersecurity-skills-zh

本技能引导从业者加固 AWS 身份和访问管理(Identity and Access Management)配置,在云账户中强制执行最小权限(Least Privilege)访问。涵盖 IAM 策略范围界定、权限边界(Permission Boundary)、Access Analyzer 集成和凭据轮换策略,以降低受损身份的影响范围。

securing-api-gateway-with-aws-waf

9
from killvxk/cybersecurity-skills-zh

通过配置 OWASP Top 10 防护托管规则组(Managed Rule Group)、创建自定义速率限制规则、实施机器人(Bot)控制、设置 IP 信誉过滤以及监控 WAF 指标,使用 AWS WAF 保护 API Gateway 端点。

performing-serverless-function-security-review

9
from killvxk/cybersecurity-skills-zh

对 AWS Lambda、Azure Functions 和 GCP Cloud Functions 中的无服务器函数(Serverless Function)执行安全审查,识别过度宽松的执行角色(Execution Role)、不安全的环境变量、注入漏洞和缺失的运行时保护措施。

implementing-taxii-server-with-opentaxii

9
from killvxk/cybersecurity-skills-zh

部署和配置 OpenTAXII 服务器,使用 TAXII 2.1 协议共享和消费 STIX 格式的网络威胁情报,实现组织间的自动化指标交换。

implementing-delinea-secret-server-for-pam

9
from killvxk/cybersecurity-skills-zh

为特权访问管理(PAM)实施 Delinea Secret Server,包括 密钥库配置、基于角色的访问策略、自动密码轮换、 会话录制,以及与 Active Directory 和云平台的集成。 适用于 PAM 部署、特权凭据保管、 密钥服务器管理或密码轮换自动化相关请求。