Mirai: The Botnet That Needed No Exploit

The first three parts of this series were about Windows botnets and the arms race around them. Coreflood was taken over because it did not sign its commands. Conficker signed everything and hid behind 50,000 domains a day. GameOver Zeus added a peer-to-peer network and still fell when defenders changed whom its bots trusted.

Mirai skipped that arms race entirely. It used no exploit, no domain generation algorithm and no peer-to-peer network. It scanned the Internet for cameras, video recorders and routers with Telnet open, and logged in with the passwords their manufacturers had shipped them with. On 1 August 2016 it started; within 20 hours it had about 64,500 devices. By late November it peaked at about 600,000.

This is Part 4 of A Short History of Botnets, and the first about devices rather than computers. It is also the closest to my own field. In embedded systems we are used to thinking about safety over a product’s lifetime; Mirai is what happens when nobody thinks about security over that lifetime.

A note on the exhibits. As before, the log and traffic exhibits are reconstructions built from published analyses, mainly the 2017 USENIX Security paper Understanding the Mirai Botnet, and each says which kind it is. The credentials shown are the kind of factory defaults the paper describes, not a working list.

How it spread: a password list, not an exploit

Every infected device became a scanner. According to the USENIX paper, each bot sent TCP SYN packets to pseudo-random IPv4 addresses on Telnet ports 23 and 2323. The scanning was stateless: the bot did not track connections, it just fired probes and waited for answers. That made it fast, and it left a fingerprint. Mirai set each probe’s TCP sequence number equal to the destination IP address, a quirk researchers used to count infected devices across the whole Internet.

When a device answered, the bot tried to log in. The source code that was later released contained 62 username and password pairs, factory defaults for cameras, video recorders and routers; each attempt tried 10 of them at random. In the wild the authors kept changing the list: honeypot data in the paper shows 48 distinct dictionaries with 371 unique passwords.

A successful login was not used straight away. The bot sent it to a separate report server, and a loader connected to the device, worked out its processor architecture, and installed the matching Mirai binary. Mirai ran on many embedded processors, so one botnet covered devices from many vendors.

Once installed, Mirai did three things that matter for defenders:

  • It hid. It deleted its own binary and disguised its process name.
  • It locked the door behind itself. It killed processes bound to TCP 22 and 23, and rival malware such as other Mirai variants, .anime and Qbot, so that no one else could take the device.
  • It did not persist. Nothing was written to survive a reboot. A restart cleaned the device, but with the default password unchanged it was soon found and infected again.

How a bot picked its targets

The released source code shows how simple the target selection was. Each bot asked its own pseudo-random number generator for a 32-bit number and split it into the four parts of an IPv4 address. Because every bot ran its own generator, the bots needed no coordination at all, yet together they covered the address space roughly evenly.

Before sending a probe, the bot checked the address against a hard-coded list and drew a new one if it matched. That list accounts for the roughly 340 million addresses the USENIX paper says Mirai never scanned. As published in Imperva’s analysis of the source code, it contained:

RangeReason
127.0.0.0/8, 0.0.0.0/8Loopback and invalid addresses
10.0.0.0/8, 172.16.0.0/14, 192.168.0.0/16Private networks
100.64.0.0/10, 169.254.0.0/16, 198.18.0.0/15, 224.0.0.0 and aboveIANA reserved, special-use and multicast
3.0.0.0/8General Electric
15.0.0.0/7Hewlett-Packard
56.0.0.0/8US Postal Service
6.0.0.0/7, 11.0.0.0/8, 21.0.0.0/8, 22.0.0.0/8, 26.0.0.0/8, 28.0.0.0/7, 30.0.0.0/8, 33.0.0.0/8, 55.0.0.0/8, 214.0.0.0/7US Department of Defense

The first groups make technical sense: those addresses are not routed on the public Internet. The rest are organisations the authors apparently wanted to avoid provoking. Imperva calls the list “fairly naïve” and notes it may have been changed before the code was released.

The port choice was equally plain. According to a line-by-line reading of the scanner code, each bot sent its probes in batches of 160 per second, and every tenth probe went to port 2323 instead of 23.

The most interesting line is the one that set the sequence number: tcph->seq = iph->daddr;. A device that answers a SYN replies with a SYN-ACK whose acknowledgement number is the original sequence number plus one. By putting the target’s address into the sequence number, the bot could recognise answers to its own probes by checking whether the acknowledgement minus one equalled the sender’s address. It needed no table of open connections, which mattered on cheap embedded devices with little memory. The same trick is what let researchers count infected devices from the outside: any SYN whose sequence number equalled its destination address came from Mirai.

Exhibit 1 (reconstruction). What an infected camera’s traffic looks like, built from the behaviour the paper documents. Addresses come from the documentation ranges; the camera’s own address is a placeholder. Note that each sequence number is just the destination IP written as a 32-bit number.

# Outbound SYN probes from an infected IP camera (10.30.8.21)
# seq = destination IPv4 address as a 32-bit integer
10.30.8.21:41022 > 198.51.100.23:23    SYN  seq=3325256727
10.30.8.21:41022 > 203.0.113.9:2323    SYN  seq=3405803785
10.30.8.21:41022 > 192.0.2.77:23       SYN  seq=3221226061
...   (thousands per minute, no ACKs, no retries)

# A target answers on 23/tcp; the bot tries factory credentials
10.30.8.21 > 198.51.100.23:23   login: root      password: ******   -> fail
10.30.8.21 > 198.51.100.23:23   login: admin     password: ******   -> fail
10.30.8.21 > 198.51.100.23:23   login: root      password: ******   -> shell

# Success is reported elsewhere; a loader does the install
10.30.8.21 > <report server>    victim=198.51.100.23:23  user=root  pass=******
<loader>   > 198.51.100.23:23   login, detect CPU architecture, push binary

Nothing in this sequence is sophisticated. That is the point. A device with an unchanged default password and Telnet open to the Internet needed no vulnerability at all.

Architecture: a division of labour

Mirai split its work into four roles, and the split explains how it grew so fast. The bots did only the cheap part, scanning and guessing. The expensive part, installing the right binary on the right processor, was done centrally by a loader that could be improved without touching a single bot.

Exhibit 2. How a new device was recruited, and how the botnet attacked.

Diagram: an infected device scans for vulnerable devices with Telnet open and a default password, sends working logins to a report server, and a loader installs the right binary; in the attack phase a C2 server sends a command to all bots, which flood the target.

Once the loader finished, the vulnerable device became an infected device and started scanning in its turn. That loop is why the botnet doubled roughly every 75 minutes in its first hours.

Compared with the earlier parts of this series, the command channel was plain. Bots reached a small number of command servers through domain names built into each build; the USENIX researchers grouped Mirai’s many operators into clusters by exactly those domains. Mirai did not need signed updates or 50,000 domains a day, because almost nobody was trying to take it over. The owners of the devices rarely knew they were infected, and the devices had no security software that could notice.

What it did: denial of service at a new scale

The earlier botnets in this series stole data. Mirai did one thing: it flooded targets with traffic until they fell over. What made it different was size, and the fact that the traffic came from hundreds of thousands of ordinary home devices instead of a few large servers.

DateTargetWhat happened
31 Oct to 13 Dec 2016Lonestar Cell, LiberiaOne Mirai cluster launched 341 attacks against the mobile operator
21 Oct 2016Dyn, DNS provider23 attack commands between 11:07 and 16:55 UTC; widely reported outages of major sites that relied on Dyn
Late Sept 2016OVH, French hosting providerA much larger attack; OVH’s CTO said the target was a Minecraft server on its network
20 to 21 Sept 2016KrebsOnSecurityAbout 620 Gbps from more than 175,000 devices; Akamai, hosting the site pro bono, eventually had to drop it

The Krebs figure comes from Brian Krebs’ own account, which notes it was almost twice the largest attack Akamai had seen; the USENIX paper measured 623 Gbps. The Dyn and Liberia details come from the paper. The Dyn attack is not attributed to Mirai’s original authors; Krebs links it to botnets built from the code after it leaked. The paper also notes that the same operators attacked PlayStation and other gaming infrastructure, which suggests Dyn may have been hit as a route to those targets.

The attack types were mostly unsophisticated. The paper’s analysis of 15,194 attack commands found three families:

  • Volumetric: UDP floods that simply fill the target’s connection.
  • TCP state exhaustion: SYN, ACK and ACK-STOMP floods that tie up firewalls and servers.
  • Application layer: HTTP and DNS floods, plus GRE and VSE floods aimed at specific services.

Only 2.8% of the commands used amplification, the trick of bouncing small requests off third-party servers to multiply their size. Mirai did not need it. It had enough devices.

The botnet’s size moved with its operators’ fortunes. It held a steady 200,000 to 300,000 devices in September 2016 and peaked at about 600,000 at the end of November, partly because one variant added an exploit for a router management protocol (CWMP). By late February 2017 it was down to about 100,000.

The leak: one botnet becomes many

On 30 September 2016, ten days after the Krebs attack, a user calling themselves “Anna-senpai” posted Mirai’s full source code on Hackforums. From that moment there was no longer one Mirai, but a toolkit anyone could build, configure and point at a target.

The effect was immediate. According to Krebs, dozens of copycat Mirai botnets appeared and competed for the same pool of vulnerable devices. The USENIX researchers could separate them only by grouping attacks and infrastructure into clusters, one per operator. Their own dataset shows how quickly the code changed in other hands: the password list grew from the original 62 pairs to 371 unique passwords across 48 dictionaries, and one variant added a router exploit that helped push the botnet to its peak.

The leak also changed the question of responsibility. With dozens of operators running the same code, a single attack could no longer be tied to a single group by its tooling. Whatever the authors intended, that ambiguity worked in their favour, at least for a while.

The pattern repeated what happened to ZeuS in 2011 (see Part 3): once source code is public, the original authors stop mattering and the code becomes a platform.

Ten years later, the platform is still in use. In March 2026 the US Justice Department announced a court-authorised disruption of four botnets, AISURU, Kimwolf, JackSkid and Mossad, that court documents describe as Mirai variants. Together they had infected at least 3 million devices, and their attacks reached about 30 terabits per second: roughly fifty times the 620 Gbps that hit KrebsOnSecurity in 2016.

The people: not who anyone expected

To my knowledge, no one has been publicly charged for the Dyn attack. Mirai’s original authors were. In January 2017 Brian Krebs, whose site Mirai had knocked offline, published the results of a four-month investigation pointing to Paras Jha and Josiah White. In December 2017 the US Justice Department announced their guilty pleas, together with a third man, Dalton Norman.

They were not a criminal syndicate or a state agency. They were 20 and 21 years old, and they had built Mirai in the summer and autumn of 2016. According to Krebs, Jha and White ran a company that sold protection against DDoS attacks, and used the botnet mainly against online gaming servers, especially Minecraft servers. The pleas covered three things:

  • Mirai. All three pleaded guilty in the District of Alaska to conspiring to violate the Computer Fraud and Abuse Act by building and operating the botnet.
  • Click fraud. Jha and Norman also admitted running a second botnet of more than 100,000 devices, mostly home routers, from December 2016 to February 2017, for advertising fraud.
  • Rutgers. Jha separately admitted DDoS attacks on Rutgers University, where he had been a student, between November 2014 and September 2016. At times they took the university’s central authentication service offline for days.

The sentences, reported by GovInfoSecurity, were unusual. In September 2018 the Alaska court gave all three five years’ probation, 2,500 hours of community service and $127,000 in restitution, with no prison time. The prosecutors explained why: the three had “provided assistance that substantially contributed to active complex cybercrime investigations”, and continued cooperation with the FBI was a condition of the sentence. For the Rutgers attacks, Jha received six months of home confinement and $8.6 million in restitution.

The authors of the most notorious IoT botnet ended up helping the FBI with other cybercrime investigations. Whether that outcome is pragmatic or too lenient is still debated; it is at least a reminder that the people behind large attacks are not always who the threat models picture.

Why there was no takedown, and what came instead

Every earlier part of this series ended with an operation: a court order, a sinkhole, a poisoned peer list. Mirai never had a defining one, and the reasons are structural.

  • The bots were not the problem. Mirai lived in memory and vanished on reboot. Cleaning a device was trivial; keeping it clean was impossible while its default password and open Telnet port remained.
  • There was no one to call. Many of Coreflood’s and GameOver Zeus’s victims were companies with IT departments. Mirai’s were cameras and video recorders bought by millions of people who had never logged into them.
  • The fix was not in the owners’ hands. Many devices had no update mechanism, and many vendors had no process to ship one.

The March 2026 operation against AISURU and its relatives shows that law enforcement can still disrupt the command servers of Mirai’s descendants. But taking out a command server does nothing to the three million devices waiting for the next operator. The lasting response to Mirai came from regulators, aimed at the manufacturers:

JurisdictionRuleStatusWhat it requires
United KingdomProduct Security and Telecommunications Infrastructure (PSTI) regimeIn force since 29 April 2024No universal default or easily guessable passwords; a published way to report vulnerabilities; a published minimum period of security updates
European UnionCyber Resilience Act, Regulation (EU) 2024/2847In force since 10 December 2024; reporting duties since 11 September 2026; full application 11 December 2027Security requirements including secure-by-default configuration and security updates over a support period, normally at least five years
United StatesU.S. Cyber Trust Mark (FCC)Voluntary; no labelled products on shelves as of late October 2026A consumer label for connected devices that meet published security criteria

Sources: UK government guidance, the Cyber Resilience Act FAQ and Nextgov’s report on the US programme, which was delayed after its first lead administrator, UL Solutions, withdrew following a national security review; the ioXt Alliance took over the role in April 2026.

The UK rule reads almost like a direct answer to Mirai’s 62-entry password list. The EU rule goes further: it turns security over a product’s lifetime into a legal duty of the manufacturer, which is exactly what the USENIX authors recommended in 2017, from randomised default passwords to automatic updates with safe rollback and better end-of-life support.

Hunting the pattern today

IoT devices rarely run endpoint security agents, so the network is where you see them. An infected camera or router behaves very differently from its normal self: instead of talking to one cloud service, it suddenly opens connections to thousands of random addresses on Telnet ports, most of which never answer. Later, when a DDoS command arrives, its outbound traffic jumps by orders of magnitude.

Exhibit 3a: Sigma correlation, Telnet scanning. One internal host contacting 100 or more distinct external addresses on TCP 23 or 2323 within five minutes, using Zeek connection logs.

title: Outbound Telnet Connection Attempt
name: outbound_telnet_attempt
status: experimental
logsource:
  product: zeek
  service: conn
detection:
  selection:
    proto: 'tcp'
    id.resp_p:
      - 23
      - 2323
    local_orig: true
    local_resp: false
  condition: selection
---
title: Possible Mirai-Style Telnet Scanning From Internal Host
id: 5e1b7c3a-9d24-4f6e-8a10-3c7d2e9b4f58
status: experimental
description: One internal host attempts Telnet connections to many distinct external hosts in a short window
correlation:
  type: value_count
  rules:
    - outbound_telnet_attempt
  group-by:
    - id.orig_h
  timespan: 5m
  condition:
    field: id.resp_h
    gte: 100
falsepositives:
  - Authorised vulnerability scanners
level: high

Exhibit 3b: Splunk, scanning and egress. Two searches over Zeek connection logs. The first finds stateless scanning: Zeek marks an unanswered SYN as connection state S0, so a host with thousands of S0 connections to Telnet ports is almost certainly scanning. The second compares each IoT host’s outbound volume with its own recent baseline, the shape of a DDoS taking part.

# 1. Stateless Telnet scanning
index=zeek sourcetype=zeek:conn local_orig=true local_resp=false
    ("id.resp_p"=23 OR "id.resp_p"=2323)
| bin _time span=5m
| stats count AS attempts
        sum(eval(if(conn_state="S0", 1, 0))) AS unanswered
        dc("id.resp_h") AS distinct_targets
        BY _time, "id.orig_h"
| eval unanswered_ratio=round(unanswered/attempts, 2)
| where distinct_targets>=100 AND unanswered_ratio>=0.9

# 2. Outbound volume far above the host's own baseline (IoT subnet)
index=zeek sourcetype=zeek:conn local_orig=true local_resp=false
    "id.orig_h"="10.30.0.0/16"
| bin _time span=5m
| stats sum(orig_bytes) AS bytes_out BY _time, "id.orig_h"
| eventstats median(bytes_out) AS baseline BY "id.orig_h"
| eval ratio=round(bytes_out/max(baseline, 1), 1)
| where ratio>=50 AND bytes_out>=100000000

Replace 10.30.0.0/16 with your IoT or OT subnet. The thresholds are starting points: tune them against a week of normal traffic before alerting on them.

Exhibit 3c: KQL (Microsoft Sentinel), firewall logs. Most IoT segments sit behind a firewall that forwards logs in CEF format, so the same scanning check works on CommonSecurityLog.

CommonSecurityLog
| where TimeGenerated > ago(1d)
| where DestinationPort in (23, 2323)
| where ipv4_is_private(SourceIP) and not(ipv4_is_private(DestinationIP))
| summarize Attempts = count(),
            DistinctTargets = dcount(DestinationIP),
            Blocked = countif(DeviceAction in~ ("deny", "drop", "block"))
            by SourceIP, bin(TimeGenerated, 5m)
| where DistinctTargets >= 100
| order by DistinctTargets desc

The preventive controls are simpler than any of these queries and matter more. Keep an inventory of every connected device; change or disable factory credentials before a device goes on the network; block Telnet at the perimeter in both directions; and give IoT segments an outbound allow-list, so a camera can reach its vendor’s cloud and nothing else. A camera that cannot reach port 23 on the Internet cannot recruit the next one.

What I take away

A default is a design decision. Mirai did not break any device. It used them exactly as they were shipped. A shared factory password and an open Telnet port are not bugs that slipped through testing; someone chose them, usually to save a step in production or support. Unique per-device credentials and closed-by-default services cost very little at design time and are almost impossible to add after a million units are in the field.

Security is a lifetime property, like safety. In functional safety we ask what a product must do over its whole service life, including after the first owner stops paying attention. Mirai shows the same question applies to security: who updates the device in year five, through which channel, and what happens at end of life. The first three parts of this series add a requirement to that channel: it must be signed, because an unsigned update channel is a command channel for whoever controls its address.

The cost landed on someone else. The owners of the cameras lost little, and their makers lost nothing. The cost fell on Krebs, OVH, Dyn’s customers and a mobile operator in Liberia. When a product’s insecurity mostly harms third parties, the market will not fix it on its own. That is the economic case for rules like PSTI and the Cyber Resilience Act.

Takedowns do not fit devices. Courts, sinkholes and poisoned peer lists worked against botnets of computers with owners who could be notified. Against hundreds of thousands of unmanaged devices, the only lasting fix is upstream, at the manufacturer, before the device ships.

Leaked code outlives its authors. Mirai’s authors stopped running the original botnet in 2016 and were sentenced in 2018. Their code was still behind 30-terabit attacks in 2026.

Mirai showed what happens when devices trust anyone with a factory password. The next part looks at Mozi, an IoT botnet that combined Mirai’s targets with the peer-to-peer design of Part 3, and that ended in 2023 with a signed kill switch whose sender is still debated.

Sources

1 thought on “Mirai: The Botnet That Needed No Exploit”

  1. Pingback: GameOver Zeus: How Defenders Broke a Peer-to-Peer Botnet - Taner Güngör

Comments are closed.