<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: implementing-ics-anomaly-detection
description: >-
  Deploy and tune anomaly detection for ICS environments using process variable baselining,
  network traffic profiling, and behavioral analysis to identify deviations from normal
  operations in SCADA/PLC systems.
domain: cybersecurity
subdomain: ot-ics-security
tags:
  - anomaly-detection
  - ics
  - scada
  - baseline
  - zeek
  - machine-learning
  - process-monitoring
version: "1.0"
author: defconxt
license: AGPL-3.0
compatibility: Designed for Claude Code, GitHub Copilot, OpenAI Codex, Cursor, Gemini CLI, and any agentskills.io-compatible agent.
metadata:
  mitre-attack: ["T0879", "T0855", "T0831"]
  nist-csf: ["DE.AE-1", "DE.AE-3", "DE.CM-1"]
  iec-62443: ["SR 6.1", "SR 6.2"]
  uuid: a1b2c3d4-1004-4000-a004-000000000004
---

# Implementing ICS Anomaly Detection

## Overview

ICS environments are highly deterministic — PLCs execute fixed cycles, communication
patterns are predictable, and process variables operate within known ranges. This
predictability makes anomaly detection highly effective. Baselining normal behavior across
network traffic, protocol commands, and process values enables detection of sophisticated
attacks that evade signature-based systems.

Mode: `[MODE: BLUE]` for detection deployment; `[MODE: PURPLE]` for coverage validation.

## Prerequisites

| Requirement | Details |
|---|---|
| Zeek 6.0+ with ICS protocol analyzers on OT network tap | Required |
| Network tap or SPAN port on OT VLAN(s) | Required |
| Historian access for process variable baselines | Required |
| Python 3.10+ with numpy/scipy for statistical analysis | Required |
| SIEM integration (Splunk, Elastic, or similar) | Required |

## Key Concepts

### Network Traffic Baselining

```bash
# Capture baseline traffic (minimum 7 days for cycle coverage)
tcpdump -i eth1 -w baseline_week.pcap -G 86400 -W 7

# Generate Zeek connection logs
zeek -r baseline_week.pcap local modbus dnp3

# Profile normal communication pairs
cat conn.log | zeek-cut id.orig_h id.orig_p id.resp_h id.resp_p proto service | \
  sort | uniq -c | sort -rn > connection_profile.txt

# Profile Modbus function code distribution
cat modbus.log | zeek-cut id.orig_h id.resp_h func | \
  sort | uniq -c | sort -rn > modbus_func_profile.txt

# Identify periodic communication (PLC poll cycles)
cat conn.log | zeek-cut ts id.orig_h id.resp_h | \
  awk '{print $2, $3, $1}' | sort -k1,2 -k3n > timing_analysis.txt
```

### Process Variable Monitoring

```python
# Monitor Modbus register values for anomalies
import statistics

def detect_anomaly(values: list[float], threshold_sigma: float = 3.0) -> dict:
    """Statistical anomaly detection on process variable time series."""
    if len(values) < 30:
        return {"error": "Insufficient data points for baseline"}
    mean = statistics.mean(values)
    stdev = statistics.stdev(values)
    anomalies = [
        {"index": i, "value": v, "z_score": (v - mean) / stdev}
        for i, v in enumerate(values)
        if abs(v - mean) > threshold_sigma * stdev
    ]
    return {
        "mean": mean, "stdev": stdev,
        "threshold": threshold_sigma,
        "anomaly_count": len(anomalies),
        "anomalies": anomalies,
    }
```

### Zeek ICS Anomaly Scripts

```bash
# Deploy Zeek with ICS-specific anomaly detection
# zeek_ics_anomaly.zeek — custom policy script

# Track new Modbus communication pairs
zeek -r live_capture.pcap modbus

# Compare against baseline
comm -13 <(sort baseline_modbus_pairs.txt) <(sort current_modbus_pairs.txt)

# Detect timing anomalies (PLC poll cycle deviation)
cat conn.log | zeek-cut ts id.orig_h id.resp_h duration | \
  awk 'prev[$2$3] {
    delta = $1 - prev[$2$3];
    if (delta > 5 || delta < 0.1)
      print "TIMING_ANOMALY:", $2, "->", $3, "delta:", delta
  } {prev[$2$3] = $1}'
```

### Suricata Threshold-Based Detection

```yaml
# Alert on Modbus register values outside normal range
alert modbus any any -> $ICS_NET 502 ( \
  msg:"ICS ANOMALY - Register value out of range"; \
  flow:established,to_client; \
  modbus.function:3; \
  content:"|03|"; offset:7; depth:1; \
  byte_test:2,>,1000,9; \
  threshold:type limit, track by_src, count 1, seconds 300; \
  sid:4002001; rev:1;)

# Alert on new communication pair to ICS network
alert tcp !$ICS_BASELINE any -> $ICS_NET 502 ( \
  msg:"ICS ANOMALY - New Modbus source detected"; \
  flow:established,to_server; \
  sid:4002002; rev:1;)
```

## Workflow

### Step 1: Establish Baselines

```bash
# Capture and profile 7+ days of normal operations
zeek -r baseline.pcap local modbus dnp3
# Generate profiles for connections, function codes, timing
```

### Step 2: Deploy Detection Rules

```bash
# Load custom Zeek scripts and Suricata rules
suricata -T -c /etc/suricata/suricata.yaml -S ics_anomaly.rules
suricata-update --reload-command "kill -USR2 $(pidof suricata)"
```

### Step 3: Tune and Validate

```bash
# Test detection against known-bad PCAPs
suricata -r attack_simulation.pcap -S ics_anomaly.rules -l /tmp/test/
cat /tmp/test/eve.json | jq 'select(.event_type=="alert")'
```

## Verification

- [ ] Network traffic baseline covers minimum 7-day operational cycle
- [ ] Process variable ranges documented per register/tag
- [ ] New communication pair detection active and alerting
- [ ] Timing anomaly detection tuned for PLC poll cycles
- [ ] False positive rate below 5 alerts/day after tuning
- [ ] Integration with SIEM for correlation and escalation

## Detection Opportunities

- New Modbus/DNP3 sources not in baseline → unauthorized device or lateral movement
- Process variable exceeding statistical bounds → process manipulation or sensor failure
- PLC poll cycle timing deviation → MitM or PLC performance degradation
- Function code distribution shift → reconnaissance or attack tooling

```yaml
title: Ics Anomaly Detection Detection
id: 49f74645-20c2-4aaa-ace7-908ad0881bd8
status: experimental
description: Detects suspicious activity related to implementing ics anomaly detection techniques in ot ics security context
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    CommandLine: "*implementing*ics*"
  condition: selection
level: medium
tags:
  - attack.t0879
  - attack.t0855
  - attack.t0831
  - attack.lateral_movement
falsepositives:
  - Industrial control system maintenance by authorized engineering staff
```

## References

- SANS ICS Security: Anomaly Detection in ICS Environments
- IEC 62443-3-3 SR 6.1: Audit Log Accessibility / SR 6.2: Continuous Monitoring
- NIST SP 800-82 Rev 3 §6.3.2: Anomaly Detection for ICS
