Learn Ethical Hacking (#57) - IoT and Embedded Security - Hacking the Physical World
Learn Ethical Hacking (#57) - IoT and Embedded Security - Hacking the Physical World
What will I learn
- The IoT attack surface -- why billions of connected devices are the largest unpatched vulnerability on earth;
- Firmware analysis -- extracting, unpacking, and reverse engineering device firmware to find hardcoded credentials and backdoors;
- Hardware hacking basics -- UART, JTAG, SPI interfaces and what they expose when you open the case;
- Default credentials and hardcoded secrets -- the vulnerability that refuses to die in embedded devices;
- Network-based IoT attacks -- UPnP exploitation, MQTT interception, Zigbee/Z-Wave attacks, and CoAP enumeration;
- Shodan and Censys -- search engines for finding exposed IoT devices at scale;
- Industrial Control Systems (ICS/SCADA) -- the terrifying intersection of IoT and critical infrastructure;
- Defense: network isolation, firmware updates, secure boot, and why most consumer IoT will never be secure.
Requirements
- A working modern computer running macOS, Windows or Ubuntu;
- binwalk and Ghidra installed for firmware analysis;
- Optional: a cheap IoT device for hands-on testing (smart plug, IP camera);
- The ambition to learn ethical hacking and security research.
Difficulty
- Intermediate/Advanced
Curriculum (of the Learn Ethical Hacking Series):
- Learn Ethical Hacking (#1) - Why Hackers Win
- Learn Ethical Hacking (#2) - Your Hacking Lab
- Learn Ethical Hacking (#3) - How the Internet Actually Works - For Attackers
- Learn Ethical Hacking (#4) - Reconnaissance - The Art of Not Being Noticed
- Learn Ethical Hacking (#5) - Active Scanning - Mapping the Attack Surface
- Learn Ethical Hacking (#6) - The AI Slop Epidemic - Why AI-Generated Code Is a Security Disaster
- Learn Ethical Hacking (#7) - Passwords - Why Humans Are the Weakest Cipher
- Learn Ethical Hacking (#8) - Social Engineering - Hacking the Human
- Learn Ethical Hacking (#9) - Cryptography for Hackers - What Protects Data (and What Doesn't)
- Learn Ethical Hacking (#10) - The Vulnerability Lifecycle - From Discovery to Patch to Exploit
- Learn Ethical Hacking (#11) - HTTP Deep Dive - Request Smuggling and Header Injection
- Learn Ethical Hacking (#12) - SQL Injection - The Bug That Won't Die
- Learn Ethical Hacking (#13) - SQL Injection Advanced - Extracting Entire Databases
- Learn Ethical Hacking (#14) - Cross-Site Scripting (XSS) - Injecting Code Into Browsers
- Learn Ethical Hacking (#15) - XSS Advanced - Bypassing Filters and CSP
- Learn Ethical Hacking (#16) - Cross-Site Request Forgery - Making Users Attack Themselves
- Learn Ethical Hacking (#17) - Authentication Bypass - Getting In Without a Password
- Learn Ethical Hacking (#18) - Server-Side Request Forgery - Making Servers Betray Themselves
- Learn Ethical Hacking (#19) - Insecure Deserialization - Code Execution via Data
- Learn Ethical Hacking (#20) - File Upload Vulnerabilities - When Users Upload Weapons
- Learn Ethical Hacking (#21) - API Security - The New Attack Surface
- Learn Ethical Hacking (#22) - Business Logic Flaws - When the Code Works But the Logic Doesn't
- Learn Ethical Hacking (#23) - Client-Side Attacks - Beyond XSS
- Learn Ethical Hacking (#24) - Content Management Systems - Hacking WordPress and Friends
- Learn Ethical Hacking (#25) - Web Application Firewalls - Bypassing the Guards
- Learn Ethical Hacking (#26) - The Full Web Pentest - Methodology and Reporting
- Learn Ethical Hacking (#27) - Bug Bounty Hunting - Getting Paid to Hack the Web
- Learn Ethical Hacking (#28) - The AI Web Attack Surface - AI Features as Vulnerabilities
- Learn Ethical Hacking (#29) - Network Sniffing - Seeing Everything on the Wire
- Learn Ethical Hacking (#30) - Wireless Network Attacks - Breaking Wi-Fi
- Learn Ethical Hacking (#31) - Privilege Escalation - Linux
- Learn Ethical Hacking (#32) - Privilege Escalation - Windows
- Learn Ethical Hacking (#33) - Active Directory Attacks - The Crown Jewels
- Learn Ethical Hacking (#34) - Pivoting and Lateral Movement - Spreading Through Networks
- Learn Ethical Hacking (#35) - Cloud Security - AWS Attack and Defense
- Learn Ethical Hacking (#36) - Cloud Security - Azure and GCP
- Learn Ethical Hacking (#37) - Container Security - Docker and Kubernetes Attacks
- Learn Ethical Hacking (#38) - Infrastructure as Code - Securing the Automation
- Learn Ethical Hacking (#39) - Email Security - Phishing Infrastructure and Defense
- Learn Ethical Hacking (#40) - DNS Attacks - Exploiting the Internet's Foundation
- Learn Ethical Hacking (#41) - Exploitation Frameworks - Metasploit and Cobalt Strike
- Learn Ethical Hacking (#42) - Custom Exploit Development - Writing Your Own
- Learn Ethical Hacking (#43) - Exploit Development Advanced - Modern Mitigations and Bypasses
- Learn Ethical Hacking (#44) - Reverse Engineering - Understanding Binaries
- Learn Ethical Hacking (#45) - Supply Chain Attacks - Poisoning the Source
- Learn Ethical Hacking (#46) - The Human Factor - Why Security Training Fails
- Learn Ethical Hacking (#47) - Physical Security and OSINT - The Forgotten Attack Vectors
- Learn Ethical Hacking (#48) - Insider Threats - When the Call Is Coming from Inside the House
- Learn Ethical Hacking (#49) - Deepfakes and AI Deception - The New Social Engineering
- Learn Ethical Hacking (#50) - Red Team Operations - Simulating Real Attacks
- Learn Ethical Hacking (#51) - Incident Response - When Things Go Wrong
- Learn Ethical Hacking (#52) - Threat Intelligence - Knowing Your Enemy
- Learn Ethical Hacking (#53) - Security Architecture - Designing Systems That Resist Attack
- Learn Ethical Hacking (#54) - Compliance and Governance - The Business of Security
- Learn Ethical Hacking (#55) - Privacy and Data Protection - GDPR, CCPA, and Beyond
- Learn Ethical Hacking (#56) - Cryptocurrency Security - Attacking and Defending Digital Assets
- Learn Ethical Hacking (#57) - IoT and Embedded Security - Hacking the Physical World (this post)
Learn Ethical Hacking (#57) - IoT and Embedded Security - Hacking the Physical World
Solutions to Episode 56 Exercises
Exercise 1: Damn Vulnerable DeFi -- challenge solutions (abbreviated).
// Challenge: Unstoppable (reentrancy variant)
// Vulnerability: lending pool checks totalBalance == token.balanceOf
// but an attacker can send tokens directly, breaking the invariant
// Exploit: token.transfer(pool, 1) -- pool is now permanently broken
// because totalBalance (tracked internally) != balanceOf (actual balance)
// Fix: track deposits internally, never compare against balanceOf()
// Challenge: Naive Receiver (access control)
// Vulnerability: flashLoan() can be called with ANY borrower address
// -- the function doesn't verify msg.sender == borrower
// Exploit: call flashLoan(victim, 0) in a loop -- victim pays fees each time
// until drained. 10 calls x 1 ETH fee = 10 ETH stolen from victim
// Fix: require(msg.sender == borrower) or only allow self-initiated loans
// Key takeaway: both challenges exploit the SAME principle --
// the contract trusts external state (balanceOf) or external callers
// (anyone can call flashLoan) when it should verify internally.
// Checks-effects-interactions from episode 56 prevents both patterns.
Exercise 2: Token approval audit (abbreviated).
Wallet: 0x742d... (test wallet on Ethereum Sepolia testnet)
Active approvals found: 7
Uniswap Router V2: USDC unlimited (still active, still in use)
Old DEX (defunct): WETH unlimited (REVOKED -- contract abandoned 2023)
NFT marketplace: DAI unlimited (REVOKED -- no longer used)
OpenSea Seaport 1.5: approve-all NFTs (keep -- actively trading)
Random airdrop claim: USDT unlimited (REVOKED -- suspicious contract)
Sushiswap Router: WETH 0.5 ETH (keep -- exact amount, low risk)
1inch Aggregator: USDC unlimited (REDUCED to 500 USDC -- still use)
Actions taken: revoked 3 unnecessary approvals, reduced 1 unlimited to exact
Cost: ~$2.50 in gas per revocation on mainnet (~$0.001 on Sepolia)
Remaining risk: 2 unlimited approvals on actively-used, audited protocols
The token approval audit is genuinely eye-opening for most people. You interact with a DEX once three years ago, and that unlimited USDC approval is still sitting there -- a loaded gun pointed at your wallet if that contract ever gets compromised. The Ledger Connect Kit attack from 2023 proved this is not hypothetical: a supply chain compromise in a JavaScript library injected malicious code into DeFi frontends that exploited existing token approvals. Your old, forgotten approvals are someone else's attack surface ;-)
Exercise 3: Ronin Bridge hack analysis (abbreviated).
Architecture:
- 9 validator nodes running the Ronin bridge
- 5-of-9 multisig threshold for authorizing withdrawals
- Bridge connected Ronin sidechain to Ethereum mainnet
Attack timeline (March 2022):
1. North Korean Lazarus Group identified Sky Mavis employees on LinkedIn
2. Sent fake senior engineer job postings to multiple employees
3. One engineer went through full fake interview process
4. Final step: "open this PDF with our offer letter"
5. PDF contained trojanized payload -- compromised employee workstation
6. Attacker pivoted from workstation to validator key infrastructure
7. Obtained 4 of 9 validator private keys from Sky Mavis nodes
8. 5th key: Axie DAO had temporarily delegated signing authority to
Sky Mavis months earlier for a one-time txn. Delegation was NEVER
revoked. Attacker used this stale delegation for the 5th signature.
9. 5-of-9 threshold met. Attacker drained 173,600 ETH + 25.5M USDC
Detection failure:
- Theft went undetected for 6 DAYS
- Discovered only when a user complained they couldn't withdraw
- No automated alerting on validator signing patterns
- No anomaly detection on withdrawal volumes
- Monitoring from episode 51 would have caught this in minutes
What should have been different:
- Separate key storage per validator (not all on same infra)
- Automated alerts on ANY validator key usage outside maintenance
- Time-locked withdrawals above threshold (24h delay for >$1M)
- Immediate revocation of temporary delegations after one-time use
- Regular validator key rotation (every 90 days minimum)
The Ronin case is a masterclass in how layered failures produce catastrophic outcomes. The social engineering alone (episode 8) was not enough -- they also needed the stale delegation from Axie DAO (a key management failure) AND the absence of monitoring (episode 51). Remove any one of those three failures and the attack either fails or gets detected before $625 million walks out the door. Defense in depth from episode 53 is not about making every layer perfect -- it's about making sure no single failure is enough.
Episode 56 covered cryptocurrency security -- the most adversarial, highest-stakes environment in computing. We walked through the full crypto attack surface (key management, smart contracts, protocols, exchanges, and the human layer), private key security (the entire blockchain security model reduces to "who has the key"), reentrancy attacks and the checks-effects-interactions pattern that prevents them, flash loan attacks (borrowing billions with zero collateral to break protocol assumptions -- Mango Markets' attacker got arrested for what he publicly called a "profitable trading strategy"), approval phishing (the silent drain -- unlimited token approvals that persist until you explicitly revoke them), the long history of exchange hacks from Mt. Gox to FTX, blockchain forensics (pseudonymous does NOT mean anonymous -- Chainalysis built a billion-dollar business proving this), and defense strategies built on wallet separation and the principle of least privilege applied to personal finance.
Today we leave the digital world entirely and hack the physical one.
For 56 episodes, every system we've attacked lived inside a computer or a network. Web servers, databases, Active Directory, cloud infrastructure, smart contracts -- all software, all virtual, all fixable with a patch or a configuration change. IoT and embedded devices change that equation fundamentally. These devices sit in the physical world. They control locks, cameras, thermostats, medical pumps, factory robots, traffic lights, and power grid substations. A vulnerability in a web application means stolen data. A vulnerability in an insulin pump means someone dies.
There are over 15 billion IoT devices connected to the internet right now. Smart cameras, thermostats, medical devices, industrial controllers, smart locks, baby monitors, refrigerators, light bulbs. Most of them run outdated Linux kernels with default credentials, receive no security updates, and will remain vulnerable for their entire operational lifetime -- which for some industrial systems is 15-20 years.
Here we go.
The IoT Security Problem -- Why It's Different
IoT is where security goes to die, and the reasons are structural, not technical. The technical vulnerabilities are the same ones we've seen throughout this series -- command injection, default credentials, missing encryption, unpatched software. What makes IoT uniquely terrible is the ECONOMIC reality:
#!/usr/bin/env python3
"""iot_economics.py -- why IoT security is structurally broken"""
IOT_PROBLEM = {
'cost_pressure': {
'reality': 'A smart light bulb retails for $12. The manufacturer margin '
'is $1-2. Adding a secure boot chip ($0.50), encrypted storage '
'($0.30), and ongoing firmware update infrastructure ($2/device/'
'year) makes the product unprofitable.',
'consequence': 'Security is the first thing cut from the BOM (bill of '
'materials). The CFO does not care about firmware signing '
'when the product already has 3% margins.',
},
'update_problem': {
'reality': 'Smartphone manufacturers provide 3-5 years of updates. IoT '
'manufacturers provide 0-2 years. Industrial control systems '
'run for 15-25 years. A PLC installed in 2010 will still be '
'running Windows XP Embedded in 2030.',
'consequence': 'The majority of IoT devices on the internet RIGHT NOW '
'are running firmware with known, unpatched vulnerabilities. '
'The manufacturers went out of business, pivoted to a new '
'product, or simply stopped caring.',
},
'user_awareness': {
'reality': 'The person who buys a $30 IP camera does not know (or care) '
'that it has a telnet service running with root:root credentials. '
'They plugged it in, connected it to wifi, and forgot about it.',
'consequence': 'There is no market pressure for security. Users buy on '
'price and features. "Has firmware signing" is not a feature '
'that moves units at Best Buy.',
},
'scale': {
'reality': '15+ billion devices. Growing by 2-3 billion per year. Each '
'one is a potential entry point, botnet node, or pivot point.',
'consequence': 'Even if 99% of new devices shipped tomorrow were perfectly '
'secure (they will not be), the existing installed base of '
'billions of vulnerable devices remains on the internet for '
'years to come.',
},
}
print("=== Why IoT Security Is Structurally Broken ===\n")
for factor, data in IOT_PROBLEM.items():
label = factor.replace('_', ' ').title()
print(f"--- {label} ---")
print(f" Reality: {data['reality']}")
print(f" Consequence: {data['consequence']}")
print()
Having said that, the economic argument does not excuse the manufacturers -- it EXPLAINS them. Understanding why IoT is insecure helps us prioritize where to focus defensive efforts (spoiler: network isolation beats device-level fixes every time).
Firmware Analysis -- Extracting the Device's Brain
Every IoT device runs firmware -- the software baked into the device's flash memory. Extracting and analyzing firmware is the single most effective IoT security assessment technique. You do not need physical access to the device if the manufacturer publishes firmware updates on their support page (and most of them do):
# Step 1: Obtain the firmware
# Option A: Download from manufacturer's website (firmware update section)
# Option B: Extract from the device via UART/JTAG/SPI (hardware access)
# Option C: Intercept an OTA update (network capture during update check)
# Many manufacturers host firmware as .bin, .img, or .zip on their CDN
# Step 2: Analyze the firmware image with binwalk
binwalk firmware.bin
# DECIMAL HEXADECIMAL DESCRIPTION
# 0 0x0 uImage header, size: 1048576
# 64 0x40 LZMA compressed data
# 1048576 0x100000 Squashfs filesystem, little endian, v4.0
# 2097152 0x200000 JFFS2 filesystem, little endian
# Step 3: Extract the filesystem
binwalk -e firmware.bin
cd _firmware.bin.extracted/squashfs-root/
# Step 4: Hunt for secrets
# Password files
cat etc/shadow # password hashes -- often MD5 or even plaintext!
cat etc/passwd
# Configuration files with credentials
grep -r "password" etc/
grep -r "admin" etc/
grep -r "secret" etc/
grep -r "key" etc/ --include="*.conf"
# Find ALL configuration files and search them
find . -name "*.conf" -exec grep -l "pass\|key\|secret\|token" {} \;
# Search compiled binaries for hardcoded strings
strings usr/sbin/httpd | grep -i "password\|admin\|root\|backdoor"
strings usr/bin/management_daemon | grep -i "api_key\|secret"
# Look for private keys and certificates
find . -name "*.pem" -o -name "*.key" -o -name "*.crt"
# If you find TLS private keys: they are the SAME key on every device
# of this model. One key compromise = MITM every device worldwide.
# Step 5: Check for debug/backdoor services
grep -r "telnetd\|dropbear\|sshd" etc/init.d/
# Many devices start telnet or SSH at boot with default credentials
Let me walk you through what you typically find, because it's almost comically bad:
#!/usr/bin/env python3
"""firmware_findings.py -- what firmware analysis reveals"""
COMMON_FINDINGS = [
{
'finding': 'Hardcoded credentials',
'prevalence': '90%+ of consumer IoT devices',
'details': 'root:admin, admin:admin, admin:password, or device-specific '
'defaults. Sometimes in /etc/shadow (crackable hashes), sometimes '
'compiled directly into the management binary as plaintext strings. '
'One D-Link camera model had the password "Dahua2017" hardcoded in '
'the httpd binary -- not even a hash, just the string.',
'episode_connection': 'Episode 7 (passwords) -- same problem, different domain',
},
{
'finding': 'Telnet/SSH with default credentials',
'prevalence': '60-70% of consumer devices',
'details': 'The manufacturer left debugging interfaces active in production '
'firmware. Telnet on port 23 with root:root or empty password. '
'No rate limiting on login attempts.',
'episode_connection': 'Episode 5 (scanning) -- nmap finds these instantly',
},
{
'finding': 'Unencrypted firmware updates',
'prevalence': '40-50% of devices',
'details': 'Device downloads updates over HTTP, no TLS. No signature '
'verification on the firmware image. Attacker on the same network '
'can MITM the update and push malicious firmware. Device happily '
'installs it.',
'episode_connection': 'Episode 45 (supply chain) -- firmware update is a '
'supply chain, and it is completely unsigned',
},
{
'finding': 'Command injection in web interface',
'prevalence': '30-40% of devices with web UIs',
'details': 'CGI scripts that pass user input directly to shell commands. '
'The device has a "ping test" feature in the admin panel: '
'http://device/cgi-bin/ping.cgi?target=8.8.8.8;cat /etc/shadow '
'Same vulnerability class as episode 12, but with root privileges '
'and no WAF.',
'episode_connection': 'Episode 12 (injection) + episode 31 (already root)',
},
{
'finding': 'Shared TLS certificates and private keys',
'prevalence': '25-35% of devices using HTTPS',
'details': 'The manufacturer generated ONE TLS certificate with private key '
'and compiled it into firmware. Every device of that model uses the '
'same certificate. Extract the private key from ANY device and you '
'can MITM the HTTPS connection to every other device of that model.',
'episode_connection': 'Episode 9 (cryptography) -- this breaks the entire '
'PKI trust model',
},
]
print("=== Common Firmware Analysis Findings ===\n")
for f in COMMON_FINDINGS:
print(f"--- {f['finding']} ({f['prevalence']}) ---")
print(f" {f['details']}")
print(f" Series connection: {f['episode_connection']}")
print()
The shared TLS key finding deserves extra attention. When you extract a private key from one $25 IP camera and discover it's identical across every unit of that model worldwide, you realize the manufacturer fundamentally misunderstands public key infrastructure. They treated the certificate like a configuration file instead of a unique identity. One extraction -- from any unit, bought on Amazon -- compromises every device's encrypted traffic.
Hardware Hacking -- Opening the Case
Sometimes firmware is not available for download and you need to extract it from the device itself. This is where hardware hacking comes in. Opening the case and connecting to debug interfaces on the PCB (printed circuit board) gives you access that the manufacturer never intended:
=== UART (Universal Asynchronous Receiver/Transmitter) ===
UART is a serial debug interface found on most IoT device PCBs.
It often provides a root shell with ZERO authentication.
How to find it:
1. Open the device (remove screws, pry clips on case seam)
2. Locate the PCB (printed circuit board)
3. Look for 4 pins in a row, often labeled: GND, TX, RX, VCC
Sometimes unlabeled -- use a multimeter to identify:
GND = 0V (continuity with ground plane)
VCC = 3.3V or 5V (steady voltage)
TX = fluctuating voltage (data being transmitted)
RX = steady high (waiting for input)
4. Connect a USB-to-UART adapter (FTDI FT232, CP2102 -- $5-10)
IMPORTANT: match voltage levels (3.3V vs 5V) or you fry the board
5. Set baud rate (try: 115200, 9600, 57600, 38400)
6. Open terminal: screen /dev/ttyUSB0 115200
What you typically get:
- Full boot log (kernel version, loaded modules, mount points)
- Login prompt -- try: root/root, admin/admin, or empty password
- Often: direct root shell with NO password prompt at all
- If login required: boot log may reveal credentials in cleartext
=== JTAG (Joint Test Action Group) ===
JTAG provides deeper access than UART -- full hardware-level control:
- Read/write flash memory (extract firmware directly from chip)
- Debug running code (set breakpoints, examine registers, step through)
- Bypass secure boot (on some implementations -- dump keys from memory)
- Brick recovery (re-flash a device you accidentally corrupted)
Tools:
- JTAGulator ($170) -- automatically identifies JTAG pins
- OpenOCD -- open-source debug interface software
- Bus Pirate ($30) -- multi-protocol hardware hacking tool
JTAG is the "game over" interface. If JTAG pads are accessible and
not disabled in production, you have complete control of the device at
the hardware level. Some manufacturers remove JTAG pads, cut traces,
or blow eFuses to disable it -- but many simply leave it open.
=== SPI (Serial Peripheral Interface) ===
SPI is used to communicate with flash memory chips. With a SOIC clip
($5-10) you can connect directly to the flash chip WITHOUT desoldering:
- Read the entire flash contents (firmware dump)
- Write modified firmware back to the chip
- Tools: flashrom, CH341A programmer ($3 on AliExpress)
Total hardware hacking kit cost: under $50
Access level: root on most consumer IoT devices
I want to be clear about something: the fact that a $50 hardware hacking kit gives you root access on most consumer IoT devices is NOT a sign that the security community has failed. It's a sign that the IoT industry has not yet reached the maturity level where security is a design requirement rather than an afterthought. The smartphone industry went through this same phase -- remember when Android devices shipped with unlocked bootloaders and root was a su command away? The phone industry fixed it (mostly). The IoT industry has not, and the economic incentives suggest it may never fix it for cheap consumer devices.
Network-Based IoT Attacks
You don't always need physical access. Many IoT devices expose services and protocols on the network that are trivially exploitable:
# Shodan: the search engine for internet-connected devices
# Indexes banners from every device responding on the internet
shodan search "webcam" country:NL
shodan search "default password" port:23
shodan search "Server: GoAhead" has_screenshot:true
# GoAhead is a web server used by hundreds of IP camera models
# Censys: similar to Shodan, focuses on certificate and service data
# Both are LEGAL -- they only scan publicly accessible services
# Find IoT devices on your local network
nmap -sV -p 80,443,23,22,8080,8443,554,1883,5683 192.168.1.0/24
# Port 554: RTSP (cameras -- often unauthenticated video streams)
# Port 1883: MQTT (IoT messaging -- often no authentication)
# Port 5683: CoAP (constrained IoT protocol -- often open)
# MQTT (Message Queuing Telemetry Transport)
# Lightweight pub/sub messaging protocol -- the backbone of smart homes
# Wildcard subscribe: see EVERY message on the broker
mosquitto_sub -h TARGET_IP -t '#' -v
# You might see: temperature readings, door open/close events,
# light on/off commands, motion sensor triggers, GPS coordinates
# All in cleartext. No authentication. No encryption.
# An attacker on the same network sees everything your smart home does.
# Publish a command to an MQTT topic (if no authentication)
mosquitto_pub -h TARGET_IP -t 'home/door/lock' -m 'UNLOCK'
# If the smart lock subscribes to this topic without auth... yep.
# UPnP (Universal Plug and Play)
# Automatically opens firewall ports WITHOUT the user's knowledge
upnpc -l # list UPnP port mappings on the router
# Many IoT devices use UPnP to punch holes in the firewall
# so they can be accessed from the internet. The user never consented.
# Result: IP camera's web interface is world-accessible with admin:admin
# CoAP (Constrained Application Protocol)
# UDP-based IoT protocol for resource-constrained devices
coap-client -m get coap://TARGET_IP/.well-known/core
# Enumerate all resources -- sensor readings, config endpoints, etc.
#!/usr/bin/env python3
"""iot_protocols.py -- IoT protocol security assessment"""
IOT_PROTOCOLS = {
'mqtt': {
'port': 1883,
'tls_port': 8883,
'auth_default': 'None (anonymous connections allowed by default)',
'encryption': 'Optional TLS (rarely configured on cheap devices)',
'risk': 'Subscribe to all topics, read sensor data, send commands. '
'Smart home data exfiltration, device control, DoS via '
'message flooding.',
'real_world': 'Researchers found 60,000+ MQTT brokers exposed to the '
'internet with no authentication (Avast, 2018). Many were '
'smart home hubs leaking location data, health device '
'readings, and home occupancy patterns.',
},
'coap': {
'port': 5683,
'tls_port': 5684,
'auth_default': 'None (most implementations skip DTLS)',
'encryption': 'DTLS optional (UDP-based TLS equivalent)',
'risk': 'Read sensor values, modify actuator states, enumerate '
'all device resources via .well-known/core discovery.',
'real_world': 'CoAP amplification attacks -- small request generates '
'large response. Used in DDoS reflection attacks.',
},
'zigbee': {
'port': 'N/A (802.15.4 wireless, not IP)',
'tls_port': 'N/A',
'auth_default': 'Network key (often default or interceptable during pairing)',
'encryption': 'AES-128 (but key exchange is the weak point)',
'risk': 'During device pairing, the network key may be transmitted in '
'cleartext or with a well-known "trust center" key. Sniff the '
'pairing process = decrypt all future traffic.',
'real_world': 'Zigbee worm: researchers demonstrated a worm that could '
'spread between Philips Hue bulbs via OTA update mechanism '
'(2016). Each infected bulb attacks its neighbors.',
},
'z_wave': {
'port': 'N/A (sub-GHz wireless)',
'tls_port': 'N/A',
'auth_default': 'S0 security (broken), S2 security (current, better)',
'encryption': 'AES-128',
'risk': 'Z-Wave S0 used a fixed key for initial exchange -- interceptable. '
'Downgrade attack: force device to use S0 instead of S2 during '
'inclusion. Door locks using S0 can be unlocked remotely.',
'real_world': 'Pen Test Partners demonstrated unlocking Z-Wave door locks '
'by forcing S0 downgrade during re-pairing (2018).',
},
}
print("=== IoT Protocol Security Assessment ===\n")
for proto, data in IOT_PROTOCOLS.items():
print(f"--- {proto.upper()} (port {data['port']}) ---")
print(f" Default auth: {data['auth_default']}")
print(f" Encryption: {data['encryption']}")
print(f" Risk: {data['risk']}")
print(f" Real world: {data['real_world']}")
print()
The MQTT situation is particularly alarming. A protocol designed for machine-to-machine communication in constrained environments got adopted by the consumer smart home industry, and most implementations ship with authentication disabled by default. The result: tens of thousands of MQTT brokers on the internet broadcasting everything from room temperatures to GPS coordinates to door lock states. Anyone can subscribe. Anyone can publish. That smart home automation you set up so your lights turn off when you leave? An attacker subscribing to your MQTT broker now knows your occupancy patterns.
ICS/SCADA -- Where IoT Meets Critical Infrastructure
This is where IoT security stops being about stolen camera feeds and starts being about physical safety and national security:
#!/usr/bin/env python3
"""ics_security.py -- industrial control system attack surface"""
ICS_LANDSCAPE = {
'what_ics_controls': [
'Power grids (electricity generation, transmission, distribution)',
'Water treatment plants (chemical dosing, filtration, pumping)',
'Manufacturing (assembly lines, CNC machines, robotics)',
'Oil and gas (pipelines, refineries, offshore drilling)',
'Transportation (traffic lights, rail switches, airport systems)',
'Building automation (HVAC, elevators, fire suppression)',
'Healthcare (medical gas systems, building management, lab equipment)',
],
'why_its_terrifying': [
'Many ICS systems run Windows XP, Windows 7, or even Windows 2000',
'Protocols like Modbus (1979) and DNP3 have ZERO authentication',
'Air-gapped networks are often not truly air-gapped (USB, vendor VPN)',
'IT/OT convergence is connecting previously isolated systems to corporate nets',
'Patching is nearly impossible -- a reboot means stopping the production line',
'A compromise can cause physical damage, environmental contamination, or death',
'Average age of ICS components: 15-25 years. Designed before "cybersecurity" existed',
],
}
ICS_ATTACKS = [
{
'name': 'Stuxnet (2010)',
'target': 'Iranian nuclear enrichment facility (Natanz)',
'method': 'Worm delivered via USB drive to air-gapped network. Exploited 4 '
'zero-days in Windows. Targeted Siemens Step 7 PLC software. '
'Modified PLC code to spin centrifuges at destructive speeds '
'(1,410 Hz instead of normal 1,064 Hz) while reporting normal '
'operation to the SCADA display.',
'impact': 'Destroyed ~1,000 uranium enrichment centrifuges. Set Iranian '
'nuclear program back an estimated 2 years. Operators watched '
'their screens showing everything running perfectly while the '
'centrifuges tore themselves apart.',
'lesson': 'Cyber weapons can cause physical destruction. Air gaps are '
'not absolute. The most dangerous attack is one where the '
'monitoring system lies to the operator.',
},
{
'name': 'Ukraine Power Grid (2015, 2016)',
'target': 'Ukrainian electrical distribution companies',
'method': '2015: Spear-phishing emails with BlackEnergy malware. Attackers '
'spent months inside the network mapping SCADA systems. On Dec 23, '
'remotely operated the SCADA to open circuit breakers. 230,000 '
'customers lost power for 1-6 hours.\n'
'2016: Industroyer/CrashOverride malware designed specifically to '
'attack power grid protocols (IEC 61850, IEC 104, OPC DA).',
'impact': 'First confirmed cyber attack causing a power outage. Russian '
'state actors (Sandworm group). Demonstrated that grid takeover '
'is practical, not theoretical.',
'lesson': 'The attackers did not need zero-days. Spear-phishing + patience '
'+ understanding of ICS protocols was enough. Episode 39 (email '
'security) meets episode 34 (lateral movement).',
},
{
'name': 'Oldsmar Water Treatment (2021)',
'target': 'Water treatment plant in Oldsmar, Florida',
'method': 'Attacker accessed the plant SCADA system via TeamViewer (remote '
'desktop software left running for vendor access). Attempted to '
'increase sodium hydroxide (lye) levels from 100 ppm to 11,100 ppm '
'-- a potentially lethal concentration.',
'impact': 'Operator noticed the cursor moving and reversed the change within '
'minutes. No public harm. But the attack demonstrated that a single '
'unsecured remote access point to a water treatment plant could have '
'poisoned a city water supply.',
'lesson': 'TeamViewer with shared credentials on a SCADA network. Every '
'episode of this series screams at this: default credentials '
'(ep 7), remote access without MFA (ep 17), no network segmentation '
'(ep 53), no monitoring (ep 51).',
},
]
print("=== What ICS Controls ===\n")
for item in ICS_LANDSCAPE['what_ics_controls']:
print(f" - {item}")
print("\n=== Why ICS Security Is Terrifying ===\n")
for item in ICS_LANDSCAPE['why_its_terrifying']:
print(f" - {item}")
print("\n=== Notable ICS Attacks ===\n")
for attack in ICS_ATTACKS:
print(f"--- {attack['name']} ---")
print(f" Target: {attack['target']}")
print(f" Method: {attack['method']}")
print(f" Impact: {attack['impact']}")
print(f" Lesson: {attack['lesson']}")
print()
# ICS protocol scanning (lab environment ONLY)
# NEVER scan production ICS systems -- a malformed packet can crash a PLC
# and crashing a PLC can stop a factory, a water pump, or a turbine
# Modbus scanning (port 502)
nmap -p 502 --script modbus-discover TARGET_IP
# Returns: Device ID, vendor, product code, firmware version
# Modbus read registers (no authentication on most PLCs)
# pip install pymodbus
python3 -c "
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('TARGET_IP')
client.connect()
result = client.read_holding_registers(0, 10)
print('Registers 0-9:', result.registers)
# These are LIVE process values -- temperatures, pressures, flow rates
# Reading is bad enough. Writing can cause physical damage.
client.close()
"
# Shodan for ICS (find exposed systems -- DO NOT interact)
shodan search "port:502 modbus"
shodan search "port:102 S7comm" # Siemens S7 PLCs
shodan search "port:44818 EtherNet/IP" # Allen-Bradley/Rockwell
# These should NEVER be on the internet. And yet thousands are.
The Oldsmar attack keeps me up at night more than Stuxnet. Stuxnet was a nation-state operation involving four zero-days and years of development. Oldsmar was someone connecting to TeamViewer with shared credentials and moving a slider. The sophistication required was ZERO. The potential consequense was poisoning a city's water supply. That gap between attack complexity and potential impact is what makes ICS security so urgent.
The Mirai Botnet -- IoT's Defining Moment
#!/usr/bin/env python3
"""mirai.py -- the botnet that weaponized the IoT problem"""
MIRAI = {
'how_it_worked': [
'Scanned the internet for devices with open Telnet (port 23)',
'Tried 62 default credential pairs (admin:admin, root:root, '
'root:xmhdipc, root:vizxv, admin:7ujMko0admin, etc.)',
'Infected devices became part of the botnet immediately',
'At peak: 600,000+ compromised cameras, routers, DVRs, NVRs',
'Source code was released publicly on HackForums by "Anna-senpai"',
'Variants are STILL active in 2026 because the devices are '
'still vulnerable and the owners still have not updated',
],
'attacks_launched': [
'DDoS against Dyn DNS (Oct 2016): took down Twitter, Reddit, '
'Netflix, GitHub, CNN, Spotify, and dozens of major websites. '
'Half the US internet was unreachable for hours.',
'DDoS against OVH: 1 Tbps attack (record at the time)',
'DDoS against Brian Krebs website: 620 Gbps (security journalist)',
'DDoS against Liberian ISP: took an entire country offline',
],
'why_it_matters': 'Mirai proved that billions of insecure IoT devices are '
'not just a theoretical risk -- they are a WEAPON. 62 '
'credential pairs and a port scan were enough to build '
'one of the largest botnets in history. The devices were '
'not the target -- they were the ammunition.',
'aftermath': 'Three college students (Paras Jha, Josiah White, Dalton '
'Norman) were eventually identified and pleaded guilty. They '
'originally built Mirai to DDoS competing Minecraft servers. '
'A tool built to gain advantage in a video game took down '
'half the US internet.',
}
print("=== Mirai Botnet ===\n")
print("How it worked:")
for step in MIRAI['how_it_worked']:
print(f" - {step}")
print(f"\nAttacks:")
for attack in MIRAI['attacks_launched']:
print(f" - {attack}")
print(f"\nWhy it matters: {MIRAI['why_it_matters']}")
print(f"\nAftermath: {MIRAI['aftermath']}")
Built to DDoS Minecraft servers. Ended up taking down half the internet. That is the IoT security story in one sentence. The devices that participated in the attack -- IP cameras, DVRs, routers -- their owners had no idea. Their ISPs had no idea. The devices were silently conscripted into an army and pointed at DNS infrastructure. This is what "the largest unpatched attack surface on earth" looks like when someone decides to weaponize it ;-)
Defense -- Securing IoT (Where Possible)
#!/usr/bin/env python3
"""iot_defense.py -- practical IoT security controls"""
DEFENSE_LAYERS = {
'network_isolation': {
'priority': 'HIGHEST -- this is the single most effective IoT defense',
'actions': [
'Separate VLAN for all IoT devices -- they NEVER need to be on '
'the same network as your workstations or servers',
'Firewall rules: IoT VLAN cannot initiate connections to corporate VLAN',
'Allow only specific outbound connections (NTP, manufacturer cloud API)',
'Block all other internet access unless specifically required',
'Monitor IoT VLAN traffic for anomalies (beaconing, scanning, '
'unusual DNS queries, connections to known C2 infrastructure)',
'Disable UPnP on your router -- IoT devices abuse it to punch holes',
],
'why_this_works': 'You cannot patch a $12 light bulb. You cannot update '
'firmware on a device whose manufacturer went bankrupt. '
'But you CAN put it on a network where even if it is '
'fully compromised, it cannot reach anything valuable.',
},
'device_hardening': {
'priority': 'HIGH -- do this for every device you control',
'actions': [
'Change default credentials IMMEDIATELY on setup (the #1 fix)',
'Disable unnecessary services (Telnet, UPnP, remote management)',
'Update firmware if updates are available',
'Disable cloud features you do not use (many devices phone home)',
'If the device supports it: enable encrypted protocols (MQTTS, HTTPS)',
],
'why_this_works': 'Default credentials are the #1 IoT attack vector. '
'Mirai succeeded with 62 credential pairs. Changing the '
'password defeats the entire botnet.',
},
'purchasing_decisions': {
'priority': 'MEDIUM -- prevent problems before they start',
'actions': [
'Does the manufacturer provide regular security updates?',
'Is there a vulnerability disclosure program or bug bounty?',
'Does the device support encrypted communication?',
'Can default credentials be changed?',
'What happens when the manufacturer goes out of business?',
'Does the device work WITHOUT cloud connectivity? (offline-capable)',
'Has the device been independently security-tested?',
],
'why_this_works': 'The cheapest IoT device is the most expensive when '
'it becomes a botnet node or network entry point. '
'Paying $20 more for a device with security updates '
'saves thousands in incident response.',
},
'monitoring': {
'priority': 'MEDIUM -- detect when prevention fails',
'actions': [
'DNS monitoring: IoT device suddenly resolving C2 domains = compromised',
'Traffic baseline: learn normal patterns, alert on deviations',
'Port scan detection: compromised IoT scanning your internal network',
'Bandwidth monitoring: sudden spike = DDoS participation or data exfil',
],
'why_this_works': 'Same principles as episode 51 (incident response) and '
'episode 52 (threat intel). You cannot patch every device '
'but you CAN detect when one starts behaving like malware.',
},
}
print("=== IoT Defense Strategy ===\n")
for layer, data in DEFENSE_LAYERS.items():
label = layer.replace('_', ' ').title()
print(f"--- {label} (Priority: {data['priority']}) ---")
for action in data['actions']:
print(f" - {action}")
print(f" Why: {data['why_this_works']}")
print()
print("The uncomfortable truth: most consumer IoT devices cannot be")
print("secured at the device level. The best defense is network isolation --")
print("assume the device is compromised and prevent it from reaching")
print("anything valuable. This is defense in depth from episode 53 applied")
print("to the weakest link in your network.")
The AI Slop Connection
AI is making IoT security worse in two distinct ways, and both connect directly to what we covered in episode 6.
First, AI-generated firmware code reproduces the same vulnerabilities found in decades of insecure embedded C: buffer overflows, command injection in CGI handlers, hardcoded credentials baked into binaries. The AI learned from millions of lines of bad embedded code on GitHub and generates more of it. A developer asks the AI to generate a "simple web interface for my IoT device" and gets back a CGI handler that pipes user input directly to system(). The AI does not know (and does not care) that the code runs as root on a device controlling a door lock.
Second, AI is being embedded INTO IoT devices -- smart cameras with face recognition, voice assistants with NLP, smart home hubs with decision-making capabilities. These AI-enhanced devices have the original IoT vulnerabilities (default creds, no updates, no encryption) PLUS new AI-specific attack surfaces: adversarial inputs that confuse the model, model poisoning via manipulated training data, and privacy violations from on-device data processing that sends everything back to the manufacturer's cloud.
AI-Generated IoT Code Problems:
1. Web interface CGI handlers
AI generates: system("ping " + user_input) -- direct command injection
Should be: input validation + exec with argument array (no shell)
2. Authentication
AI generates: if (strcmp(password, "admin123")) -- hardcoded credential
Should be: configurable credential stored in protected flash partition
3. Memory management
AI generates: char buffer[64]; strcpy(buffer, request) -- overflow
Should be: strncpy with bounds checking, or better: use safe string lib
4. Update mechanism
AI generates: download firmware via HTTP, flash immediately
Should be: HTTPS + signature verification + rollback capability
5. Data transmission
AI generates: send sensor_data over plaintext TCP socket
Should be: TLS with certificate pinning to manufacturer endpoint
Same pattern as every other domain: AI optimizes for "it compiles"
not "it resists attack." But on an IoT device running as root with
no firewall, the consequences of bad code are immediate and physical.
What Comes Next
IoT security brings everything in this series from the virtual world into the physical one. The attacks are familiar -- default credentials, command injection, missing encryption, supply chain compromise -- but the consequences extend beyond data theft into physical safety. When a vulnerability can unlock a door, disable a medical device, or shut down a power grid, the stakes of security shift from financial to existential. We've covered the full spectrum of attacks (episodes 1-50), the defensive disciplines (architecture, IR, threat intel, compliance, privacy), and the specialized domains (crypto, IoT). The next phase of this series moves to the tooling side: how do you build your own security tools, automate the techniques we've practiced by hand, and develop the programming skills that separate script users from security engineers?
Exercises
Exercise 1: Download a firmware image for a popular IoT device (many manufacturers publish updates on their support pages -- try TP-Link, D-Link, or Netgear routers). Use binwalk to extract the filesystem. Document: (a) what filesystem type was used (squashfs, JFFS2, cramfs), (b) any hardcoded credentials found in /etc/shadow or configuration files, (c) what services start at boot (/etc/init.d/ scripts -- look for telnetd, httpd, sshd), (d) any private keys or certificates found, (e) strings output from the main web server binary (look for hardcoded passwords or API keys). Save your findings to ~/lab-notes/firmware-analysis.md.
Exercise 2: Use Shodan (free tier, no account needed for basic searches) to search for exposed IoT devices in your country. Try queries: "default password" port:23, "Server: GoAhead", webcamXP, "authentication disabled" port:1883 (MQTT brokers). Document: (a) how many results each query returns, (b) what device types are most commonly exposed, (c) what the most common open ports are across results, (d) any patterns in manufacturer or firmware version. Do NOT interact with any device -- observation only. Save to ~/lab-notes/shodan-iot-recon.md.
Exercise 3: Research the Stuxnet worm in depth. Document: (a) the delivery mechanism (USB drive propagation to air-gapped network), (b) the full exploitation chain (four zero-days in Windows: print spooler, .lnk shortcut, Windows Server Service, Task Scheduler), (c) the payload (Siemens Step 7 PLC code modification -- what specific PLC instructions were changed and why), (d) stealth mechanisms (rootkit on both Windows AND the PLC that hid modified ladder logic from the SCADA display), (e) the physical damage caused (centrifuge speed manipulation: normal 1,064 Hz pushed to 1,410 Hz), (f) attribution evidence (joint US-Israel operation, codenamed Olympic Games). Save to ~/lab-notes/stuxnet-analysis.md.
De groeten!
Leave Learn Ethical Hacking (#57) - IoT and Embedded Security - Hacking the Physical World to:
Read more #stem posts
Best Posts From scipio
We have not curated any of scipio's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.
More Posts From scipio
- Learn AI Series (#141) - Robotics and Embodied AI
- Learn Zig Series (#121) - Topological Sort
- Learn Rust Series (#10) - Lifetimes
- Learn AI Series (#140) - Scientific AI
- Learn Zig Series (#120) - Dijkstra and A*
- Learn Rust Series (#9) - Modules & Crates
- Learn AI Series (#139) - AI for Code
- Learn Zig Series (#119) - BFS and DFS
- Learn Rust Series (#8) - Traits & Generics
- Learn AI Series (#138) - Multimodal AI