[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GZD0HWD87BQ4CTF2J5JMP7":3,"skill-same:01M6GZD0HWD87BQ4CTF2J5JMP7":109},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":6,"ownerHtmlUrl":58,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":59,"install":60,"resources":73},"01M6GZD0HWD87BQ4CTF2J5JMP7","performing-ot-network-security-assessment",null,"This skill covers conducting comprehensive security assessments of Operational Technology (OT) networks including SCADA systems, DCS architectures, and industrial control system communication paths. It addresses the Purdue Reference Model layers, identifies IT\u002FOT convergence risks, evaluates firewall rules between zones, and maps industrial protocol traffic (Modbus, DNP3, OPC UA, EtherNet\u002FIP) to detect misconfigurations, unauthorized connections, and attack surfaces in critical infrastructure.","micsapp\u002Fmicstec-skills","micsapp","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F82411001?v=4","01M6GWCFQ6D3PV8EHNY62NN5VW","01M6GWCFVE1PA5HG0DKC7AMFJ3",4,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"network security","performing","security assessment","performing ot network security assessment","network","assessment","security","communication","firewall","ICS-security","network-assessment","model","cybersecurity","maps","surfaces","ip","critical","paths","traffic","convergence","2026-11-10 10:12:30",false,"---\nname: performing-ot-network-security-assessment\ndescription: >\n  This skill covers conducting comprehensive security assessments of Operational\n  Technology (OT) networks including SCADA systems, DCS architectures, and industrial\n  control system communication paths. It addresses the Purdue Reference Model layers,\n  identifies IT\u002FOT convergence risks, evaluates firewall rules between zones, and\n  maps industrial protocol traffic (Modbus, DNP3, OPC UA, EtherNet\u002FIP) to detect\n  misconfigurations, unauthorized connections, and attack surfaces in critical infrastructure.\ndomain: cybersecurity\nsubdomain: ot-ics-security\ntags: [ot-security, ics, scada, industrial-control, iec62443, network-assessment]\nversion: 1.0.0\nauthor: mahipal\nlicense: Apache-2.0\n---\n\n# Performing OT Network Security Assessment\n\n## When to Use\n\n- When conducting an initial security baseline of an OT\u002FICS environment for a new client\n- When evaluating the security posture of a facility after an IT\u002FOT convergence initiative\n- When preparing for IEC 62443 or NERC CIP compliance audits\n- When assessing risk following a merger or acquisition involving industrial facilities\n- When investigating whether an OT network has been compromised or has unmonitored pathways to corporate IT\n\n**Do not use** for IT-only network assessments without OT components, for application-layer vulnerability scanning of IT web applications (see performing-web-app-penetration-test), or for active exploitation of live OT systems without explicit authorization and safety controls in place.\n\n## Prerequisites\n\n- Written authorization from the asset owner and operations management for all assessment activities\n- Understanding of the Purdue Reference Model and IEC 62443 zone\u002Fconduit architecture\n- Passive network monitoring tools (Nozomi Guardian, Dragos Platform, or Wireshark with industrial protocol dissectors)\n- Access to network diagrams, firewall rule sets, and asset inventories (or the ability to perform passive discovery)\n- Safety briefing on the physical processes controlled by the OT systems under assessment\n\n## Workflow\n\n### Step 1: Establish Assessment Scope and Safety Boundaries\n\nDefine the scope based on the Purdue Reference Model levels and identify safety-critical systems that must not be actively scanned. OT assessments differ fundamentally from IT assessments because active scanning can crash PLCs, disrupt safety instrumented systems (SIS), and cause physical harm.\n\n```yaml\n# OT Assessment Scope Definition\nassessment:\n  facility: \"Chemical Processing Plant - Site Alpha\"\n  purdue_levels_in_scope:\n    - level_0: \"Physical process sensors and actuators (passive observation only)\"\n    - level_1: \"PLCs, RTUs, safety controllers (passive only, no active scanning)\"\n    - level_2: \"HMI stations, engineering workstations, historian (limited active with approval)\"\n    - level_3: \"Site operations - OPC servers, application servers (active scanning permitted)\"\n    - level_3_5: \"DMZ - data diodes, jump servers (active scanning permitted)\"\n    - level_4: \"Enterprise IT connecting to OT (active scanning permitted)\"\n\n  safety_exclusions:\n    - \"Safety Instrumented Systems (SIS) - Triconex controllers\"\n    - \"Emergency Shutdown (ESD) systems\"\n    - \"Fire and Gas detection systems\"\n    - \"Any Level 0\u002F1 device during active production\"\n\n  authorized_activities:\n    passive:\n      - \"Network traffic capture and analysis via SPAN ports\"\n      - \"Industrial protocol deep packet inspection\"\n      - \"Wireless spectrum analysis\"\n      - \"Physical walkthrough and visual inspection\"\n    active_with_approval:\n      - \"Targeted Nmap scans of Level 2-4 systems during maintenance windows\"\n      - \"Authentication testing on HMI and engineering workstations\"\n      - \"Firewall rule verification between zones\"\n    prohibited:\n      - \"Active scanning of PLCs, RTUs, or SIS controllers\"\n      - \"Fuzzing industrial protocols on live systems\"\n      - \"Modifying PLC logic or firmware\"\n```\n\n### Step 2: Perform Passive Network Discovery and Asset Inventory\n\nDeploy passive monitoring to map all devices, communication flows, and protocols on the OT network without sending any traffic that could disrupt operations.\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"OT Network Passive Discovery and Asset Inventory Builder.\n\nUses pcap captures from SPAN ports to identify OT assets, protocols,\nand communication patterns without active scanning.\n\"\"\"\n\nimport json\nimport sys\nfrom collections import defaultdict\nfrom datetime import datetime\n\ntry:\n    from scapy.all import rdpcap, IP, TCP, UDP\n    from scapy.contrib.modbus import ModbusADURequest, ModbusADUResponse\nexcept ImportError:\n    print(\"Install scapy: pip install scapy\")\n    sys.exit(1)\n\n# Industrial protocol port mappings\nOT_PROTOCOL_PORTS = {\n    502: \"Modbus\u002FTCP\",\n    102: \"S7comm (Siemens)\",\n    44818: \"EtherNet\u002FIP (CIP)\",\n    2222: \"EtherNet\u002FIP (implicit)\",\n    4840: \"OPC UA\",\n    20000: \"DNP3\",\n    47808: \"BACnet\",\n    1911: \"Niagara Fox\",\n    789: \"Crimson v3 (Red Lion)\",\n    2404: \"IEC 60870-5-104\",\n    18245: \"GE SRTP\",\n    5094: \"HART-IP\",\n}\n\nPURDUE_LEVEL_RANGES = {\n    \"Level 0-1 (Field Devices)\": [\"10.10.0.0\u002F16\", \"192.168.10.0\u002F24\"],\n    \"Level 2 (Control Systems)\": [\"10.20.0.0\u002F16\", \"192.168.20.0\u002F24\"],\n    \"Level 3 (Site Operations)\": [\"10.30.0.0\u002F16\", \"192.168.30.0\u002F24\"],\n    \"Level 3.5 (DMZ)\": [\"172.16.0.0\u002F16\"],\n    \"Level 4 (Enterprise)\": [\"10.0.0.0\u002F16\"],\n}\n\n\ndef classify_purdue_level(ip_addr):\n    \"\"\"Classify an IP address to its Purdue Reference Model level.\"\"\"\n    from ipaddress import ip_address, ip_network\n\n    addr = ip_address(ip_addr)\n    for level, subnets in PURDUE_LEVEL_RANGES.items():\n        for subnet in subnets:\n            if addr in ip_network(subnet):\n                return level\n    return \"Unknown\"\n\n\ndef analyze_ot_pcap(pcap_file):\n    \"\"\"Analyze pcap file to discover OT assets and communication patterns.\"\"\"\n    packets = rdpcap(pcap_file)\n\n    assets = {}\n    connections = defaultdict(lambda: {\"count\": 0, \"protocols\": set(), \"ports\": set()})\n    protocol_stats = defaultdict(int)\n    cross_zone_flows = []\n\n    for pkt in packets:\n        if not pkt.haslayer(IP):\n            continue\n\n        src_ip = pkt[IP].src\n        dst_ip = pkt[IP].dst\n\n        # Track assets\n        for ip in (src_ip, dst_ip):\n            if ip not in assets:\n                assets[ip] = {\n                    \"ip\": ip,\n                    \"purdue_level\": classify_purdue_level(ip),\n                    \"protocols_observed\": set(),\n                    \"roles\": set(),\n                    \"first_seen\": str(pkt.time),\n                    \"last_seen\": str(pkt.time),\n                    \"mac\": None,\n                }\n            assets[ip][\"last_seen\"] = str(pkt.time)\n\n        # Identify OT protocols by port\n        dst_port = None\n        if pkt.haslayer(TCP):\n            dst_port = pkt[TCP].dport\n        elif pkt.haslayer(UDP):\n            dst_port = pkt[UDP].dport\n\n        if dst_port and dst_port in OT_PROTOCOL_PORTS:\n            protocol_name = OT_PROTOCOL_PORTS[dst_port]\n            protocol_stats[protocol_name] += 1\n            assets[src_ip][\"protocols_observed\"].add(protocol_name)\n            assets[dst_ip][\"protocols_observed\"].add(protocol_name)\n\n            # Determine roles\n            assets[src_ip][\"roles\"].add(\"client\u002Fmaster\")\n            assets[dst_ip][\"roles\"].add(\"server\u002Fslave\")\n\n        # Track connections\n        conn_key = (src_ip, dst_ip)\n        connections[conn_key][\"count\"] += 1\n        if dst_port:\n            connections[conn_key][\"ports\"].add(dst_port)\n            if dst_port in OT_PROTOCOL_PORTS:\n                connections[conn_key][\"protocols\"].add(OT_PROTOCOL_PORTS[dst_port])\n\n        # Detect cross-zone communication\n        src_level = classify_purdue_level(src_ip)\n        dst_level = classify_purdue_level(dst_ip)\n        if src_level != dst_level and src_level != \"Unknown\" and dst_level != \"Unknown\":\n            cross_zone_flows.append({\n                \"src\": src_ip,\n                \"src_level\": src_level,\n                \"dst\": dst_ip,\n                \"dst_level\": dst_level,\n                \"protocol\": OT_PROTOCOL_PORTS.get(dst_port, f\"port\u002F{dst_port}\"),\n            })\n\n    return {\n        \"asset_count\": len(assets),\n        \"assets\": {ip: {k: list(v) if isinstance(v, set) else v for k, v in info.items()} for ip, info in assets.items()},\n        \"protocol_distribution\": dict(protocol_stats),\n        \"total_connections\": len(connections),\n        \"cross_zone_flows\": cross_zone_flows[:50],\n    }\n\n\ndef generate_assessment_report(results):\n    \"\"\"Generate the OT network assessment findings report.\"\"\"\n    report = []\n    report.append(\"=\" * 70)\n    report.append(\"OT NETWORK PASSIVE DISCOVERY REPORT\")\n    report.append(f\"Generated: {datetime.now().isoformat()}\")\n    report.append(\"=\" * 70)\n\n    report.append(f\"\\nTotal Assets Discovered: {results['asset_count']}\")\n    report.append(f\"Total Unique Connections: {results['total_connections']}\")\n\n    report.append(\"\\n--- INDUSTRIAL PROTOCOL DISTRIBUTION ---\")\n    for proto, count in sorted(results[\"protocol_distribution\"].items(), key=lambda x: -x[1]):\n        report.append(f\"  {proto}: {count} packets\")\n\n    report.append(\"\\n--- CROSS-ZONE COMMUNICATION FLOWS ---\")\n    if results[\"cross_zone_flows\"]:\n        for flow in results[\"cross_zone_flows\"][:20]:\n            report.append(\n                f\"  {flow['src']} ({flow['src_level']}) -> \"\n                f\"{flow['dst']} ({flow['dst_level']}) via {flow['protocol']}\"\n            )\n    else:\n        report.append(\"  No cross-zone flows detected (check subnet classifications)\")\n\n    report.append(\"\\n--- FINDINGS ---\")\n    # Check for Level 4 to Level 0-1 direct connections (critical finding)\n    for flow in results[\"cross_zone_flows\"]:\n        if \"Level 4\" in flow[\"src_level\"] and \"Level 0-1\" in flow[\"dst_level\"]:\n            report.append(\n                f\"  [CRITICAL] Direct Enterprise-to-Field traffic: \"\n                f\"{flow['src']} -> {flow['dst']} via {flow['protocol']}\"\n            )\n        elif \"Level 4\" in flow[\"src_level\"] and \"Level 2\" in flow[\"dst_level\"]:\n            report.append(\n                f\"  [HIGH] Enterprise-to-Control traffic bypassing DMZ: \"\n                f\"{flow['src']} -> {flow['dst']} via {flow['protocol']}\"\n            )\n\n    return \"\\n\".join(report)\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) \u003C 2:\n        print(\"Usage: python ot_network_discovery.py \u003Cpcap_file>\")\n        sys.exit(1)\n\n    results = analyze_ot_pcap(sys.argv[1])\n    print(generate_assessment_report(results))\n\n    # Save detailed JSON\n    output_file = sys.argv[1].replace(\".pcap\", \"_inventory.json\")\n    with open(output_file, \"w\") as f:\n        json.dump(results, f, indent=2, default=str)\n    print(f\"\\nDetailed inventory saved to: {output_file}\")\n```\n\n### Step 3: Evaluate Firewall Rules Between Purdue Zones\n\nAnalyze firewall configurations between OT zones to identify overly permissive rules, missing deny defaults, and unauthorized conduits that violate the IEC 62443 zone model.\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"OT Zone Firewall Rule Analyzer.\n\nParses firewall rule exports (CSV format) and evaluates them against\nIEC 62443 zone\u002Fconduit model requirements.\n\"\"\"\n\nimport csv\nimport json\nimport sys\nfrom dataclasses import dataclass, field\nfrom typing import Optional\n\n\n@dataclass\nclass FirewallRule:\n    rule_id: str\n    source_zone: str\n    source_ip: str\n    dest_zone: str\n    dest_ip: str\n    service: str\n    port: str\n    action: str\n    enabled: bool\n    comment: str = \"\"\n\n\n# IEC 62443 zone communication policy\n# Defines which zone pairs are allowed to communicate and through what conduit\nALLOWED_CONDUITS = {\n    (\"Level 4\", \"Level 3.5\"): {\n        \"allowed_ports\": [443, 3389, 22],\n        \"description\": \"Enterprise to DMZ - web services, jump hosts\",\n        \"requires_inspection\": True,\n    },\n    (\"Level 3.5\", \"Level 3\"): {\n        \"allowed_ports\": [443, 1433, 5432, 8080],\n        \"description\": \"DMZ to Site Ops - historian mirror, OPC relay\",\n        \"requires_inspection\": True,\n    },\n    (\"Level 3\", \"Level 2\"): {\n        \"allowed_ports\": [502, 44818, 4840, 102],\n        \"description\": \"Site Ops to Control - OPC UA, Modbus, S7comm\",\n        \"requires_inspection\": True,\n    },\n    (\"Level 2\", \"Level 1\"): {\n        \"allowed_ports\": [502, 44818, 102, 2222],\n        \"description\": \"Control to Field - direct industrial protocols\",\n        \"requires_inspection\": False,\n    },\n}\n\n# Prohibited direct connections\nPROHIBITED_CONDUITS = [\n    (\"Level 4\", \"Level 3\"),\n    (\"Level 4\", \"Level 2\"),\n    (\"Level 4\", \"Level 1\"),\n    (\"Level 4\", \"Level 0\"),\n    (\"Level 3\", \"Level 1\"),\n    (\"Level 3\", \"Level 0\"),\n    (\"Internet\", \"Level 3.5\"),\n    (\"Internet\", \"Level 3\"),\n    (\"Internet\", \"Level 2\"),\n    (\"Internet\", \"Level 1\"),\n]\n\n\ndef parse_firewall_rules(csv_file):\n    \"\"\"Parse firewall rules from CSV export.\"\"\"\n    rules = []\n    with open(csv_file, \"r\") as f:\n        reader = csv.DictReader(f)\n        for row in reader:\n            rules.append(FirewallRule(\n                rule_id=row.get(\"rule_id\", \"\"),\n                source_zone=row.get(\"source_zone\", \"\"),\n                source_ip=row.get(\"source_ip\", \"\"),\n                dest_zone=row.get(\"dest_zone\", \"\"),\n                dest_ip=row.get(\"dest_ip\", \"\"),\n                service=row.get(\"service\", \"\"),\n                port=row.get(\"port\", \"\"),\n                action=row.get(\"action\", \"\"),\n                enabled=row.get(\"enabled\", \"true\").lower() == \"true\",\n                comment=row.get(\"comment\", \"\"),\n            ))\n    return rules\n\n\ndef analyze_rules(rules):\n    \"\"\"Analyze firewall rules against IEC 62443 zone model.\"\"\"\n    findings = {\"critical\": [], \"high\": [], \"medium\": [], \"low\": [], \"info\": []}\n\n    for rule in rules:\n        if not rule.enabled or rule.action.lower() != \"allow\":\n            continue\n\n        zone_pair = (rule.source_zone, rule.dest_zone)\n        port = int(rule.port) if rule.port.isdigit() else 0\n\n        # Check for prohibited conduits\n        if zone_pair in PROHIBITED_CONDUITS:\n            findings[\"critical\"].append({\n                \"rule_id\": rule.rule_id,\n                \"finding\": f\"Prohibited direct connection: {rule.source_zone} -> {rule.dest_zone}\",\n                \"detail\": f\"Rule allows {rule.source_ip} to reach {rule.dest_ip}:{rule.port} ({rule.service})\",\n                \"remediation\": \"Remove rule. Route traffic through DMZ (Level 3.5) with application-layer inspection.\",\n            })\n\n        # Check for overly broad rules (any\u002Fany)\n        elif rule.source_ip in (\"any\", \"0.0.0.0\u002F0\") or rule.dest_ip in (\"any\", \"0.0.0.0\u002F0\"):\n            findings[\"high\"].append({\n                \"rule_id\": rule.rule_id,\n                \"finding\": f\"Overly permissive rule with 'any' address\",\n                \"detail\": f\"{rule.source_ip} -> {rule.dest_ip}:{rule.port} in {zone_pair}\",\n                \"remediation\": \"Restrict to specific host IPs per IEC 62443 least-privilege conduit policy.\",\n            })\n\n        # Check allowed conduits for port violations\n        elif zone_pair in ALLOWED_CONDUITS:\n            conduit = ALLOWED_CONDUITS[zone_pair]\n            if port and port not in conduit[\"allowed_ports\"]:\n                findings[\"medium\"].append({\n                    \"rule_id\": rule.rule_id,\n                    \"finding\": f\"Unauthorized port in conduit {zone_pair}\",\n                    \"detail\": f\"Port {port} ({rule.service}) not in allowed list {conduit['allowed_ports']}\",\n                    \"remediation\": f\"Remove port {port} from conduit or justify in risk assessment.\",\n                })\n\n    return findings\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) \u003C 2:\n        print(\"Usage: python ot_firewall_analyzer.py \u003Crules.csv>\")\n        sys.exit(1)\n\n    rules = parse_firewall_rules(sys.argv[1])\n    findings = analyze_rules(rules)\n\n    print(\"=\" * 70)\n    print(\"OT ZONE FIREWALL RULE ANALYSIS\")\n    print(\"=\" * 70)\n    for severity in [\"critical\", \"high\", \"medium\", \"low\"]:\n        if findings[severity]:\n            print(f\"\\n--- {severity.upper()} FINDINGS ({len(findings[severity])}) ---\")\n            for f in findings[severity]:\n                print(f\"  [{f['rule_id']}] {f['finding']}\")\n                print(f\"    Detail: {f['detail']}\")\n                print(f\"    Fix: {f['remediation']}\")\n```\n\n### Step 4: Assess Industrial Protocol Security\n\nEvaluate the security configuration of industrial protocols in use, checking for authentication, encryption, and access controls.\n\n```bash\n# Capture Modbus\u002FTCP traffic for analysis\ntcpdump -i eth0 -w ot_capture.pcap 'port 502 or port 44818 or port 4840 or port 102 or port 20000' -c 100000\n\n# Use Wireshark with OT protocol dissectors for deep inspection\ntshark -r ot_capture.pcap -Y \"modbus\" -T fields \\\n  -e ip.src -e ip.dst -e modbus.func_code -e modbus.reference_num \\\n  -e modbus.word_cnt > modbus_analysis.csv\n\n# Check for unauthenticated Modbus write operations (function codes 5,6,15,16)\ntshark -r ot_capture.pcap -Y \"modbus.func_code >= 5 && modbus.func_code \u003C= 16\" \\\n  -T fields -e ip.src -e ip.dst -e modbus.func_code -e frame.time\n\n# Scan for OPC UA servers and check security policies\n# Only run against Level 3+ systems with explicit authorization\npython3 -c \"\nfrom opcua import Client\nserver_url = 'opc.tcp:\u002F\u002F10.30.1.50:4840'\nclient = Client(server_url)\nendpoints = client.connect_and_get_server_endpoints()\nfor ep in endpoints:\n    print(f'Endpoint: {ep.EndpointUrl}')\n    print(f'  Security Mode: {ep.SecurityMode}')\n    print(f'  Security Policy: {ep.SecurityPolicyUri}')\n    print(f'  Auth Tokens: {[t.TokenType for t in ep.UserIdentityTokens]}')\n\"\n```\n\n### Step 5: Generate Assessment Report\n\nCompile findings into a structured report aligned with IEC 62443 and NIST SP 800-82 Rev.3.\n\n```\nOT Network Security Assessment Report\n=======================================\nFacility: Chemical Processing Plant - Site Alpha\nAssessment Date: 2026-02-23\nStandard: IEC 62443-3-3 \u002F NIST SP 800-82r3\nAssessor: [Assessor Name]\n\nEXECUTIVE SUMMARY:\n  The OT network assessment identified 47 assets across Purdue levels 0-4.\n  12 critical and 23 high-severity findings were identified, primarily\n  related to insufficient network segmentation, unauthenticated industrial\n  protocols, and unauthorized cross-zone communication paths.\n\nASSET INVENTORY SUMMARY:\n  Level 0-1 (Field):    18 devices (PLCs, RTUs, I\u002FO modules)\n  Level 2 (Control):     9 devices (HMIs, engineering workstations)\n  Level 3 (Operations): 12 devices (historians, OPC servers, app servers)\n  Level 3.5 (DMZ):       3 devices (data diode, jump server, patch server)\n  Level 4 (Enterprise):  5 devices (domain controllers, file servers)\n\nCRITICAL FINDINGS:\n  [OT-001] Direct Enterprise-to-PLC communication detected\n    Source: 10.0.5.22 (Level 4 - IT workstation)\n    Dest: 10.10.1.15 (Level 1 - Allen-Bradley PLC)\n    Protocol: EtherNet\u002FIP (port 44818)\n    Impact: An attacker on the corporate network could directly modify PLC logic\n    Remediation: Block direct L4-L1 traffic; route through DMZ proxy\n\n  [OT-002] Modbus\u002FTCP write commands without authentication\n    Affected: 8 PLCs accepting unauthenticated FC6 (Write Single Register)\n    Impact: Any device on the OT network can modify process setpoints\n    Remediation: Deploy Modbus-aware firewall; restrict write-capable sources\n\n  [OT-003] Flat network - no segmentation between Purdue levels\n    Detail: All OT devices share VLAN 100 (10.10.0.0\u002F16)\n    Impact: Compromised HMI has direct access to all PLCs and SIS\n    Remediation: Implement zone-based segmentation per IEC 62443-3-2\n\nRISK MATRIX:\n  Critical: 12 findings (immediate remediation required)\n  High:     23 findings (remediate within 30 days)\n  Medium:   15 findings (remediate within 90 days)\n  Low:       8 findings (remediate in next maintenance cycle)\n```\n\n## Key Concepts\n\n| Term | Definition |\n|------|------------|\n| Purdue Reference Model | Hierarchical architecture model (Levels 0-5) for organizing industrial control systems, defining security zones from physical process to enterprise IT |\n| IEC 62443 | International standard series for industrial automation and control systems (IACS) security, defining security levels, zones, conduits, and security requirements |\n| Zone | A grouping of logical or physical assets that share common security requirements, defined by IEC 62443-3-2 |\n| Conduit | A logical grouping of communication channels connecting two or more zones, subject to common security policies |\n| SCADA | Supervisory Control and Data Acquisition - system architecture for high-level process supervisory management of industrial processes |\n| DCS | Distributed Control System - control system architecture where control elements are distributed throughout the system |\n| Air Gap | Physical isolation of OT networks from IT\u002Finternet, increasingly replaced by managed conduits with firewalls and data diodes |\n| Safety Instrumented System (SIS) | Independent system designed to bring a process to a safe state when a hazardous condition is detected |\n\n## Tools & Systems\n\n- **Nozomi Networks Guardian**: Passive OT network monitoring platform providing asset discovery, vulnerability assessment, and anomaly detection for industrial environments\n- **Dragos Platform**: OT cybersecurity platform with asset visibility, threat detection, and vulnerability management designed for critical infrastructure\n- **Claroty xDome**: Cyber-physical systems protection platform providing comprehensive asset inventory and risk scoring across OT, IoT, and IIoT\n- **Wireshark\u002Ftshark**: Network protocol analyzer with industrial protocol dissectors for Modbus, DNP3, S7comm, EtherNet\u002FIP, OPC UA, and BACnet\n- **Nmap with OT scripts**: Network scanner with NSE scripts for OT protocol enumeration (use only on Level 2+ with authorization)\n- **Grassmarlin**: NSA-developed passive OT network mapping tool for identifying SCADA\u002FICS network topology\n\n## Common Scenarios\n\n### Scenario: Flat OT Network with No Segmentation\n\n**Context**: A water utility has all OT devices on a single VLAN. Passive network monitoring reveals HMIs, PLCs, historians, and a domain controller all sharing the same Layer 2 broadcast domain. There is no DMZ between the corporate network and the OT environment.\n\n**Approach**:\n1. Deploy passive monitoring on the SPAN port to capture a complete communication baseline over 2-4 weeks\n2. Map all device-to-device communication flows with protocols and data volumes\n3. Classify assets into Purdue levels based on their function and communication patterns\n4. Design zone architecture with VLANs and inter-zone firewalls per IEC 62443-3-2\n5. Prioritize DMZ creation between Level 3 and Level 4 as the highest-impact segmentation\n6. Present segmentation plan with migration phases that avoid production disruption\n\n**Pitfalls**: Active scanning PLCs during production can cause communication timeouts and process disruptions. Implementing segmentation without a complete traffic baseline will break legitimate control system communications. Relying solely on network-layer firewalls without industrial protocol inspection leaves Modbus\u002FTCP and EtherNet\u002FIP write commands unchecked.\n\n## Output Format\n\n```\nOT Network Security Assessment Report\n=======================================\nFacility: [Facility Name]\nAssessment Date: YYYY-MM-DD\nStandard: IEC 62443-3-3 \u002F NIST SP 800-82r3\n\nEXECUTIVE SUMMARY:\n  [2-3 sentence overview of findings and risk level]\n\nASSET INVENTORY:\n  Level 0-1: [count] field devices\n  Level 2:   [count] control systems\n  Level 3:   [count] operations systems\n  Level 3.5: [count] DMZ systems\n  Level 4:   [count] enterprise systems\n\nFINDINGS BY SEVERITY:\n  Critical: [count] (immediate action required)\n  High:     [count] (30-day remediation)\n  Medium:   [count] (90-day remediation)\n  Low:      [count] (next maintenance window)\n\nDETAILED FINDINGS:\n  [OT-NNN] Finding Title\n    Severity: Critical|High|Medium|Low\n    Affected Assets: [list]\n    IEC 62443 Reference: [section]\n    NIST 800-82r3 Reference: [section]\n    Description: [technical detail]\n    Impact: [operational and safety impact]\n    Remediation: [specific technical remediation steps]\n```\n","# Performing OT Network Security Assessment\n\n## When to Use\n\n- When conducting an initial security baseline of an OT\u002FICS environment for a new client\n- When evaluating the security posture of a facility after an IT\u002FOT convergence initiative\n- When preparing for IEC 62443 or NERC CIP compliance audits\n- When assessing risk following a merger or acquisition involving industrial facilities\n- When investigating whether an OT network has been compromised or has unmonitored pathways to corporate IT\n\n**Do not use** for IT-only network assessments without OT components, for application-layer vulnerability scanning of IT web applications (see performing-web-app-penetration-test), or for active exploitation of live OT systems without explicit authorization and safety controls in place.\n\n## Prerequisites\n\n- Written authorization from the asset owner and operations management for all assessment activities\n- Understanding of the Purdue Reference Model and IEC 62443 zone\u002Fconduit architecture\n- Passive network monitoring tools (Nozomi Guardian, Dragos Platform, or Wireshark with industrial protocol dissectors)\n- Access to network diagrams, firewall rule sets, and asset inventories (or the ability to perform passive discovery)\n- Safety briefing on the physical processes controlled by the OT systems under assessment\n\n## Workflow\n\n### Step 1: Establish Assessment Scope and Safety Boundaries\n\nDefine the scope based on the Purdue Reference Model levels and identify safety-critical systems that must not be actively scanned. OT assessments differ fundamentally from IT assessments because active scanning can crash PLCs, disrupt safety instrumented systems (SIS), and cause physical harm.\n\n```yaml\n# OT Assessment Scope Definition\nassessment:\n  facility: \"Chemical Processing Plant - Site Alpha\"\n  purdue_levels_in_scope:\n    - level_0: \"Physical process sensors and actuators (passive observation only)\"\n    - level_1: \"PLCs, RTUs, safety controllers (passive only, no active scanning)\"\n    - level_2: \"HMI stations, engineering workstations, historian (limited active with approval)\"\n    - level_3: \"Site operations - OPC servers, application servers (active scanning permitted)\"\n    - level_3_5: \"DMZ - data diodes, jump servers (active scanning permitted)\"\n    - level_4: \"Enterprise IT connecting to OT (active scanning permitted)\"\n\n  safety_exclusions:\n    - \"Safety Instrumented Systems (SIS) - Triconex controllers\"\n    - \"Emergency Shutdown (ESD) systems\"\n    - \"Fire and Gas detection systems\"\n    - \"Any Level 0\u002F1 device during active production\"\n\n  authorized_activities:\n    passive:\n      - \"Network traffic capture and analysis via SPAN ports\"\n      - \"Industrial protocol deep packet inspection\"\n      - \"Wireless spectrum analysis\"\n      - \"Physical walkthrough and visual inspection\"\n    active_with_approval:\n      - \"Targeted Nmap scans of Level 2-4 systems during maintenance windows\"\n      - \"Authentication testing on HMI and engineering workstations\"\n      - \"Firewall rule verification between zones\"\n    prohibited:\n      - \"Active scanning of PLCs, RTUs, or SIS controllers\"\n      - \"Fuzzing industrial protocols on live systems\"\n      - \"Modifying PLC logic or firmware\"\n```\n\n### Step 2: Perform Passive Network Discovery and Asset Inventory\n\nDeploy passive monitoring to map all devices, communication flows, and protocols on the OT network without sending any traffic that could disrupt operations.\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"OT Network Passive Discovery and Asset Inventory Builder.\n\nUses pcap captures from SPAN ports to identify OT assets, protocols,\nand communication patterns without active scanning.\n\"\"\"\n\nimport json\nimport sys\nfrom collections import defaultdict\nfrom datetime import datetime\n\ntry:\n    from scapy.all import rdpcap, IP, TCP, UDP\n    from scapy.contrib.modbus import ModbusADURequest, ModbusADUResponse\nexcept ImportError:\n    print(\"Install scapy: pip install scapy\")\n    sys.exit(1)\n\n# Industrial protocol port mappings\nOT_PROTOCOL_PORTS = {\n    502: \"Modbus\u002FTCP\",\n    102: \"S7comm (Siemens)\",\n    44818: \"EtherNet\u002FIP (CIP)\",\n    2222: \"EtherNet\u002FIP (implicit)\",\n    4840: \"OPC UA\",\n    20000: \"DNP3\",\n    47808: \"BACnet\",\n    1911: \"Niagara Fox\",\n    789: \"Crimson v3 (Red Lion)\",\n    2404: \"IEC 60870-5-104\",\n    18245: \"GE SRTP\",\n    5094: \"HART-IP\",\n}\n\nPURDUE_LEVEL_RANGES = {\n    \"Level 0-1 (Field Devices)\": [\"10.10.0.0\u002F16\", \"192.168.10.0\u002F24\"],\n    \"Level 2 (Control Systems)\": [\"10.20.0.0\u002F16\", \"192.168.20.0\u002F24\"],\n    \"Level 3 (Site Operations)\": [\"10.30.0.0\u002F16\", \"192.168.30.0\u002F24\"],\n    \"Level 3.5 (DMZ)\": [\"172.16.0.0\u002F16\"],\n    \"Level 4 (Enterprise)\": [\"10.0.0.0\u002F16\"],\n}\n\n\ndef classify_purdue_level(ip_addr):\n    \"\"\"Classify an IP address to its Purdue Reference Model level.\"\"\"\n    from ipaddress import ip_address, ip_network\n\n    addr = ip_address(ip_addr)\n    for level, subnets in PURDUE_LEVEL_RANGES.items():\n        for subnet in subnets:\n            if addr in ip_network(subnet):\n                return level\n    return \"Unknown\"\n\n\ndef analyze_ot_pcap(pcap_file):\n    \"\"\"Analyze pcap file to discover OT assets and communication patterns.\"\"\"\n    packets = rdpcap(pcap_file)\n\n    assets = {}\n    connections = defaultdict(lambda: {\"count\": 0, \"protocols\": set(), \"ports\": set()})\n    protocol_stats = defaultdict(int)\n    cross_zone_flows = []\n\n    for pkt in packets:\n        if not pkt.haslayer(IP):\n            continue\n\n        src_ip = pkt[IP].src\n        dst_ip = pkt[IP].dst\n\n        # Track assets\n        for ip in (src_ip, dst_ip):\n            if ip not in assets:\n                assets[ip] = {\n                    \"ip\": ip,\n                    \"purdue_level\": classify_purdue_level(ip),\n                    \"protocols_observed\": set(),\n                    \"roles\": set(),\n                    \"first_seen\": str(pkt.time),\n                    \"last_seen\": str(pkt.time),\n                    \"mac\": None,\n                }\n            assets[ip][\"last_seen\"] = str(pkt.time)\n\n        # Identify OT protocols by port\n        dst_port = None\n        if pkt.haslayer(TCP):\n            dst_port = pkt[TCP].dport\n        elif pkt.haslayer(UDP):\n            dst_port = pkt[UDP].dport\n\n        if dst_port and dst_port in OT_PROTOCOL_PORTS:\n            protocol_name = OT_PROTOCOL_PORTS[dst_port]\n            protocol_stats[protocol_name] += 1\n            assets[src_ip][\"protocols_observed\"].add(protocol_name)\n            assets[dst_ip][\"protocols_observed\"].add(protocol_name)\n\n            # Determine roles\n            assets[src_ip][\"roles\"].add(\"client\u002Fmaster\")\n            assets[dst_ip][\"roles\"].add(\"server\u002Fslave\")\n\n        # Track connections\n        conn_key = (src_ip, dst_ip)\n        connections[conn_key][\"count\"] += 1\n        if dst_port:\n            connections[conn_key][\"ports\"].add(dst_port)\n            if dst_port in OT_PROTOCOL_PORTS:\n                connections[conn_key][\"protocols\"].add(OT_PROTOCOL_PORTS[dst_port])\n\n        # Detect cross-zone communication\n        src_level = classify_purdue_level(src_ip)\n        dst_level = classify_purdue_level(dst_ip)\n        if src_level != dst_level and src_level != \"Unknown\" and dst_level != \"Unknown\":\n            cross_zone_flows.append({\n                \"src\": src_ip,\n                \"src_level\": src_level,\n                \"dst\": dst_ip,\n                \"dst_level\": dst_level,\n                \"protocol\": OT_PROTOCOL_PORTS.get(dst_port, f\"port\u002F{dst_port}\"),\n            })\n\n    return {\n        \"asset_count\": len(assets),\n        \"assets\": {ip: {k: list(v) if isinstance(v, set) else v for k, v in info.items()} for ip, info in assets.items()},\n        \"protocol_distribution\": dict(protocol_stats),\n        \"total_connections\": len(connections),\n        \"cross_zone_flows\": cross_zone_flows[:50],\n    }\n\n\ndef generate_assessment_report(results):\n    \"\"\"Generate the OT network assessment findings report.\"\"\"\n    report = []\n    report.append(\"=\" * 70)\n    report.append(\"OT NETWORK PASSIVE DISCOVERY REPORT\")\n    report.append(f\"Generated: {datetime.now().isoformat()}\")\n    report.append(\"=\" * 70)\n\n    report.append(f\"\\nTotal Assets Discovered: {results['asset_count']}\")\n    report.append(f\"Total Unique Connections: {results['total_connections']}\")\n\n    report.append(\"\\n--- INDUSTRIAL PROTOCOL DISTRIBUTION ---\")\n    for proto, count in sorted(results[\"protocol_distribution\"].items(), key=lambda x: -x[1]):\n        report.append(f\"  {proto}: {count} packets\")\n\n    report.append(\"\\n--- CROSS-ZONE COMMUNICATION FLOWS ---\")\n    if results[\"cross_zone_flows\"]:\n        for flow in results[\"cross_zone_flows\"][:20]:\n            report.append(\n                f\"  {flow['src']} ({flow['src_level']}) -> \"\n                f\"{flow['dst']} ({flow['dst_level']}) via {flow['protocol']}\"\n            )\n    else:\n        report.append(\"  No cross-zone flows detected (check subnet classifications)\")\n\n    report.append(\"\\n--- FINDINGS ---\")\n    # Check for Level 4 to Level 0-1 direct connections (critical finding)\n    for flow in results[\"cross_zone_flows\"]:\n        if \"Level 4\" in flow[\"src_level\"] and \"Level 0-1\" in flow[\"dst_level\"]:\n            report.append(\n                f\"  [CRITICAL] Direct Enterprise-to-Field traffic: \"\n                f\"{flow['src']} -> {flow['dst']} via {flow['protocol']}\"\n            )\n        elif \"Level 4\" in flow[\"src_level\"] and \"Level 2\" in flow[\"dst_level\"]:\n            report.append(\n                f\"  [HIGH] Enterprise-to-Control traffic bypassing DMZ: \"\n                f\"{flow['src']} -> {flow['dst']} via {flow['protocol']}\"\n            )\n\n    return \"\\n\".join(report)\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) \u003C 2:\n        print(\"Usage: python ot_network_discovery.py \u003Cpcap_file>\")\n        sys.exit(1)\n\n    results = analyze_ot_pcap(sys.argv[1])\n    print(generate_assessment_report(results))\n\n    # Save detailed JSON\n    output_file = sys.argv[1].replace(\".pcap\", \"_inventory.json\")\n    with open(output_file, \"w\") as f:\n        json.dump(results, f, indent=2, default=str)\n    print(f\"\\nDetailed inventory saved to: {output_file}\")\n```\n\n### Step 3: Evaluate Firewall Rules Between Purdue Zones\n\nAnalyze firewall configurations between OT zones to identify overly permissive rules, missing deny defaults, and unauthorized conduits that violate the IEC 62443 zone model.\n\n```python\n#!\u002Fusr\u002Fbin\u002Fenv python3\n\"\"\"OT Zone Firewall Rule Analyzer.\n\nParses firewall rule exports (CSV format) and evaluates them against\nIEC 62443 zone\u002Fconduit model requirements.\n\"\"\"\n\nimport csv\nimport json\nimport sys\nfrom dataclasses import dataclass, field\nfrom typing import Optional\n\n\n@dataclass\nclass FirewallRule:\n    rule_id: str\n    source_zone: str\n    source_ip: str\n    dest_zone: str\n    dest_ip: str\n    service: str\n    port: str\n    action: str\n    enabled: bool\n    comment: str = \"\"\n\n\n# IEC 62443 zone communication policy\n# Defines which zone pairs are allowed to communicate and through what conduit\nALLOWED_CONDUITS = {\n    (\"Level 4\", \"Level 3.5\"): {\n        \"allowed_ports\": [443, 3389, 22],\n        \"description\": \"Enterprise to DMZ - web services, jump hosts\",\n        \"requires_inspection\": True,\n    },\n    (\"Level 3.5\", \"Level 3\"): {\n        \"allowed_ports\": [443, 1433, 5432, 8080],\n        \"description\": \"DMZ to Site Ops - historian mirror, OPC relay\",\n        \"requires_inspection\": True,\n    },\n    (\"Level 3\", \"Level 2\"): {\n        \"allowed_ports\": [502, 44818, 4840, 102],\n        \"description\": \"Site Ops to Control - OPC UA, Modbus, S7comm\",\n        \"requires_inspection\": True,\n    },\n    (\"Level 2\", \"Level 1\"): {\n        \"allowed_ports\": [502, 44818, 102, 2222],\n        \"description\": \"Control to Field - direct industrial protocols\",\n        \"requires_inspection\": False,\n    },\n}\n\n# Prohibited direct connections\nPROHIBITED_CONDUITS = [\n    (\"Level 4\", \"Level 3\"),\n    (\"Level 4\", \"Level 2\"),\n    (\"Level 4\", \"Level 1\"),\n    (\"Level 4\", \"Level 0\"),\n    (\"Level 3\", \"Level 1\"),\n    (\"Level 3\", \"Level 0\"),\n    (\"Internet\", \"Level 3.5\"),\n    (\"Internet\", \"Level 3\"),\n    (\"Internet\", \"Level 2\"),\n    (\"Internet\", \"Level 1\"),\n]\n\n\ndef parse_firewall_rules(csv_file):\n    \"\"\"Parse firewall rules from CSV export.\"\"\"\n    rules = []\n    with open(csv_file, \"r\") as f:\n        reader = csv.DictReader(f)\n        for row in reader:\n            rules.append(FirewallRule(\n                rule_id=row.get(\"rule_id\", \"\"),\n                source_zone=row.get(\"source_zone\", \"\"),\n                source_ip=row.get(\"source_ip\", \"\"),\n                dest_zone=row.get(\"dest_zone\", \"\"),\n                dest_ip=row.get(\"dest_ip\", \"\"),\n                service=row.get(\"service\", \"\"),\n                port=row.get(\"port\", \"\"),\n                action=row.get(\"action\", \"\"),\n                enabled=row.get(\"enabled\", \"true\").lower() == \"true\",\n                comment=row.get(\"comment\", \"\"),\n            ))\n    return rules\n\n\ndef analyze_rules(rules):\n    \"\"\"Analyze firewall rules against IEC 62443 zone model.\"\"\"\n    findings = {\"critical\": [], \"high\": [], \"medium\": [], \"low\": [], \"info\": []}\n\n    for rule in rules:\n        if not rule.enabled or rule.action.lower() != \"allow\":\n            continue\n\n        zone_pair = (rule.source_zone, rule.dest_zone)\n        port = int(rule.port) if rule.port.isdigit() else 0\n\n        # Check for prohibited conduits\n        if zone_pair in PROHIBITED_CONDUITS:\n            findings[\"critical\"].append({\n                \"rule_id\": rule.rule_id,\n                \"finding\": f\"Prohibited direct connection: {rule.source_zone} -> {rule.dest_zone}\",\n                \"detail\": f\"Rule allows {rule.source_ip} to reach {rule.dest_ip}:{rule.port} ({rule.service})\",\n                \"remediation\": \"Remove rule. Route traffic through DMZ (Level 3.5) with application-layer inspection.\",\n            })\n\n        # Check for overly broad rules (any\u002Fany)\n        elif rule.source_ip in (\"any\", \"0.0.0.0\u002F0\") or rule.dest_ip in (\"any\", \"0.0.0.0\u002F0\"):\n            findings[\"high\"].append({\n                \"rule_id\": rule.rule_id,\n                \"finding\": f\"Overly permissive rule with 'any' address\",\n                \"detail\": f\"{rule.source_ip} -> {rule.dest_ip}:{rule.port} in {zone_pair}\",\n                \"remediation\": \"Restrict to specific host IPs per IEC 62443 least-privilege conduit policy.\",\n            })\n\n        # Check allowed conduits for port violations\n        elif zone_pair in ALLOWED_CONDUITS:\n            conduit = ALLOWED_CONDUITS[zone_pair]\n            if port and port not in conduit[\"allowed_ports\"]:\n                findings[\"medium\"].append({\n                    \"rule_id\": rule.rule_id,\n                    \"finding\": f\"Unauthorized port in conduit {zone_pair}\",\n                    \"detail\": f\"Port {port} ({rule.service}) not in allowed list {conduit['allowed_ports']}\",\n                    \"remediation\": f\"Remove port {port} from conduit or justify in risk assessment.\",\n                })\n\n    return findings\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) \u003C 2:\n        print(\"Usage: python ot_firewall_analyzer.py \u003Crules.csv>\")\n        sys.exit(1)\n\n    rules = parse_firewall_rules(sys.argv[1])\n    findings = analyze_rules(rules)\n\n    print(\"=\" * 70)\n    print(\"OT ZONE FIREWALL RULE ANALYSIS\")\n    print(\"=\" * 70)\n    for severity in [\"critical\", \"high\", \"medium\", \"low\"]:\n        if findings[severity]:\n            print(f\"\\n--- {severity.upper()} FINDINGS ({len(findings[severity])}) ---\")\n            for f in findings[severity]:\n                print(f\"  [{f['rule_id']}] {f['finding']}\")\n                print(f\"    Detail: {f['detail']}\")\n                print(f\"    Fix: {f['remediation']}\")\n```\n\n### Step 4: Assess Industrial Protocol Security\n\nEvaluate the security configuration of industrial protocols in use, checking for authentication, encryption, and access controls.\n\n```bash\n# Capture Modbus\u002FTCP traffic for analysis\ntcpdump -i eth0 -w ot_capture.pcap 'port 502 or port 44818 or port 4840 or port 102 or port 20000' -c 100000\n\n# Use Wireshark with OT protocol dissectors for deep inspection\ntshark -r ot_capture.pcap -Y \"modbus\" -T fields \\\n  -e ip.src -e ip.dst -e modbus.func_code -e modbus.reference_num \\\n  -e modbus.word_cnt > modbus_analysis.csv\n\n# Check for unauthenticated Modbus write operations (function codes 5,6,15,16)\ntshark -r ot_capture.pcap -Y \"modbus.func_code >= 5 && modbus.func_code \u003C= 16\" \\\n  -T fields -e ip.src -e ip.dst -e modbus.func_code -e frame.time\n\n# Scan for OPC UA servers and check security policies\n# Only run against Level 3+ systems with explicit authorization\npython3 -c \"\nfrom opcua import Client\nserver_url = 'opc.tcp:\u002F\u002F10.30.1.50:4840'\nclient = Client(server_url)\nendpoints = client.connect_and_get_server_endpoints()\nfor ep in endpoints:\n    print(f'Endpoint: {ep.EndpointUrl}')\n    print(f'  Security Mode: {ep.SecurityMode}')\n    print(f'  Security Policy: {ep.SecurityPolicyUri}')\n    print(f'  Auth Tokens: {[t.TokenType for t in ep.UserIdentityTokens]}')\n\"\n```\n\n### Step 5: Generate Assessment Report\n\nCompile findings into a structured report aligned with IEC 62443 and NIST SP 800-82 Rev.3.\n\n```\nOT Network Security Assessment Report\n=======================================\nFacility: Chemical Processing Plant - Site Alpha\nAssessment Date: 2026-02-23\nStandard: IEC 62443-3-3 \u002F NIST SP 800-82r3\nAssessor: [Assessor Name]\n\nEXECUTIVE SUMMARY:\n  The OT network assessment identified 47 assets across Purdue levels 0-4.\n  12 critical and 23 high-severity findings were identified, primarily\n  related to insufficient network segmentation, unauthenticated industrial\n  protocols, and unauthorized cross-zone communication paths.\n\nASSET INVENTORY SUMMARY:\n  Level 0-1 (Field):    18 devices (PLCs, RTUs, I\u002FO modules)\n  Level 2 (Control):     9 devices (HMIs, engineering workstations)\n  Level 3 (Operations): 12 devices (historians, OPC servers, app servers)\n  Level 3.5 (DMZ):       3 devices (data diode, jump server, patch server)\n  Level 4 (Enterprise):  5 devices (domain controllers, file servers)\n\nCRITICAL FINDINGS:\n  [OT-001] Direct Enterprise-to-PLC communication detected\n    Source: 10.0.5.22 (Level 4 - IT workstation)\n    Dest: 10.10.1.15 (Level 1 - Allen-Bradley PLC)\n    Protocol: EtherNet\u002FIP (port 44818)\n    Impact: An attacker on the corporate network could directly modify PLC logic\n    Remediation: Block direct L4-L1 traffic; route through DMZ proxy\n\n  [OT-002] Modbus\u002FTCP write commands without authentication\n    Affected: 8 PLCs accepting unauthenticated FC6 (Write Single Register)\n    Impact: Any device on the OT network can modify process setpoints\n    Remediation: Deploy Modbus-aware firewall; restrict write-capable sources\n\n  [OT-003] Flat network - no segmentation between Purdue levels\n    Detail: All OT devices share VLAN 100 (10.10.0.0\u002F16)\n    Impact: Compromised HMI has direct access to all PLCs and SIS\n    Remediation: Implement zone-based segmentation per IEC 62443-3-2\n\nRISK MATRIX:\n  Critical: 12 findings (immediate remediation required)\n  High:     23 findings (remediate within 30 days)\n  Medium:   15 findings (remediate within 90 days)\n  Low:       8 findings (remediate in next maintenance cycle)\n```\n\n## Key Concepts\n\n| Term | Definition |\n|------|------------|\n| Purdue Reference Model | Hierarchical architecture model (Levels 0-5) for organizing industrial control systems, defining security zones from physical process to enterprise IT |\n| IEC 62443 | International standard series for industrial automation and control systems (IACS) security, defining security levels, zones, conduits, and security requirements |\n| Zone | A grouping of logical or physical assets that share common security requirements, defined by IEC 62443-3-2 |\n| Conduit | A logical grouping of communication channels connecting two or more zones, subject to common security policies |\n| SCADA | Supervisory Control and Data Acquisition - system architecture for high-level process supervisory management of industrial processes |\n| DCS | Distributed Control System - control system architecture where control elements are distributed throughout the system |\n| Air Gap | Physical isolation of OT networks from IT\u002Finternet, increasingly replaced by managed conduits with firewalls and data diodes |\n| Safety Instrumented System (SIS) | Independent system designed to bring a process to a safe state when a hazardous condition is detected |\n\n## Tools & Systems\n\n- **Nozomi Networks Guardian**: Passive OT network monitoring platform providing asset discovery, vulnerability assessment, and anomaly detection for industrial environments\n- **Dragos Platform**: OT cybersecurity platform with asset visibility, threat detection, and vulnerability management designed for critical infrastructure\n- **Claroty xDome**: Cyber-physical systems protection platform providing comprehensive asset inventory and risk scoring across OT, IoT, and IIoT\n- **Wireshark\u002Ftshark**: Network protocol analyzer with industrial protocol dissectors for Modbus, DNP3, S7comm, EtherNet\u002FIP, OPC UA, and BACnet\n- **Nmap with OT scripts**: Network scanner with NSE scripts for OT protocol enumeration (use only on Level 2+ with authorization)\n- **Grassmarlin**: NSA-developed passive OT network mapping tool for identifying SCADA\u002FICS network topology\n\n## Common Scenarios\n\n### Scenario: Flat OT Network with No Segmentation\n\n**Context**: A water utility has all OT devices on a single VLAN. Passive network monitoring reveals HMIs, PLCs, historians, and a domain controller all sharing the same Layer 2 broadcast domain. There is no DMZ between the corporate network and the OT environment.\n\n**Approach**:\n1. Deploy passive monitoring on the SPAN port to capture a complete communication baseline over 2-4 weeks\n2. Map all device-to-device communication flows with protocols and data volumes\n3. Classify assets into Purdue levels based on their function and communication patterns\n4. Design zone architecture with VLANs and inter-zone firewalls per IEC 62443-3-2\n5. Prioritize DMZ creation between Level 3 and Level 4 as the highest-impact segmentation\n6. Present segmentation plan with migration phases that avoid production disruption\n\n**Pitfalls**: Active scanning PLCs during production can cause communication timeouts and process disruptions. Implementing segmentation without a complete traffic baseline will break legitimate control system communications. Relying solely on network-layer firewalls without industrial protocol inspection leaves Modbus\u002FTCP and EtherNet\u002FIP write commands unchecked.\n\n## Output Format\n\n```\nOT Network Security Assessment Report\n=======================================\nFacility: [Facility Name]\nAssessment Date: YYYY-MM-DD\nStandard: IEC 62443-3-3 \u002F NIST SP 800-82r3\n\nEXECUTIVE SUMMARY:\n  [2-3 sentence overview of findings and risk level]\n\nASSET INVENTORY:\n  Level 0-1: [count] field devices\n  Level 2:   [count] control systems\n  Level 3:   [count] operations systems\n  Level 3.5: [count] DMZ systems\n  Level 4:   [count] enterprise systems\n\nFINDINGS BY SEVERITY:\n  Critical: [count] (immediate action required)\n  High:     [count] (30-day remediation)\n  Medium:   [count] (90-day remediation)\n  Low:      [count] (next maintenance window)\n\nDETAILED FINDINGS:\n  [OT-NNN] Finding Title\n    Severity: Critical|High|Medium|Low\n    Affected Assets: [list]\n    IEC 62443 Reference: [section]\n    NIST 800-82r3 Reference: [section]\n    Description: [technical detail]\n    Impact: [operational and safety impact]\n    Remediation: [specific technical remediation steps]\n```\n",{"name":5,"tags":43,"author":49,"domain":30,"license":14,"version":50,"subdomain":51,"description":52},[44,45,46,47,48,28],"ot-security","ics","scada","industrial-control","iec62443","mahipal","1.0.0","ot-ics-security","This skill covers conducting comprehensive security assessments of Operational Technology (OT) networks including SCADA systems, DCS architectures, and industrial control system communication paths. It addresses the Purdue Reference Model layers, identifies IT\u002FOT convergence risks, evaluates firewall rules between zones, and maps industrial protocol traffic (Modbus, DNP3, OPC UA, EtherNet\u002FIP) to detect misconfigurations, unauthorized connections, and attack surfaces in critical infrastructure.\n","master","3f5d983eb4ef375b749adcd6b07ec03bd82ae8a8","_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment",0,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills","https:\u002F\u002Fgithub.com\u002Fmicsapp","2026-03-20 11:24:18",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add micsapp\u002Fmicstec-skills --skill performing-ot-network-security-assessment",{"tool":66,"command":67},"bunx","bunx skills add micsapp\u002Fmicstec-skills --skill performing-ot-network-security-assessment",{"tool":69,"command":70},"pnpm","pnpm dlx skills add micsapp\u002Fmicstec-skills --skill performing-ot-network-security-assessment","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002FSKILL.md",true,[74,80,85,91,95,99,105],{"path":75,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":78,"sourceHtmlUrl":79},"assets\u002Ftemplate.md","ASSET","资产文件",4929,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002Fassets\u002Ftemplate.md",{"path":81,"resourceType":81,"resourceTypeDesc":82,"sizeBytes":83,"sourceHtmlUrl":84},"LICENSE","许可证",11255,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002FLICENSE",{"path":86,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":89,"sourceHtmlUrl":90},"references\u002Fapi-reference.md","REFERENCE","参考文档",1452,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002Freferences\u002Fapi-reference.md",{"path":92,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":93,"sourceHtmlUrl":94},"references\u002Fstandards.md",4136,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002Freferences\u002Fstandards.md",{"path":96,"resourceType":87,"resourceTypeDesc":88,"sizeBytes":97,"sourceHtmlUrl":98},"references\u002Fworkflows.md",4858,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002Freferences\u002Fworkflows.md",{"path":100,"resourceType":101,"resourceTypeDesc":102,"sizeBytes":103,"sourceHtmlUrl":104},"scripts\u002Fagent.py","SCRIPT","脚本",6511,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002Fscripts\u002Fagent.py",{"path":106,"resourceType":101,"resourceTypeDesc":102,"sizeBytes":107,"sourceHtmlUrl":108},"scripts\u002Fprocess.py",17904,"https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002F_universal\u002Fcybersecurity-skills\u002Fskills\u002Fperforming-ot-network-security-assessment\u002Fscripts\u002Fprocess.py",[110,147,177,197,217,242],{"skillNo":111,"name":112,"nameZh":6,"description":113,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":114,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":127,"publishedAt":38},"01M6HBTJ02FXBFG9NYEHHYAP52","azure-apim-architecture","Analyzes and explains Azure API Management architecture decisions for enterprise API marketplace implementations using VNet Internal mode, Front Door, hybrid authentication, and multi-environment strategies. Use when discussing APIM component selection, network topology, cost optimization, or comparing alternatives like workspaces vs instances, VNet Internal vs External mode, or Front Door vs Application Gateway.","MIT","https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002Fcopilot-cli\u002Fcopilot-agent-skills\u002F.github\u002Fskills\u002Fazure-apim-architecture\u002FSKILL.md",[117,122],{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":123,"categoryName":124,"taxonomyType":125,"taxonomyTypeDesc":126},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[128,129,130,131,132,133,134,135,22,136,137,138,139,140,141,142,143,144,145,146],"architecture","azure","azure apim architecture","component","authentication","gateway","topology","Optimization","api","team","environment","multi-environment","workspaces","instances","selection","strategies","azure api management","mode","for",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":114,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":161,"publishedAt":38},"01M6HBT7J4H082JEEA670B3EQ9","apiops-deployment","Guides deployment of Azure API Management infrastructure using Infrastructure as Code (Bicep\u002FTerraform), CI\u002FCD pipelines (GitHub Actions\u002FAzure DevOps), and APIOps workflows. Use when deploying APIM, creating pipelines, or implementing dev→test→prod promotion strategies.","https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002Fcopilot-cli\u002Fcopilot-agent-skills\u002F.github\u002Fskills\u002Fapiops-deployment\u002FSKILL.md",[153,154,157,160],{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},{"categoryNo":155,"categoryName":156,"taxonomyType":120,"taxonomyTypeDesc":121},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":158,"categoryName":159,"taxonomyType":120,"taxonomyTypeDesc":121},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":123,"categoryName":124,"taxonomyType":125,"taxonomyTypeDesc":126},[162,163,164,165,129,166,167,168,169,170,171,172,136,137,143,173,174,144,175,176],"deployment","apiops deployment","workflows","azure devops","infrastructure","code","infrastructure as code","actions","ci","github actions","github-actions","as","guides","CI\u002FCD","implementing",{"skillNo":178,"name":179,"nameZh":6,"description":180,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":114,"licenseFileUrl":6,"sourceHtmlUrl":181,"categories":182,"keywords":184,"publishedAt":38},"01M6HBT2HEA23THNE9E00GYQBE","apim-policy-authoring","Creates production-ready Azure API Management policy XML for authentication (OAuth 2.0, JWT validation, subscription keys), rate limiting, CORS configuration, error handling, and API transformations. Use when implementing API security, access control, or request\u002Fresponse processing logic.","https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002Fcopilot-cli\u002Fcopilot-agent-skills\u002F.github\u002Fskills\u002Fapim-policy-authoring\u002FSKILL.md",[183],{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},[185,186,187,24,129,132,136,137,188,189,190,191,192,193,194,144,195,196,176,146],"policy","authoring","apim policy authoring","access","use","ready","api security","Access Control","error","processing","cors configuration","production-ready",{"skillNo":198,"name":199,"nameZh":6,"description":200,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":114,"licenseFileUrl":6,"sourceHtmlUrl":201,"categories":202,"keywords":205,"publishedAt":38},"01M6HBSY65SB29J9WE9KYD0K6T","api-security-review","Reviews Azure API Management configurations for security vulnerabilities, OWASP API Security Top 10 compliance, VNet Internal mode validation, Private Link verification, and Azure Security Benchmark alignment. Use when performing security audits, pre-deployment validation, or compliance reviews.","https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002Fcopilot-cli\u002Fcopilot-agent-skills\u002F.github\u002Fskills\u002Fapi-security-review\u002FSKILL.md",[203,204],{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},{"categoryNo":123,"categoryName":124,"taxonomyType":125,"taxonomyTypeDesc":126},[206,24,207,136,191,208,129,162,209,210,211,212,137,213,144,214,215,216,145,146],"review","security review","api security review","benchmark","verification","owasp","owasp-api","alignment","azure security","reviews","top",{"skillNo":218,"name":219,"nameZh":6,"description":220,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":114,"licenseFileUrl":6,"sourceHtmlUrl":221,"categories":222,"keywords":223,"publishedAt":38},"01M6HBSRW4PDFE6K4F8JYPZQ05","jira-cli","Interact with Jira from the command line to create, list, view, edit, and transition issues, manage sprints and epics, and perform common Jira workflows. Use when the user asks about Jira tasks, tickets, issues, sprints, or needs to manage project work items.","https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002Fcopilot-cli\u002Fawesome-copilot-agents\u002Fskills\u002Fjira-cli\u002FSKILL.md",[],[224,225,226,164,227,228,229,230,136,231,232,233,234,235,236,237,238,239,240,241],"cli","jira","jira cli","init","tasks","create","issues","common","work","command","edit","list","view","project","project work","token","line","sprints",{"skillNo":243,"name":244,"nameZh":6,"description":245,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":114,"licenseFileUrl":6,"sourceHtmlUrl":246,"categories":247,"keywords":248,"publishedAt":38},"01M6HBSNS3JHMW603G47TWE31H","calculator","Performs arbitrary-precision arithmetic calculations including addition, subtraction, multiplication, division, and exponents. Use when the user asks to calculate, compute, or evaluate math expressions, or when precise decimal arithmetic is needed to avoid floating-point errors.","https:\u002F\u002Fgithub.com\u002Fmicsapp\u002Fmicstec-skills\u002Fblob\u002Fmaster\u002Fcopilot-cli\u002Fawesome-copilot-agents\u002Fskills\u002Fcalculator\u002FSKILL.md",[],[244,249,250,251,252,253,254,189,255,256],"npm","js","calculate","node","math","user","compute","errors"]