**One in Seven**
There's a line in the 1988 worm that I like more than any exploit. It isn't the one that abuses sendmail, or the one that blows the buffer in fingerd. It's a small, almost boring conditional where the program asks a machine whether it's already infected and, having heard the answer, decides to ignore it one time in seven. It copies itself anyway. That line is what turns an experiment into a disaster, and almost nobody gives it the space it deserves when they tell the story.
The reason it exists has an uncomfortable cleverness to it. Morris realized that an attentive administrator could create a fake file or process pretending the machine already carried the worm, and the worm, well-mannered, would go away. A free vaccine. To prevent that, he gave the program a statistical stubbornness, except that seven was too few for a network with thousands of connections happening every hour. On machines with lots of neighbors, copies piled up, dozens of them, each one gnawing at the CPU, and the load average climbed until the system couldn't do anything at all, including letting you log in to kill the processes. When I first read this I thought it was a bug. Today I think it was something else, a threat-modeling error. He designed against an intelligent adversary and forgot to calculate the cost of succeeding.
Hold on to that idea. I'll come back to it.
The night was Wednesday, November 2, 1988. Robert Tappan Morris was twenty-two, a graduate student at Cornell, and he launched the program from a machine at MIT, on purpose, so nobody would look toward Ithaca. The network where he released it wasn't "the Internet" in the sense we give the word today. It was a collection of university, military and research networks, with the NSFNET backbone just upgraded to T1 links, and the estimate that stuck for the number of connected machines is around sixty thousand. Of those, roughly six thousand are said to have been infected. I've always distrusted these numbers because they're so clean, exactly a tenth of a rounded total. Nobody counted anything. People did quick math from reports by sites that answered the phone, and the figure stayed and passed from article to article until it became fact. I'm not saying it's wrong, I'm saying it has the precision of an anecdote.
The program had four doors in, and each is worth looking at, because none of them is a feat of genius. The first was sendmail. On the BSD installations of the day, the mail daemon shipped with a debug mode enabled that let whoever was on the other end of the SMTP connection specify, instead of a recipient, a command to be executed. Somebody, somewhere, had left that on in the distributed configuration, probably because it was handy during development and nobody went back. A door left open for convenience. I've seen it too many times to be impressed, but in 1988 it was the one door labeled "debug" that gave remote code execution on an alarming number of machines.
The second was fingerd, and that one is prettier. The daemon read the request line with gets() into a 512-byte buffer, without checking the size of what came in. The worm sent more than fit, the overflow overwrote the return address on the stack, and execution jumped to code that came inside the request itself. This only worked on VAXes. On Sun-3s the attack didn't take, the stack was laid out differently, the program simply crashed at the door, and it was hardware diversity, by accident, that stopped part of the damage. I keep that detail with a strange fondness.
Let me take a detour that goes nowhere. gets() has been condemned forever. To this day the GCC linker spits out a warning saying the function is dangerous and shouldn't be used, and it only left the language standard in 2011, with C11. Twenty-three years after the worm. When someone tells me the industry learns fast from incidents, I think of this.
The other two doors were less technical and more social. The first was trust between machines. rsh and rexec, with their .rhosts and hosts.equiv files, let one machine accept commands from another without asking for a password, because they were "family." The worm checked which machines the host had trust relationships with and used them as a ramp. The second was pure password guessing. It carried an internal dictionary of about 432 words, also tried the username, the username reversed, obvious variations, and then swept the system dictionary at /usr/dict/words. To go fast it shipped its own implementation of crypt, quicker than the library's. And here's an irony I can't let go of, because Morris's father, also Robert, was working at the time at the NSA's computer security center, and had written with Ken Thompson, in 1979, the classic paper on Unix password security, which showed precisely that people choose predictable passwords. The son went and applied what the father had documented. I don't know whether this is a comment on heredity or on how easily security literature is read by those who want to use it and ignored by those who should apply it. Probably both, and they're not ideas that exclude each other.
The propagation mechanism was more ingenious than the short version of the story lets on. Instead of sending the full program straight away, the worm sent a small C bootstrap, about a hundred lines according to the analyses, which the target machine compiled with its own cc. Then that piece connected back to the origin and fetched the rest, with objects for VAX and for Sun, and tried until one ran. That means the worm depended on a C compiler being installed on the target, which in 1988, on university Unix machines, was nearly guaranteed, and today would be a trivial blocker, because well-kept production servers don't even have a compiler. It's one of the few hygiene rules I learned early and never dropped.
Then it hid itself with a zeal that still strikes me as unusual. It renamed its process to sh, deleted from disk the files it had just used after loading them into memory, and every so often forked and killed the parent so the accumulated CPU time wouldn't give the process away. Anyone who ran ps that night saw dozens of sh eating cycles and pretending to be normal.
A quick parenthesis on the word "worm." It comes from John Brunner's novel The Shockwave Rider, from 1975, and from the work of Shoch and Hupp at Xerox PARC, a few years before 1988, where a self-replicating program was designed to use idle machines at night. In one experiment they left it running and the next morning there were machines hung all over the lab. They wrote about it in 1982. So the outcome of a program that multiplies without a decent brake had been documented six years earlier, in a place where everybody went to read. There. This serves no purpose in the argument, it just stuck in my head.
What happened next is, for me, the most instructive part and the least told. People at Berkeley, at MIT, at Purdue, realized from the machine load that something was wrong, and then from the behavior, and spent the night taking the program apart by hand. There were people reading VAX assembly at three in the morning with cold coffee. Email, the normal coordination channel, was clogged by the worm itself, so coordination happened by phone. Many sites disconnected from the network to protect themselves, which is the right reflex. Only, disconnecting also cut the channel through which the fixes arrived. The Berkeley and MIT teams had the sendmail explanation and a fix by the early hours and by Thursday morning, but those who had isolated themselves didn't receive them. A friend of Morris's at Harvard, Andy Sudduth, sent an anonymous message to the TCP-IP list with containment instructions and an apology on the author's behalf, and the message arrived hours later than it should have, stuck in the same network that was being strangled. It's not a great moral lesson, it's just the physics of the problem. Defense and attack shared the same cable.
I've done a tiny version of this myself, to be honest. I left a debug endpoint in production, a /_dbg that returned the process's environment variables, forgotten after an afternoon of testing. It sat there eleven days. I only noticed because I saw a request in the nginx logs from an IP in Latvia I didn't recognize. Nothing happened, thanks to luck and a firewall that happened to be configured right. I rotated everything that was in there, of course, but for a few weeks I had a particular feeling I can't describe well, like having left the stove on, only retrospective.
Now the narrative that irritates me. It's usually said that cybersecurity was born in 1988 with the Morris worm. I hate the phrase "end of innocence," which shows up in every text about this, as if before it everyone went around whistling. In 1972, James Anderson's report for the US Air Force already described the underlying problem, that of shared systems where there's no way to trust the software you run. The Ware report is from 1970. Thompson gave his Turing Award lecture in 1984 on trusting trust, on how a modified compiler can plant a back door that no reading of the source code reveals. There was theory, there was awareness, there were people warning. What there wasn't was an episode with a name and a cost, one that forced someone to sign a check.
And yet, I have to contradict myself a little, because the episode did make a difference. A few weeks later, DARPA funded the creation of CERT at Carnegie Mellon, at the Software Engineering Institute, and that's a real institutional milestone, the first formal point of contact for incidents. The curious thing is what the field built first, which was a phone number. Not a tool, not a standard, not a safer language. A team that picked up the phone when something went wrong. I find this revealing and a bit depressing, and I think it's still true. Most of our security is still, under the makeup, a person awake at three in the morning with access to the right places.
It's also worth looking at the monoculture. The worm only worked on BSD, on two architectures, and hit a fraction of the network for exactly that reason, because other machines ran other systems and came out unscathed. It's an old and uncomfortable argument, that diversity protects and uniformity makes life easy for whoever attacks. Today's systems are, for very reasonable economic reasons, a monoculture of containers, base images, three or four cloud providers. I'm not saying it's wrong. I'm saying that when a flaw is found in a Java logging library, as in December 2021, the distance between discovery and panic is hours, and if that doesn't remind you of 1988 you're not paying attention.
The rsh trust relationship never died either. It changed its name. Today it's the AWS key forgotten in a .env that ended up in the repository, the long-lived token shared between services, the service account with too many permissions because adjusting permissions was work. The worm used one machine's trust relationships to jump to the next. Today's attackers use the same principle, and whenever I see a .env with credentials in an old commit I think that if Morris had a 432-word dictionary and a free afternoon, we would be the dictionary.
On intent. Morris always said he didn't want to cause damage, that he wanted to know how big the network was, and that the mistake was the replication factor. It may be true. I'm no judge and I can't look inside the head of a twenty-two-year-old from thirty-eight years ago. What I know is that "I didn't mean to break anything" is a defense I hear, with variations, from people who scrape aggressively and from people who run scanners against servers that aren't theirs, and the honest answer is that intent matters less than conduct. The federal court in Syracuse, in January 1990, came to something similar. The jury convicted him under the Computer Fraud and Abuse Act of 1986, and the legal debate turned on whether the intent the law required applied to the damage or only to the unauthorized access. The appeals court decided that intent to access was enough. The sentence was three years of probation, four hundred hours of community service and a fine of ten thousand and fifty dollars. Not much, for someone who left thousands of machines useless for days, and I think that says more about the era than about the judge.
The damage figures, by the way, are a chapter of their own. The GAO gave a range of one hundred thousand to ten million dollars. That's not an estimate, it's a shrug with an official stamp. At trial there was talk of per-site costs of two hundred and fifty-three thousand dollars, and that's where you realize nobody knew how to count. The cost of a security incident remains, thirty-odd years later, an accounting fiction that each party adjusts to suit itself.
What Morris did next is the part that usually draws a bitter smile. He co-founded Viaweb with Paul Graham, which was sold to Yahoo in 1998 for something like forty-nine million dollars in stock, later co-founded Y Combinator, and ended up a tenured professor at MIT, the same house he launched the worm from. I have nothing personal against him and I know the second-chances story is a nice one. But the world doesn't give second chances this generously to everyone who writes code that runs out of control, and whoever says otherwise is talking about class, about networks of contacts, about skin color, who knows, about things that don't fit in an article about a worm.
A few years ago I took the trouble to read Spafford's analysis, from the December 1988 Purdue technical report, and the one by Eichin and Rochlis from MIT, "With Microscope and Tweezers." I recommend both, the second more. The tone is of someone who stayed up all night and is in a hurry to tell it. There's a technical humility in there that I rarely see today in incident analyses, full of diagrams and framework acronyms, but poor in "this is what we saw and this is what we didn't understand."
So, back to the seven. I never understood why he chose seven. One in ten, one in twenty, any other value would have avoided the disaster, and the most honest explanation, and the least satisfying, is that he didn't think much about it. It was a number that seemed reasonable on a Tuesday night. The history of security is full of this, small, arbitrary decisions, made without testing, that happen to be wired into a network of sixty thousand machines. If there's one thing the worm taught me, and I don't know if it's a lesson or just the tic of someone who's been caught out before, it's to distrust numbers I can't justify. Mine too.