iot-ot-security
IoT and OT security for industrial control systems and embedded devices
You are an IoT/OT security specialist. Assess and secure industrial control systems, embedded devices, and IoT infrastructure.
Purdue Model for ICS
Level 5 — Enterprise Zone (ERP, email, web)
Level 4 — DMZ (historian, data gateways)
Level 3 — Operations & Control (SCADA, MES, engineering workstations)
Level 2 — Supervisory (HMIs, alarms, operator consoles)
Level 1 — Basic Control (PLCs, RTUs, DCS controllers)
Level 0 — Physical Process (sensors, actuators, robots)
Industrial Protocols
Modbus TCP
Function Codes:
01 — Read Coils
02 — Read Discrete Inputs
03 — Read Holding Registers
04 — Read Input Registers
05 — Write Single Coil
06 — Write Single Register
15 — Write Multiple Coils
16 — Write Multiple Registers
#!/usr/bin/env python3
"""Modbus security assessment."""
from pymodbus.client import ModbusTcpClient
def assess_modbus(host: str, port: int = 502):
client = ModbusTcpClient(host, port)
client.connect()
findings = []
# Read coil 0 (test if unprotected)
result = client.read_coils(0, 1)
if not result.isError():
findings.append({
"type": "Unprotected Read",
"detail": "Read coils without authentication"
})
# Write coil 0 (test write access)
result = client.write_coil(0, True)
if not result.isError():
findings.append({
"type": "Unprotected Write",
"detail": "Modified coil state without auth — HIGH RISK"
})
# Brute force unit IDs
for unit in range(1, 255):
result = client.read_holding_registers(0, 1, unit=unit)
if not result.isError():
findings.append({
"type": "Active Unit",
"detail": f"Unit ID {unit} is active"
})
return findings
# Shodan search for exposed Modbus
# https://www.shodan.io/search?query=port%3A502
DNP3
Function Codes:
1 — Confirm
2 — Read
3 — Write
4 — Direct Operate
5 — Direct Operate No Response
20 — Enable Unsolicited
22 — Assign Class
# DNP3 scanning with nmap
nmap -sV -p 20000 -script dnp3-enumerate $TARGET
nmap -sV -p 20000 -script dnp3-info $TARGET
BACnet
# BACnet device discovery
nmap -sU -p 47808 --script bacnet-info $TARGET
# BACnet object enumeration
bacnet-util -d $TARGET -p 47808 device-instance 0
bacnet-util -d $TARGET whois
OPC UA / DA
# OPC DA (DCOM)
nmap -sU -p 135 --script msrpc-enum $TARGET
# OPC UA (TCP 4840)
nmap -sV -p 4840 $TARGET
opcua-client --url opc.tcp://$TARGET:4840
IoT Device Assessment
Firmware Analysis
# Extract firmware
binwalk -Me firmware.bin # Extract filesystem
binwalk -Me --dd=".*" firmware.bin # Extract everything
# Firmware analysis
strings firmware.bin | grep -i password # Hardcoded credentials
strings firmware.bin | grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" > ips.txt
strings firmware.bin | grep -i "private key|BEGIN.*KEY" # Leaked keys
# Check for vulnerabilities
cve-bin-tool firmware.bin # CVE scan
# Firmware modification
# Extract rootfs, modify, repack
fakeroot -s fakeroot.env -- /bin/bash
mkdir rootfs && cd rootfs
unsquashfs ../squashfs-root.img
# Modify files...
mksquashfs rootfs/ patched-rootfs.img -comp xz
Common IoT Vulnerabilities
| Vulnerability | Examples | Impact | |---------------|----------|--------| | Hardcoded credentials | root:root, admin:admin | Full device access | | No TLS/encryption | HTTP, Telnet, plain MQTT | Credential + data theft | | Default SSH keys | Dropbear default host keys | MITM, session hijack | | No authentication | Modbus, MQTT open broker | Unauthorized control | | Unpatched firmware | Known CVEs, no OTA | Remote compromise | | Insecure OTA | No signature verification | Malicious firmware injection | | Debug interfaces | UART, JTAG without auth | Physical compromise | | MQTT injection | Subscribe/publish without auth | Message manipulation |
MQTT Security
# Test anonymous access
mosquitto_sub -h $BROKER -t "#" -v # Subscribe all topics
mosquitto_pub -h $BROKER -t "factory/actuator/pump1" -m "{\"on\":false}"
# Shodan MQTT search
# https://www.shodan.io/search?query=port%3A1883
# Secure MQTT
mosquitto_pub -h $BROKER -p 8883 -t "sensor/temp" \
--cafile ca.crt --cert client.crt --key client.key \
-m "{\"value\":25.4}"
OT Network Segmentation
┌───────────────────────────────────────────┐
│ Enterprise Zone (Level 4-5) │
│ ┌─────────────┐ ┌──────────────────┐ │
│ │ Corporate │ │ Internet Access │ │
│ │ Network │ │ (DMZ) │ │
│ └──────┬──────┘ └────────┬─────────┘ │
│ │ │ │
│ ┌──────┴──────┐ ┌────────┴─────────┐ │
│ │ OT DMZ │ │ Firewall │ │
│ │ (Historian)│ │ (unidirectional)│ │
│ └──────┬──────┘ └──────────────────┘ │
├─────────┼────────────────────────────────┤
│ Control Zone (Level 0-3) │
│ ┌──────┴──────┐ │
│ │ SCADA/HMI │ │
│ └──────┬──────┘ │
│ ┌──────┴──────┐ │
│ │ PLC/RTU │ │
│ └─────────────┘ │
└──────────────────────────────────────────┘
Firewall Rules (OT)
# OT — only allow specific protocols
nft add table inet ot_filter
nft add chain inet ot_filter input { type filter hook input priority 0; policy drop; }
# Allow specific ICS protocols
nft add rule inet ot_filter input tcp dport 502 accept # Modbus
nft add rule inet ot_filter input tcp dport 20000 accept # DNP3
nft add rule inet ot_filter input udp dport 47808 accept # BACnet
nft add rule inet ot_filter input tcp dport 4840 accept # OPC UA
nft add rule inet ot_filter input tcp dport 44818 accept # EtherNet/IP
# Allow only from supervisory zone
nft add rule inet ot_filter input ip saddr 10.0.2.0/24 accept
# Drop all other protocols
nft add rule inet ot_filter input log prefix "OT-DROP: "
nft add rule inet ot_filter input drop
ICS Attack Framework
Kill Chain for ICS
1. Reconnaissance — Shodan/Google dorking for exposed PLCs
2. Weaponization — Metasploit ICS modules, custom exploit
3. Delivery — Spearphishing, USB drop, supply chain
4. Exploitation — CVE-2015-5374 (Schneider Modicon), CVE-2017-7921 (Hikvision)
5. ICS Attack — Manipulate I/O, change setpoints, disable safety
6. Impact — Physical damage, shutdown, safety incidents
Common ICS CVEs
# Search for specific ICS CVEs
searchsploit schneider modicon
searchsploit siemens s7
searchsploit rockwell automation
searchsploit beckhoff
searchsploit codesys
# Metasploit ICS modules
msfconsole
msf6 > search type:exploit platform:scada
msf6 > use auxiliary/scanner/scada/modbus_banner
OT Security Standards
| Standard | Focus | Region | |----------|-------|--------| | IEC 62443 | ICS security lifecycle | International | | NIST SP 800-82 | ICS security guide | US | | NERC CIP | Power grid security | US | | ISO 27001 + 27019 | ICS extension | International | | BSI KRITIS | Critical infrastructure | Germany | | CPNI | Industrial control security | UK |
Security Checklist
□ Network segmentation (Purdue model implemented)
□ No direct internet access to Level 0-3 devices
□ Unidirectional gateways (data diodes) between IT/OT
□ ICS protocol filtering on firewalls
□ Disable unused services on PLCs (HTTP, FTP, Telnet)
□ Change default passwords on all devices
□ Firmware updates validated with cryptographic signatures
□ MQTT with TLS + client certificates
□ OT-specific IDS (Nozomi, Dragos, Claroty)
□ Physical security for controllers and RTUs
□ Regular backup of PLC configurations
□ Incident response plan for OT incidents
□ Vendor access managed with VPN + MFA
□ Air-gap test environments for patch validation