SC-076: Critical Water Infrastructure SCADA Attack¶
Scenario Overview¶
| Field | Detail |
|---|---|
| ID | SC-076 |
| Category | Critical Infrastructure / Water / OT-ICS |
| Severity | Critical |
| ATT&CK Tactics | Initial Access, Lateral Movement, Inhibit Response Function, Impair Process Control, Impact |
| ATT&CK Techniques (ICS) | T0886 (Remote Services), T0836 (Modify Parameter), T0855 (Unauthorized Command Message), T0856 (Spoof Reporting Message), T0831 (Manipulation of Control), T0882 (Theft of Operational Information) |
| ATT&CK Techniques (Enterprise) | T1133 (External Remote Services), T1078 (Valid Accounts), T1021 (Remote Services), T1059 (Command and Scripting Interpreter) |
| Target Environment | Municipal water treatment facility, SCADA/HMI systems, programmable logic controllers (PLCs), chemical dosing systems, historian databases |
| Estimated Impact | Manipulation of sodium hydroxide (NaOH) dosing levels at a municipal water treatment plant serving 85,000 residents; potential public health emergency if undetected; disruption of water treatment operations for 48+ hours during incident response |
Narrative¶
Clearwater Municipal Water Authority (CMWA), a fictional public water utility serving 85,000 residents in a mid-sized American city, operates a 12 million gallon per day (MGD) surface water treatment facility. The plant uses a conventional treatment process: coagulation, flocculation, sedimentation, filtration, and disinfection. Chemical dosing is controlled by a SCADA system comprising 14 Allen-Bradley ControlLogix PLCs, 3 operator HMI workstations running Rockwell FactoryTalk View, and a centralized historian server. The SCADA network (172.16.10.0/24) is connected to the corporate IT network (10.10.1.0/24) through a single firewall at 172.16.10.1 / 10.10.1.1.
In April 2026, a threat actor gains access to CMWA's SCADA systems through a compromised VPN account. The attacker — assessed as a disgruntled former contractor with knowledge of the facility's systems — uses VPN credentials that were never revoked after the contractor's engagement ended six months prior. From the VPN, the attacker pivots through the poorly segmented network to reach the SCADA HMI and modifies the sodium hydroxide (NaOH) dosing setpoint from the normal 28 mg/L to 280 mg/L — a tenfold increase that could cause chemical burns and serious injury if it reached consumers.
The attack is detected within 14 minutes by an alert operator who notices the pH sensor readings spiking above normal parameters on the plant floor. The operator manually overrides the chemical dosing system and initiates emergency response procedures. No contaminated water reaches the distribution system due to the multi-barrier treatment process and the operator's rapid response.
Educational Context
This scenario is based on publicly reported incidents including the 2021 Oldsmar, Florida water treatment attack. All data is 100% synthetic. The scenario is designed to educate water sector defenders on detection and response strategies. No working exploit code is provided.
Attack Flow¶
graph TD
A[Phase 1: Initial Access<br/>Compromised VPN credentials] --> B[Phase 2: Network Reconnaissance<br/>Map IT/OT network topology]
B --> C[Phase 3: IT/OT Pivot<br/>Traverse firewall to SCADA network]
C --> D[Phase 4: HMI Access<br/>Remote desktop to operator workstation]
D --> E[Phase 5: Parameter Manipulation<br/>Modify NaOH dosing setpoint 28→280 mg/L]
E --> F[Phase 6: Detection<br/>Operator observes pH anomaly at 14 minutes]
F --> G[Phase 7: Manual Override<br/>Chemical dosing returned to safe levels]
G --> H[Phase 8: Incident Response<br/>Network isolation + forensics + recovery] Phase Details¶
Phase 1: Initial Access via Compromised VPN¶
ATT&CK Technique: T1133 (External Remote Services), T1078 (Valid Accounts)
The attacker uses VPN credentials belonging to a former contractor, James Thornton (fictional), whose account was never deactivated after his contract ended in October 2025. The VPN (Cisco AnyConnect) provides split-tunnel access to the corporate IT network. CMWA does not require multi-factor authentication for VPN access — a common weakness in small municipal utilities with limited cybersecurity budgets.
# Simulated VPN authentication log (educational only)
[2026-04-12 02:17:33 UTC] Cisco AnyConnect VPN
Event: Authentication SUCCESS
User: jthornton@cmwa.example.com
Source IP: 203.0.113.201 (residential ISP)
Assigned IP: 10.10.1.200
Group Policy: CONTRACTORS (full tunnel)
MFA: NOT REQUIRED ← VULNERABILITY
Session ID: VPN-20260412-0847
Note: Account status ACTIVE (should have been disabled 2025-10-15)
# Account lifecycle failure:
# Contractor offboarding checklist: NOT COMPLETED
# Last password rotation: 2025-08-22 (8 months ago)
# Account review: Last performed 2024-12-01 (16 months ago)
Phase 2: Network Reconnaissance¶
ATT&CK Technique: T0882 (Theft of Operational Information)
From the VPN connection, the attacker scans the internal network to map the IT/OT topology. The attacker has prior knowledge of the network layout from their time as a contractor but verifies current configurations. The corporate IT network and the SCADA OT network are separated by a single firewall, but several ports are open to allow remote monitoring and historian data access.
# Simulated network reconnaissance (educational only)
# Attacker scans from VPN-assigned IP 10.10.1.200
$ nmap -sV 10.10.1.0/24 -p 22,80,443,3389,5900 --open
# Corporate IT network discovery:
10.10.1.10 - dc01.cmwa.example.com (Domain Controller)
10.10.1.20 - exchange.cmwa.example.com (Email)
10.10.1.30 - historian-gw.cmwa.example.com (Historian Gateway)
10.10.1.50 - scada-jump.cmwa.example.com (Jump Server — RDP open)
# Firewall rule discovery (ports open from IT to OT):
10.10.1.50 → 172.16.10.0/24 : TCP/3389 (RDP to HMI workstations)
10.10.1.30 → 172.16.10.50 : TCP/1433 (SQL to Historian)
10.10.1.0/24 → 172.16.10.0/24 : ICMP (ping allowed)
# Critical finding: RDP from jump server to SCADA HMIs is unrestricted
# No application allowlisting, no session recording, no time restrictions
Phase 3: Pivot to SCADA Network¶
ATT&CK Technique: T1021 (Remote Services)
The attacker uses Remote Desktop Protocol (RDP) to connect from the corporate jump server (10.10.1.50) to the SCADA network. The jump server uses a shared local administrator account with a weak password that the attacker knows from their contractor engagement. There is no privileged access management (PAM) solution, no session recording, and no time-based access restrictions.
# Simulated lateral movement (educational only)
# Step 1: RDP to jump server
$ xfreerdp /v:10.10.1.50 /u:scadajump /p:REDACTED /cert:ignore
# Step 2: From jump server, RDP to HMI workstation
# HMI-01 is logged in with the shared operator account (always on)
$ mstsc /v:172.16.10.20 # HMI-01.scada.cmwa.example.com
# Jump server access log (if it existed — logging was minimal):
[2026-04-12 02:31:15 UTC] RDP Session Started
User: scadajump (local admin)
Source: 10.10.1.200 (VPN)
Destination: 10.10.1.50
Session Type: Interactive
[2026-04-12 02:33:42 UTC] RDP Session Started
User: operator (shared HMI account) ← NO INDIVIDUAL ACCOUNTABILITY
Source: 10.10.1.50 (jump server)
Destination: 172.16.10.20 (HMI-01)
Session Type: Shadow (connected to existing session)
Phase 4: HMI Access and Orientation¶
ATT&CK Technique: T0831 (Manipulation of Control)
The attacker accesses the FactoryTalk View HMI application running on the operator workstation. The HMI is permanently logged in with a shared operator account — a common practice in water treatment facilities to ensure operators can respond quickly to alarms. The attacker navigates to the chemical dosing control screen, which displays current setpoints, actual dosing rates, and chemical tank levels.
# Simulated HMI screen state (educational only)
╔══════════════════════════════════════════════════════════════╗
║ CMWA Water Treatment Plant — Chemical Dosing Control ║
║ Station: HMI-01 | Operator: OPERATOR (shared) ║
╠══════════════════════════════════════════════════════════════╣
║ ║
║ SODIUM HYDROXIDE (NaOH) — pH Adjustment ║
║ ┌─────────────────────────────────────────────┐ ║
║ │ Setpoint: 28.0 mg/L [MODIFY] │ ║
║ │ Actual Rate: 27.8 mg/L │ ║
║ │ pH (treated): 7.42 │ ║
║ │ pH Target: 7.20 - 7.80 │ ║
║ │ Tank Level: 68% (4,200 gal) │ ║
║ │ Mode: AUTO │ ║
║ └─────────────────────────────────────────────┘ ║
║ ║
║ CHLORINE (Cl₂) — Disinfection ║
║ ┌─────────────────────────────────────────────┐ ║
║ │ Setpoint: 1.8 mg/L [MODIFY] │ ║
║ │ Actual Rate: 1.7 mg/L │ ║
║ │ Residual: 0.6 mg/L │ ║
║ │ Mode: AUTO │ ║
║ └─────────────────────────────────────────────┘ ║
║ ║
║ FLUORIDE (HFS) — Fluoridation ║
║ ┌─────────────────────────────────────────────┐ ║
║ │ Setpoint: 0.7 mg/L [MODIFY] │ ║
║ │ Actual Rate: 0.68 mg/L │ ║
║ │ Mode: AUTO │ ║
║ └─────────────────────────────────────────────┘ ║
╚══════════════════════════════════════════════════════════════╝
Phase 5: Chemical Dosing Manipulation¶
ATT&CK Technique (ICS): T0836 (Modify Parameter), T0855 (Unauthorized Command Message)
At 02:41 UTC, the attacker modifies the sodium hydroxide dosing setpoint from 28 mg/L to 280 mg/L — a tenfold increase. This change is entered directly through the HMI interface. The FactoryTalk View application does not require re-authentication for setpoint changes, and the PLC does not enforce range-checking limits on the NaOH setpoint — it accepts any value within the data type range.
# Simulated parameter manipulation (educational only)
[2026-04-12 02:41:07 UTC] FactoryTalk View — Setpoint Change
Tag: NaOH_SP_MGL
Previous Value: 28.0
New Value: 280.0 ← 10x INCREASE
Changed By: OPERATOR (shared account — no individual attribution)
Authorization: NONE REQUIRED ← VULNERABILITY
PLC: PLC-CHEM-01 (172.16.10.100)
Range Check: NONE CONFIGURED ← VULNERABILITY
# PLC response (educational only):
[02:41:08] PLC-CHEM-01: Tag NaOH_SP_MGL updated to 280.0
[02:41:09] NaOH metering pump speed increasing: 12% → 100%
[02:41:15] NaOH actual dosing rate climbing: 28.0 → 56.0 → 112.0 mg/L
[02:41:30] pH sensor reading: 7.42 → 8.10 → 9.30 (RISING)
[02:42:00] pH sensor reading: 10.20 ← HIGH pH ALARM THRESHOLD: 9.50
[02:42:01] *** ALARM: HIGH pH — TREATED WATER — 10.20 ***
Phase 6: Operator Detection (T+14 Minutes)¶
A night-shift operator, Maria Santos (fictional), is conducting a routine plant walkthrough when she notices the high-pH alarm on the local alarm panel at the treatment basin. She immediately returns to the control room and observes the anomalous NaOH setpoint on the HMI.
# Simulated detection and operator response (educational only)
[2026-04-12 02:42:01 UTC] ALARM: HIGH_PH_TREATED_WATER
Value: 10.20 | Threshold: 9.50 | Priority: HIGH
Location: Post-filtration basin, pH analyzer PT-401
[02:43:00] Operator Santos observes alarm on local panel during walkthrough
[02:44:30] Santos returns to control room, reviews HMI
→ Observes NaOH setpoint at 280.0 mg/L (expected: ~28 mg/L)
→ Observes pH at 10.85 and still rising
→ Notes: "I did not make this change. No one else is in the plant."
[02:45:00] Santos initiates MANUAL OVERRIDE:
→ Switches NaOH dosing to MANUAL mode
→ Sets NaOH pump speed to 0% (STOP)
→ Confirms NaOH flow stops within 15 seconds
→ Opens treated water diversion valve to waste basin
→ Calls Plant Superintendent (emergency protocol)
[02:47:00] pH begins declining: 11.02 → 10.80 → 10.45
[02:55:00] pH returns to safe range: 8.20 (declining toward normal)
[03:00:00] Plant Superintendent arrives; incident formally declared
# CRITICAL SAFETY NOTE:
# No contaminated water reached the distribution system because:
# 1. Clearwell (finished water tank) provides 4-hour residence time buffer
# 2. Distribution system pumps were not running (low-demand overnight period)
# 3. Operator response within 14 minutes limited pH excursion
# 4. Diversion to waste basin prevented high-pH water from entering clearwell
Phase 7: Emergency Response¶
Immediate Actions (0-4 hours):
# Simulated emergency response (educational only)
[03:00] INCIDENT COMMANDER designated (Plant Superintendent)
→ Emergency notification: Mayor's office, State EPA, CISA, FBI
→ Water quality advisory: PRECAUTIONARY (no contamination confirmed)
→ Distribution system: Increased chlorine residual monitoring
[03:15] NETWORK ISOLATION
→ VPN concentrator: DISABLED (all remote access cut)
→ IT/OT firewall: ALL rules set to DENY
→ SCADA network: AIR-GAPPED from corporate network
→ HMI workstations: Preserved for forensics (not rebooted)
→ Chemical dosing: ALL systems switched to MANUAL operation
[03:30] WATER QUALITY VERIFICATION
→ Manual sampling at 5 distribution system points
→ pH, chlorine residual, turbidity, alkalinity tested
→ All samples WITHIN NORMAL PARAMETERS
→ Clearwell pH: 7.65 (normal — high-pH water was diverted)
→ Continuous monitoring: Hourly manual sampling for 48 hours
[04:00] FORENSIC PRESERVATION
→ Historian database exported (172.16.10.50)
→ HMI event logs preserved
→ VPN authentication logs pulled from RADIUS server
→ Firewall logs exported (both directions)
→ PLC program backups downloaded for integrity comparison
Forensic Analysis (4-72 hours):
# Simulated forensic findings (educational only)
FORENSIC ANALYSIS SUMMARY — CMWA-IR-2026-0412
================================================
VPN ACCESS:
User: jthornton@cmwa.example.com
Source IP: 203.0.113.201 (residential ISP — registered to James Thornton)
VPN session: 02:17:33 - 02:52:18 UTC (34 minutes 45 seconds)
Account status: Should have been DISABLED on 2025-10-15
RDP SESSION CHAIN:
203.0.113.201 → 10.10.1.50 (jump server) → 172.16.10.20 (HMI-01)
Total dwell time on SCADA network: ~19 minutes
PARAMETER CHANGE:
Tag NaOH_SP_MGL changed from 28.0 to 280.0 at 02:41:07 UTC
Source: HMI-01 operator session (FactoryTalk View)
PLC: PLC-CHEM-01 at 172.16.10.100
ROOT CAUSE:
1. VPN account not deactivated after contractor offboarding
2. No MFA on VPN access
3. Shared operator account on HMI (no individual accountability)
4. No PLC-level setpoint range checking
5. IT/OT firewall allowed unrestricted RDP from jump server to SCADA
6. No privileged access management (PAM) for OT systems
Phase 8: Remediation and Hardening¶
Security Improvements Implemented
Immediate (Week 1):
- All contractor and vendor VPN accounts audited and disabled
- MFA enforced on all remote access (VPN, RDP, web portals)
- IT/OT firewall rules reduced to explicit allow-list
- Shared HMI operator accounts replaced with individual logins
- PLC setpoint range limits configured for all chemical dosing parameters
Short-term (Month 1-3):
- Network segmentation: Dedicated OT DMZ with data diode for historian
- Privileged access management (PAM) solution deployed for OT access
- Continuous OT network monitoring (network traffic analysis)
- PLC integrity monitoring (program change detection)
- Automated contractor account lifecycle management
Long-term (Month 3-12):
- Application allowlisting on all HMI workstations
- Independent Safety Instrumented System (SIS) for chemical dosing limits
- Redundant pH monitoring with independent alarm path
- Quarterly tabletop exercises for water sector cyber incidents
- Participation in WaterISAC threat intelligence sharing
Detection Opportunities¶
OT Network Monitoring¶
| Detection Point | Method | Indicator |
|---|---|---|
| VPN authentication | RADIUS/SIEM correlation | Login from deactivated/contractor account |
| RDP sessions | Network flow analysis | RDP from VPN segment to SCADA network |
| HMI access | Windows event logs | Remote desktop connection to HMI workstation |
| PLC commands | OT network monitoring (Claroty, Dragos, Nozomi) | Setpoint changes from unexpected sources |
| Process variables | Historian trend analysis | Rapid parameter changes exceeding normal rates |
Process Variable Anomaly Detection¶
# Educational example: Chemical dosing anomaly detection
import json
from datetime import datetime, timedelta
def detect_dosing_anomaly(historian_data, parameter, window_minutes=5):
"""Detect abnormal chemical dosing parameter changes"""
anomalies = []
for i in range(1, len(historian_data)):
current = historian_data[i]
previous = historian_data[i-1]
# Calculate rate of change
value_delta = abs(current['value'] - previous['value'])
time_delta = (current['timestamp'] - previous['timestamp']).total_seconds()
if time_delta > 0:
rate_of_change = value_delta / time_delta * 60 # per minute
# Alert if setpoint changes by more than 20% in any single update
pct_change = value_delta / previous['value'] * 100 if previous['value'] > 0 else 0
if pct_change > 20:
anomalies.append({
'parameter': parameter,
'timestamp': current['timestamp'].isoformat(),
'previous_value': previous['value'],
'new_value': current['value'],
'pct_change': round(pct_change, 1),
'severity': 'CRITICAL' if pct_change > 100 else 'HIGH'
})
return anomalies
# Example (synthetic data):
# anomalies = detect_dosing_anomaly(naoh_history, "NaOH_SP_MGL")
# In this scenario: 28 → 280 = 900% change → CRITICAL alert
Historian Data Analysis¶
# KQL — Detect abnormal PLC setpoint changes (educational)
OTHistorianData
| where TimeGenerated > ago(24h)
| where TagName in ("NaOH_SP_MGL", "Cl2_SP_MGL", "HFS_SP_MGL")
| extend PreviousValue = prev(Value, 1)
| extend PctChange = abs(Value - PreviousValue) / PreviousValue * 100
| where PctChange > 20
| project TimeGenerated, TagName, PreviousValue, Value, PctChange, SourceHMI
| sort by TimeGenerated desc
# SPL — Correlate VPN logins with SCADA access (educational)
index=vpn sourcetype=radius action=accept
| join type=inner user
[search index=windows sourcetype=WinEventLog:Security EventCode=4624
LogonType=10 TargetServerName="HMI-*"]
| where user_category="contractor" OR user_status="disabled"
| table _time, user, src_ip, dest_ip, TargetServerName
Lessons Learned¶
Key Takeaways
-
Account lifecycle management is critical — The failure to deactivate a contractor VPN account was the root cause of this incident. Automated account provisioning and deprovisioning, tied to HR/procurement systems, must be implemented even in small utilities.
-
MFA is non-negotiable for remote access — Single-factor VPN authentication to critical infrastructure is an unacceptable risk. MFA must be enforced for all remote access to OT environments.
-
IT/OT segmentation must be enforced — A single firewall with overly permissive rules is insufficient. OT networks require dedicated DMZs, data diodes for one-way data flow, and explicit allow-list firewall rules.
-
Shared operator accounts eliminate accountability — Individual authentication on HMI systems is essential for forensic attribution and access control. Shared accounts must be eliminated.
-
PLC-level safety limits are a critical safety control — The PLC accepted a 10x setpoint change without range-checking. Engineering limits must be programmed into PLCs as a last line of defense, independent of HMI-level controls.
-
Human operators remain the most important safety layer — Operator Santos detected the attack within 14 minutes through observational awareness. Automated monitoring is essential, but trained, alert operators are irreplaceable in OT environments.
-
Independent Safety Instrumented Systems (SIS) — Chemical dosing systems should have independent safety systems that can override the control system and shut down dosing pumps when process variables exceed safe limits.
MITRE ATT&CK Mapping¶
| Technique ID | Technique Name | Framework | Phase |
|---|---|---|---|
| T1133 | External Remote Services | Enterprise | Initial Access |
| T1078 | Valid Accounts | Enterprise | Initial Access / Persistence |
| T1021 | Remote Services | Enterprise | Lateral Movement |
| T0886 | Remote Services | ICS | Lateral Movement |
| T0882 | Theft of Operational Information | ICS | Collection |
| T0836 | Modify Parameter | ICS | Impair Process Control |
| T0855 | Unauthorized Command Message | ICS | Impair Process Control |
| T0831 | Manipulation of Control | ICS | Impact |