In October 2016, a botnet of IP cameras, DVRs, and home routers knocked GitHub, Twitter, Netflix, and PayPal offline simultaneously. The attack did not originate from some sophisticated nation-state infrastructure. It came from ordinary consumer electronics sitting in homes and small offices — devices whose owners had never changed the factory default password, never applied a firmware update, and had no idea their camera was making outbound TCP connections to a server in France while simultaneously streaming video to their phone.
Mirai was not sophisticated in the traditional sense. It was methodical. It scanned the entire routable IPv4 address space, tried sixty default passwords, and built an army of 600,000 devices. When it attacked, it delivered attack traffic that no single data center could absorb.
This post dissects how Mirai works at the code and protocol level, traces the anatomy of the Dyn DDoS attack, covers detection techniques for identifying compromised IoT devices in your environment, and lays out the segmentation and monitoring controls that actually constrain the threat.
Mirai Architecture: How the Botnet Works
Mirai consists of three distinct components operating in coordination:
- Scanner/bot: Runs on each compromised device. Scans for new victims and executes DDoS attack commands.
- Report server: Receives reports of new vulnerable hosts found by scanners. Passes candidates to the loader.
- Loader: Receives host credentials from the report server, logs in via Telnet, and installs the bot binary for the device’s CPU architecture (MIPS, ARM, x86, PowerPC, SH4, m68k).
- C2 server: Receives bot registrations, issues attack commands, tracks botnet size and status.
Scanner Logic
Mirai’s scanner generates random IPv4 addresses, excluding RFC1918 private ranges, IANA reserved space, CGNAT, and the US DoD ranges. It then probes TCP port 23 (Telnet) and port 2323 (used by some embedded devices as an alternative Telnet port).
The following Python is a simplified conceptual equivalent for educational purposes — it illustrates the logic without being a functional exploit tool:
1#!/usr/bin/env python3
2"""
3Conceptual illustration of Mirai scanner logic.
4NOT a functional exploit — for educational analysis only.
5"""
6import random
7import ipaddress
8
9# IPv4 ranges excluded by Mirai scanner (blacklisted)
10EXCLUDED = [
11 "0.0.0.0/8", "127.0.0.0/8", "10.0.0.0/8",
12 "192.168.0.0/16", "172.16.0.0/12", "100.64.0.0/10",
13 "169.254.0.0/16", "192.0.2.0/24", "198.51.100.0/24",
14 "203.0.113.0/24", "224.0.0.0/4", "240.0.0.0/4",
15 "255.255.255.255/32",
16]
17EXCLUDED_NETS = [ipaddress.ip_network(n) for n in EXCLUDED]
18
19def random_public_ip():
20 while True:
21 ip = ipaddress.IPv4Address(random.randint(0, 2**32 - 1))
22 if not any(ip in net for net in EXCLUDED_NETS):
23 return str(ip)
24
25# Mirai's hardcoded credential pairs (subset — full list is 60 pairs)
26CREDENTIALS = [
27 ("root", "xc3511"), # Common Hikvision DVR default
28 ("root", "vizxv"), # Common camera firmware default
29 ("admin", "admin"),
30 ("root", "admin"),
31 ("admin", ""),
32 ("root", ""),
33 ("admin", "1234"),
34 ("root", "root"),
35 ("admin", "9999"),
36 ("root", "pass"),
37 # ... 50 more pairs in actual Mirai
38]
39
40# Scanner would: connect TCP to random_public_ip():23,
41# attempt Telnet banner matching, try each credential pair,
42# and report successful logins to report server.
43# This function is intentionally incomplete — not a working exploit.
44def illustrate_scan_target():
45 target = random_public_ip()
46 print(f"Would probe {target}:23 and {target}:2323")
47 print(f"Would try {len(CREDENTIALS)} credential pairs")
Shodan Queries for Exposure Assessment
Security teams can use Shodan to assess how many devices matching vulnerable product families are exposed on their IP ranges:
1# Hikvision cameras with default web interface
2shodan search "Hikvision-Webs" --fields ip_str,port,org
3
4# Dahua DVR exposure
5shodan search "DahuaHttp" --fields ip_str,port,org
6
7# Generic CCTV/DVR on Telnet
8shodan search "port:23 DVR" --fields ip_str,port,hostnames
9
10# Mirai-related: open Telnet with common banner strings
11shodan search "port:23 login:" --fields ip_str,port,org,isp
12
13# Search your own IP range for exposed IoT
14shodan search "net:203.0.113.0/24" --fields ip_str,port,product
The Dyn DDoS Attack — October 21, 2016
Timeline
| Time (EDT) | Event |
|---|---|
| 07:10 | First wave begins. DNS queries to Dyn’s Managed DNS infrastructure spike. |
| 07:52 | Dyn confirms DDoS under way. Twitter, Reddit, Spotify, Airbnb, GitHub begin failing. |
| 09:20 | Dyn resolves first wave. Service partially restored. |
| 11:52 | Second attack wave begins. Netflix, PayPal, CNN affected. |
| 17:00 | Third wave. Attack traffic estimated at 1.2 Tbps. |
| 20:00 | Attack subsides. Most services restore. |
Attack Vector
Mirai bots primarily used UDP flood (random UDP packets to random ports) and DNS water torture (high-volume random subdomain queries to target authoritative DNS servers). The DNS water torture attack was particularly effective against Dyn because:
- Each query required Dyn to look up a unique, non-cached QNAME.
- Legitimate resolvers forwarded Mirai bots’ spoofed queries to Dyn, amplifying the traffic.
- DNS infrastructure is inherently stateless and difficult to rate-limit without dropping legitimate traffic.
Aftermath and Variants
After the Mirai source code was published in September 2016, the following variants emerged:
- Satori (2017): Added exploit modules targeting Huawei HG532 (CVE-2017-17215) and GPON routers, enabling zero-credential compromise without Telnet.
- Hajime (2016): A “worm war” variant that appeared to fight Mirai by closing Telnet ports after compromise — its motivations remain debated.
- Botnet of Things / Okiru (2018): Targeted ARC CPU architecture, dramatically expanding the device surface.
- Moobot (2021): Targeted Hikvision cameras (CVE-2021-36260, an unauthenticated command injection) — no brute-force required.
Detection
iptables Rules to Detect Outbound Scanning from IoT Devices
If you segment IoT devices onto a dedicated VLAN (192.168.200.0/24 in this example), these iptables rules on the router/firewall detect anomalous outbound activity:
1# Log outbound connections from IoT VLAN on Telnet port (23)
2# (IoT devices should never be initiating Telnet outbound)
3iptables -I FORWARD -s 192.168.200.0/24 -p tcp --dport 23 \
4 -j LOG --log-prefix "IOT-OUTBOUND-TELNET: " --log-level 4
5
6# Drop it after logging
7iptables -I FORWARD -s 192.168.200.0/24 -p tcp --dport 23 -j DROP
8
9# Log high-volume UDP from IoT VLAN (potential DDoS participation)
10iptables -I FORWARD -s 192.168.200.0/24 -p udp \
11 -m limit --limit 1000/min --limit-burst 2000 \
12 -j LOG --log-prefix "IOT-UDP-FLOOD: " --log-level 4
13
14# Block outbound IoT traffic except what's required
15# (Allow only HTTPS for cloud management, NTP, DNS to local resolver)
16iptables -I FORWARD -s 192.168.200.0/24 -p tcp --dport 443 -j ACCEPT
17iptables -I FORWARD -s 192.168.200.0/24 -p udp --dport 53 -j ACCEPT
18iptables -I FORWARD -s 192.168.200.0/24 -p udp --dport 123 -j ACCEPT
19iptables -I FORWARD -s 192.168.200.0/24 -j DROP
Zeek Script for C2 Beaconing Detection
# /usr/local/zeek/share/zeek/site/iot-beacon-detect.zeek
# Detect regular beaconing from IoT VLAN to external IPs
@load base/protocols/conn
module IoTBeacon;
export {
redef enum Notice::Type += { Potential_Beacon };
const iot_subnet: subnet = 192.168.200.0/24 &redef;
const beacon_interval_threshold: interval = 58sec &redef;
const beacon_interval_variance: interval = 5sec &redef;
}
global connection_history: table[addr, addr] of vector of time;
event connection_state_remove(c: connection)
{
local orig = c$id$orig_h;
local resp = c$id$resp_h;
if ( orig !in iot_subnet ) return;
if ( is_local_addr(resp) ) return; # Skip internal traffic
local pair = [orig, resp];
if ( pair !in connection_history )
connection_history[pair] = vector();
connection_history[pair] += network_time();
local hist = connection_history[pair];
if ( |hist| < 5 ) return;
# Check regularity of intervals
local intervals: vector of interval = vector();
for ( i in hist ) {
if ( i > 0 )
intervals += hist[i] - hist[i-1];
}
# If all intervals are within variance of the threshold: beacon
local regular = T;
for ( i in intervals ) {
if ( intervals[i] < beacon_interval_threshold - beacon_interval_variance ||
intervals[i] > beacon_interval_threshold + beacon_interval_variance )
regular = F;
}
if ( regular ) {
NOTICE([
$note = Potential_Beacon,
$src = orig,
$dst = resp,
$msg = fmt("IoT device %s beaconing to %s every ~%s",
orig, resp, beacon_interval_threshold)
]);
}
}
DNS Log Analysis for DGA Domains
Mirai variants using DGA-based C2 generate high-entropy, non-resolving domain queries from IoT devices:
1# Zeek dns.log — look for NXDOMAIN responses from IoT devices
2zeek-cut ts id.orig_h query qtype_name rcode_name \
3 < /var/log/zeek/current/dns.log \
4 | awk '$3~/192\.168\.200\./ && $6=="NXDOMAIN"' \
5 | sort | uniq -c | sort -rn | head -20
6
7# High entropy domain detection using a simple awk heuristic
8# (real implementations use Shannon entropy calculation)
9cat /var/log/zeek/current/dns.log \
10 | zeek-cut query \
11 | awk 'length($1) > 20 && $1 ~ /^[a-z0-9]{16,}\./' \
12 | sort | uniq -c | sort -rn
Defense and Mitigation
1. IoT Network Segmentation
The single most effective control is preventing IoT devices from communicating with corporate assets or from reaching arbitrary internet destinations:
Network Design:
IoT VLAN (192.168.200.0/24)
└── Default route: internet (HTTPS/443, DNS, NTP only)
└── Firewall rule: DENY any → Corporate VLAN
└── Firewall rule: DENY any → Server VLAN
└── No inbound access from internet
Corporate VLAN (10.0.0.0/8)
└── No route to IoT VLAN
2. Default Credential Policy
Enforce credential changes before any IoT device is permitted network access. This can be implemented via:
- 802.1X: Require certificate-based authentication before VLAN assignment. IoT devices that cannot do 802.1X are placed in an isolated quarantine VLAN.
- DHCP fingerprinting: Tools like ntopng or fingerbank identify device type from DHCP options and enforce policy before IP assignment.
3. Firmware Update Process
1# Automated firmware check for Hikvision cameras (ISAPI)
2curl -s --digest -u admin:YourPassword \
3 http://CAMERA_IP/ISAPI/System/updateFirmware \
4 | xmllint --format -
5
6# For Dahua cameras
7curl -s -u admin:YourPassword \
8 http://CAMERA_IP/cgi-bin/deviceSummary.cgi
For large deployments, network device management tools (Cisco IoT Control Center, Armis, Claroty) provide automated firmware vulnerability tracking and deployment workflows.
4. Network Behavior Detection with NDR
Network Detection and Response (NDR) tools like Darktrace, ExtraHop, or Vectra AI establish behavioral baselines for each IoT device. Deviations — such as an IP camera suddenly making outbound connections to port 23 on random IPs — trigger alerts regardless of whether the traffic matches a known signature.
5. Shodan Monitoring for External Exposure
1# Set up Shodan alerting for your IP ranges
2shodan alert create "MyOrg IoT Monitoring" 203.0.113.0/24
3
4# Trigger notifications when new devices appear on ports 23, 2323, 8080
5shodan alert triggers
6shodan alert enable <alert-id> open_port
MITRE ATT&CK Mapping
| Technique | ID | Description |
|---|---|---|
| Active Scanning: Scanning IP Blocks | T1595.001 | Mirai’s random IPv4 scan |
| Brute Force: Password Spraying | T1110.003 | Default credential list against Telnet |
| Network Denial of Service: Direct Network Flood | T1498.001 | UDP/DNS flood attack execution |
| Resource Hijacking | T1496 | IoT device commandeered for DDoS |
| Acquire Infrastructure: Botnet | T1583.005 | C2 infrastructure management |
Related Attacks in This Series
- Firmware Rootkit: Malware That Survives Reinstall
- Bluetooth BlueBorne Exploitation: No Pairing Needed
- DNS Hijacking: Redirecting Traffic Without You Knowing
- Supply Chain Attack: How SolarWinds Was Compromised
References
- MITRE ATT&CK T1595 — Active Scanning
- MITRE ATT&CK T1498 — Network Denial of Service
- Krebs on Security — KrebsOnSecurity Hit With Record DDoS (2016)
- Dyn Blog — October 21 DDoS Attack Summary
- CVE-2021-36260 — Hikvision Command Injection
- CVE-2017-17215 — Huawei HG532 RCE (Satori)
- Mirai Source Code Analysis — Cloudflare Blog
- NIST SP 800-213 — IoT Device Cybersecurity Guidance



