0% encontró este documento útil (0 votos)
17 vistas12 páginas

The Internet Worm Program

El documento analiza el gusano de Internet de 1988, que se propagó a través de vulnerabilidades en sistemas UNIX, interrumpiendo la conectividad durante días. Se detalla la estructura de datos y las rutinas del gusano, incluyendo cómo se infectaban otros hosts y se gestionaban las contraseñas. Además, se ofrecen recomendaciones para mitigar las vulnerabilidades explotadas por el gusano.

Cargado por

Santiago AF
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Temas abordados

  • gusano de Internet,
  • funciones del gusano,
  • código ineficiente,
  • ciberseguridad,
  • cifrado de contraseñas,
  • análisis de sistemas,
  • seguridad informática,
  • código fuente,
  • programación en C,
  • análisis de impacto
0% encontró este documento útil (0 votos)
17 vistas12 páginas

The Internet Worm Program

El documento analiza el gusano de Internet de 1988, que se propagó a través de vulnerabilidades en sistemas UNIX, interrumpiendo la conectividad durante días. Se detalla la estructura de datos y las rutinas del gusano, incluyendo cómo se infectaban otros hosts y se gestionaban las contraseñas. Además, se ofrecen recomendaciones para mitigar las vulnerabilidades explotadas por el gusano.

Cargado por

Santiago AF
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Temas abordados

  • gusano de Internet,
  • funciones del gusano,
  • código ineficiente,
  • ciberseguridad,
  • cifrado de contraseñas,
  • análisis de sistemas,
  • seguridad informática,
  • código fuente,
  • programación en C,
  • análisis de impacto

THE INTERNET WORM PROGRAM: AN

ANALYSIS
3.1.2. LISTA DE PUERTAS DE ENLACE
Abstract:
El gusano construyó una matriz simple de
En la tarde del 2 de noviembre de 1988, alguien infectó Internet direcciones IP de puerta de enlace mediante el
con un programa gusano. Este programa explotaba fallos en los comando `netstat` del sistema. Estas
programas de utilidad de sistemas basados en versiones de direcciones se utilizaron para infectar redes
UNIX derivadas de BSD. Los fallos permitieron al programa conectadas directamente. El uso de la lista se
infiltrarse en esas máquinas y copiarse a sí mismo, infectando describe en la explicación de `scan_gateways`
así dichos sistemas. Este programa finalmente se propagó a y `rt_init`, más adelante.
miles de máquinas e interrumpió las actividades normales y la 3.1.3. LISTA DE INTERFACES
conectividad a Internet durante muchos días. Se llenó una matriz de registros con información
sobre cada interfaz de red activa en el host
Este informe ofrece una descripción detallada de los actual. Esto incluía el nombre de la interfaz, la
componentes del programa gusano: datos y funciones. Se basa dirección de salida, la máscara de red, el host
en el estudio de dos compilaciones inversas completamente de destino si el enlace era punto a punto y los
independientes del gusano y una versión desensamblada al indicadores de la interfaz. Curiosamente,
lenguaje ensamblador VAX. El artículo prácticamente no aunque esta rutina se programó para obtener la
incluye código fuente debido a la preocupación actual sobre el dirección del host en el extremo remoto de los
estado del "sistema inmunitario" de los hosts de Internet, pero enlaces punto a punto, no parece haberse
la descripción debe ser lo suficientemente detallada como para utilizado esa información en ninguna otra parte
que el lector comprenda el comportamiento del programa. El del programa.
artículo contiene una revisión de las vulnerabilidades de 3.1.4. PWD
seguridad explotadas por el gusano y ofrece recomendaciones Se creó una lista enlazada de registros para
para eliminarlas o mitigar su uso futuro. El informe también almacenar la información del usuario. Cada
incluye un análisis del estilo de codificación y los métodos estructura contenía el nombre de la cuenta, la
utilizados por el/los autores(es) del gusano y extrae contraseña cifrada, el directorio de inicio, el
conclusiones sobre sus capacidades e intenciones. campo GECOS y un enlace al siguiente registro.
También se asignó un campo en blanco para las
3. UN RECORRIDO POR EL GUSANO
contraseñas descifradas a medida que se
A continuación, se presenta una breve descripción general de encontraban.
las rutinas presentes en el código de Worm. Esta descripción 3.1.5. OBJETOS
abarca todas las funciones importantes del programa, pero El programa mantenía una matriz de "objetos"
no describe todas las rutinas auxiliares utilizadas ni todos los que albergaba los archivos que componían el
parámetros o algoritmos involucrados. Sin embargo, debería gusano. En lugar de almacenar los archivos en
ofrecer al usuario una visión completa del funcionamiento de disco, el programa los leía en estas estructuras
Worm. internas. Cada registro de la lista contenía el
sufijo del nombre del archivo (p. ej., "sun3.o"),
3.1. ESTRUCTURA DE DATOS el tamaño del archivo y su contenido cifrado. El
El gusano tenía algunas estructuras de datos uso de esta estructura se describe a
globales que vale la pena mencionar. Además, continuación.
resulta interesante la forma en que manejaba 3.1.6. PALABRAS
algunos datos locales. El gusano contenía un minidiccionario de
3.1.1. HOST LIST palabras para la adivinación de contraseñas
El gusano construyó una lista enlazada de registros (véase el Apéndice A). Las palabras se
de host. Cada registro contenía una matriz de almacenaban en una matriz y cada una se
punteros de 12 caracteres para permitir el enmascaraba (XOR) con el patrón de bits 0x80.
almacenamiento de hasta 12 names/aliases de host. Por lo tanto, el diccionario no aparecía al
Cada registro también contenía una matriz de seis ejecutar el programa de cadenas en los
enteros largos sin signo para las direcciones de host, archivos binarios u objeto.
y cada registro contenía un campo de indicador. 3.1.7. CADENAS INCRUSTADAS
Los únicos bits de indicador utilizados en el código Todas las cadenas de texto utilizadas por el
parecen ser 0x01 (el host era una puerta de enlace), programa, excepto las palabras del
0x2 (el host ha sido infectado), 0x4 (el host no puede minidiccionario se enmascararon (XOR) con el
ser infectado — no accesible, no UMX, tipo de patrón de bits 0x81. Cada vez que se hacía
máquina incorrecto) y 0x8 (el host era "equivalente" referencia a una cadena, se hacía mediante una
en el sentido de que aparecía en un contexto como el llamada a XS. La función XS descifraba la
archivo .rhosts). cadena solicitada en un búfer circular estático y
devolvía un puntero a la versión descifrada. Esto otra manera). El programa terminó de poner a
también impedía que las cadenas de texto del cero el vector de argumentos.
programa aparecieran durante la invocación de A continuación, el código ejecutaba "if init"; si
cadenas. Simplemente borrar el bit de orden esa rutina no detectaba interfaces, el programa
superior (p. ej., XOR 0x80) o mostrar el binario ejecutaba la función "exit". El programa obtenía
del programa no produciría un texto inteligible. entonces su grupo de procesos actual. Si el
Se han omitido todas las referencias a XS del grupo de procesos coincidía con el ID de su
siguiente texto; tenga en cuenta que todas las proceso principal (transmitido en la línea de
cadenas se cifraron de esta manera. No es comandos), este restablecía su grupo de
evidente cómo se colocaron las cadenas en el procesos y enviaba una señal de desconexión
programa de esta manera. Las cadenas (KILL) a su principal.
enmascaradas estaban presentes en línea en el Por último, se invocaba la rutina doit.
código, por lo que probablemente se utilizó 3.2.2. DOIT
algún preprocesador o una versión modificada Este era el código principal del gusano. Primero,
del compilador. Esto representa un esfuerzo se establecía una variable con la hora actual
significativo por parte del autor del Gusano y mediante una llamada a time, y el generador de
sugiere fuertemente que el autor quería números aleatorios se inicializaba con el valor
complicar o prevenir el análisis del programa de retorno.
una vez que fue descubierto. A continuación, se invocaban las rutinas hg y hl
3.2. RUTINAS para infectar algunos hosts. Si una o ambas
Las descripciones que se ofrecen aquí están ordenadas fallaban en infectar algún host, se invocaba la
alfabéticamente. Los nombres de algunas rutinas son rutina ha.
exactamente los utilizados por el autor del código. A continuación, se ejecutó la rutina checkother
Otros nombres se basan en la función de la rutina, y se para comprobar si había otros gusanos en este
eligieron porque las rutinas originales se declararon host. También se ejecutó la rutina
estáticas y la información del nombre no estaba send_message para sembrar sospechas sobre
presente en los archivos de objeto. el personal de Berkeley. El código entró
Si el lector desea rastrear el flujo funcional del Gusano, entonces en un bucle infinito:
comience con la descripción de las rutinas main y doit
(presentadas primero por este motivo). Por función, las “Se realizaría una llamada a cracksome seguida
rutinas pueden agruparse (arbitrariamente) de la de una llamada a other_sleep con un parámetro
siguiente manera: de 30. Luego, se llamaría a cracksome de
nuevo. En este punto, el proceso se bifurcaría y
el padre saldría, dejando que el hijo continuara.
A continuación, se llamarían las rutinas hg, ha y
hi para infectar otros hosts. Si alguna (o
combinación) de estas rutinas no lograba
infectar un nuevo host, se llamaría a la rutina hl
3.2.1. MAIN para infectar un host local. Por lo tanto, el
Aquí fue donde comenzó el programa. Lo código era agresivo al infectar siempre al menos
primero que hizo fue cambiar su vector de un host en cada paso por este bucle. Sin
argumentos para que pareciera que era el shell embargo, la lógica aquí era defectuosa, ya que,
ejecutándose. A continuación, estableció sus si todos los hosts de puerta de enlace
límites de recursos para que un fallo no conocidos estaban infectados, o se probaba un
eliminara un archivo principal. Después, cargó conjunto incorrecto de números de host en ha,
todos los archivos nombrados en la línea de este código llamaría a hl en cada paso del
comandos en la estructura de objetos en bucle. Este comportamiento fue una de las
memoria mediante llamadas a load_object. Si el razones por las que los hosts se sobrecargaron
archivo 11.c no era uno de los objetos cargados, con procesos Worm: en cada paso por el bucle,
el gusano ejecutaba inmediatamente la función cada Worm probablemente se vería obligado a
"exit". infectar otro host local. Considerando que
A continuación, el código desvinculó todos los varios gusanos podían ejecutarse en un host
archivos de objetos, el archivo llamado sh (el durante un tiempo antes de que uno de ellos
propio gusano) y el archivo /tmp/. dumb finalizara, esto podría provocar un crecimiento
(aparentemente un remanente de alguna exponencial de gusanos en un entorno LAN.
versión anterior del programa, posiblemente A continuación, se llamó a la rutina other_sleep
usado como restricción o registro durante las con un tiempo de espera de 120. Se comprobó
pruebas; el archivo no se referencia de ninguna si el gusano se había ejecutado durante más de
12 horas. De ser así, se invocó a h_clean.
Finalmente, se comprobaron las variables archivo .rhosts, si estaba presente, en el
pleasequit y nextw (configuradas en other_sleep directorio personal del usuario.
o checkother y crack_2, respectivamente). Si
pleasequit era distinto de cero y nextw era
mayor que 10, el gusano finalizaba.” 3.2.5. CHECKOTHER
3.2.3. ATTACK_NETWORK Esta rutina verificaba si había otro gusano en
Esta rutina fue diseñada para infectar hosts esta máquina y es una rutina complementaria
aleatorios en una subred. Primero, para cada de other_sleep. Primero, se comprobaba un
una de las interfaces de red, se verificaba si el valor aleatorio: con una probabilidad de 1 en 7,
host objetivo estaba en una red a la que el host la rutina regresaba sin hacer nada; estos
actual estaba conectado directamente. De ser gusanos se volvían inmortales, en el sentido de
así, la rutina regresaba inmediatamente. que nunca volvían a participar en el proceso de
Basándose en la clase de la máscara de red (p. reducción de varios gusanos locales.
ej., Clase A, Clase B), el código construyó una De lo contrario, el gusano creaba un socket e
lista de posibles números de red. Se utilizó un intentaba conectarse al puerto local de gusanos
algoritmo especial para realizar estimaciones (23357). Si la conexión era exitosa, se realizaba
precisas de los posibles números de host de un intercambio de desafíos para verificar que el
Clase A. Todos estos números de host otro lado era realmente otro gusano. De ser así,
construidos se colocaron en una lista, y esta se se escribía un valor aleatorio en el otro lado y se
aleatorizó mediante permutación. Si la red era leía un valor del socket.
de Clase B, la permutación se realizó para Si la suma del valor enviado más el valor leído
favorecer a los hosts con números bajos era par, el gusano local establecía su variable
mediante dos permutaciones separadas: se "pleasequit" en 1, marcándolo para su eventual
garantizaba que los primeros seis hosts en la autodestrucción. El socket se cerraba entonces
lista de salida se eligieran de la primera docena y el gusano abría un nuevo socket en el mismo
de números de host (de números bajos) puerto (si no estaba destinado a autodestruirse)
generados. Las primeras 20 entradas en la lista y asignaba `other_fd` a ese socket para que
permutada fueron las únicas examinadas. Para escuchara otros gusanos. Si se encontraba
cada dirección IP, su entrada se recuperó de la algún error durante este procedimiento, el
lista global de hosts (si estaba en la lista). Si el gusano implicado asignaba `other_fd` a -1 y
host estaba en la lista y estaba marcado como regresaba de la rutina. Esto significaba que
ya infectado o inmune, se ignoraba. De lo cualquier error también hacía que el gusano se
contrario, se verificaba si el host admitía el volviera inmortal.
comando rsh (identificándolo como existente y 3.2.6. CRACK_0
con servicios de red derivados de BSD) Esta rutina primero analizó el archivo
llamando a "supports_rsh". Si el host admitía /etc/[Link], añadiendo nuevos hosts a la
rsh, se introducía en la lista de hosts si aún no lista global de hosts y configurando el campo
estaba presente y se realizaba una llamada a "flags" para marcarlos como equivalentes. Se
"infect" para ese host. Si la infección se realizaron llamadas a name2host y getaddrs. A
realizaba correctamente, la rutina regresaba continuación, se realizó un análisis similar del
antes con un valor de TRUE (1). archivo /.rhosts utilizando exactamente las
3.2.4. ATTACK USER mismas llamadas.
Esta rutina se llamó después de que se El código entonces llamó a setpwent para abrir
descifrara la contraseña de un usuario. el archivo /etc/passwd. Se ejecutó un bucle
Contiene código incorrecto y podría no mientras se pudieran leer las contraseñas:
funcionar correctamente en todas las Cada décima entrada, se realizó una llamada a
arquitecturas debido a que a una subrutina le other_sleep con un tiempo de espera de 0. Para
faltaba un argumento. Sin embargo, en Suns y cada usuario, se intentó abrir el archivo
VAxen, el código funcionará porque el .forward. En el directorio de inicio de ese
argumento faltante se proporcionó como usuario y leer los nombres de host que
argumento adicional a la llamada anterior, y el contenía. Estos nombres de host también se
orden de los argumentos en la pila coincide agregaron a la lista de hosts y se marcaron
entre las dos rutinas. Fue en gran medida una como equivalentes. La contraseña cifrada, el
coincidencia que esto funcionara. La rutina directorio de inicio y el campo GECOS de cada
intentó abrir un archivo de reenvío en el usuario se almacenaron en la estructura pwd.
directorio personal del usuario y, para cada host Después de leer todas las entradas del usuario,
y nombre de usuario presente en ese archivo, se invocó la rutina endpwent y la variable
llamó a la rutina hul. Luego hizo lo mismo con el cmode se estableció en 1.
3.2.7. CRACK_1
Esta rutina intentó descifrar contraseñas. Su cada cuenta. Si la primera letra de la palabra
objetivo era realizar un bucle hasta que se era mayúscula, se convertía a minúscula y se
hubieran probado todas las cuentas o hasta reintentaba. Tras probar todas las palabras, se
que se hubiera probado el siguiente grupo de 50 incrementaba la variable cmode y la rutina
cuentas. En el bucle: regresaba. En esta rutina, no se intercalaban
Se realizó una llamada a other_sleep con un llamadas a otros "sleep", lo que provocaba que
parámetro de cero cada vez que el índice del los procesos se ejecutaran durante un tiempo
bucle módulo 10 fuera cero (es decir, cada 10 prolongado antes de buscar otros gusanos en la
llamadas). Se realizaron repetidas llamadas a máquina local. Cabe destacar que esta rutina
try_password con los valores mencionados tampoco probaba la operación inversa de las
anteriormente en §4-8b. palabras.
Una vez probadas todas las cuentas, la variable 3.2.10. CRACKSOME
cmode se estableció en 2. Esta rutina consistía en una simple sentencia
El código de esta rutina presentaba un fallo, ya switch sobre una variable externa llamada
que el índice del bucle nunca se incrementó. cmode e implementaba las cinco estrategias
Por lo tanto, la comprobación cada 50 cuentas y descritas en los §4-8 de este documento. El
la llamada a other_sleep cada 10 cuentas no se estado cero se llamaba crack_0, el estado uno
producían. Una vez introducido, crack_1 se se llamaba crack_1, el estado dos se llamaba
ejecutaba hasta que se habían comprobado crack_2 y el estado tres se llamaba crack_3. El
todas las cuentas de usuario. caso predeterminado simplemente devolvía.
3.2.8. CRACK_2 3.2.11. CRYPT
Esta rutina utilizó el minidiccionario para Esta rutina tomaba una clave y una sal, y luego
intentar descifrar las contraseñas de los ejecutaba la función de cifrado de contraseña
usuarios (véase el Apéndice A). El diccionario se UMIX en un bloque de cero bits. El valor de
permutó primero (mediante la llamada retorno de la rutina era un puntero a una cadena
permute). Cada palabra se descifró in situ de 1 a 3 caracteres que representaba la
mediante la operación XOR de sus bytes con contraseña codificada.
0x80. Las palabras descifradas se pasaron a la La rutina estaba altamente optimizada y difiere
rutina try_password para cada cuenta de considerablemente de la versión de la
usuario. El diccionario se volvió a cifrar. Se biblioteca estándar de la misma rutina.
incrementó un índice global, llamado nextw, Llamaba a las siguientes rutinas: compkeys,
para apuntar a la siguiente entrada del mungE, des y ipi. Una rutina, setupE, también
diccionario. El índice nextw también se utiliza estaba presente y estaba asociada a este
en doit para determinar si se ha realizado el código, pero nunca se hizo referencia a ella.
esfuerzo suficiente para que el gusano pueda Parece duplicar la funcionalidad de la función
"...entrar tranquilamente en esa buena noche". mungE.
Cuando no quedaban más palabras, la variable 3.2.12. h_addaddr
cmode se estableció en 3. Esta rutina agregó direcciones alternativas a
Hay dos puntos interesantes a destacar en esta una entrada de host en la lista global si aún no
rutina: no se intentó el reverso de estas estaban presentes.
palabras, aunque parecería lógico, y todas las 3.2.13. h_addname
palabras se cifraron y descifraron in situ, en Esta rutina agregó alias de host (nombres) a una
lugar de en un búfer temporal. Esto es menos entrada de host dada. Se eliminaron las
eficiente que una copia con enmascaramiento, entradas duplicadas.
ya que no es necesario volver a cifrar. Como se 3.2.14. h_add2host
explica en la siguiente sección, el programa La dirección de host proporcionada a la rutina
presentaba muchos ejemplos de esfuerzos se comparó con cada entrada de la lista global
innecesarios como este. Además, el de hosts para comprobar si ya existía. De ser
minidiccionario completo se descifró de una así, se devolvía un puntero a esa entrada. De no
sola vez, en lugar de palabra por palabra. Esto ser así, y si se había establecido un indicador de
parecería reducir el beneficio de cifrar esas parámetro, se inicializaba una nueva entrada
palabras, ya que el diccionario completo estaría con el argumento "dirección" y se devolvía un
presente en la memoria como texto plano puntero a ella.
durante el proceso de descifrado de todas las 3.2.15. h_clean
palabras. Esta rutina recorrió la lista de hosts y eliminó
3.2.9. CRACK_3 todas las entradas marcadas como infectadas o
Esta fue la última rutina de descifrado de inmunes (dejando hosts que aún no se habían
contraseñas. Abría /usr/dict/words y, por cada probado).
palabra encontrada, ejecutaba try_password en 3.2.16. h_name2host
Igual que h_addr2host excepto que la 3.2.22. if_init
comparación se realizó por nombre con todos Esta rutina construyó la lista de interfaces
los alias. mediante llamadas ioctl. En resumen, obtuvo
3.2.17. Ha información sobre cada interfaz activa,
Esta rutina intentó infectar hosts en redes incluyendo la dirección de destino en enlaces
remotas. Primero, comprobaba si la lista de punto a punto y su máscara de red. Inicializó el
puertas de enlace contenía entradas; de no ser puntero "me" a la primera dirección no
así, ejecutaba rt init. A continuación, generaba loopback encontrada e ingresó todas las
una lista de todas las direcciones IP de los direcciones alternativas en la lista de
hosts de puerta de enlace que respondían a la direcciones.
rutina try_telnet. La lista de direcciones de host 3.2.23. infect
se aleatorizaba mediante permutación. A Esta era la rutina principal de infección.
continuación, cada dirección de la lista así Primero, se verificaba el argumento del host
construida se enmascaraba con el valor para asegurarse de que no fuera el host actual,
devuelto por netmaskfor y el resultado se que no estuviera infectado y que no se hubiera
pasaba a la rutina attack_network. Si un ataque determinado su inmunidad. A continuación, se
tenía éxito, la rutina finalizaba prematuramente verificaba que se pudiera encontrar una
con un valor de retorno TRUE. dirección para el host llamando a getaddrs. Si
3.2.18. hg no se encontraba ninguna dirección, el host se
Esta rutina intentó infectar las puertas de marcaba como inmune y la rutina devolvía
enlace. Primero llamó a rt_init para reinicializar FALSE.
la lista de puertas de enlace y, luego, para cada A continuación, la rutina llamaba a other_sleep
puerta de enlace, llamó a la rutina de infección con un tiempo de espera de 1. A continuación,
principal, infect, con la puerta de enlace como intentaba, sucesivamente, llamadas a try_rsh,
argumento. En cuanto una puerta de enlace se try_fingerd y try_sendmail. Si las llamadas a
infectó con éxito, la rutina devolvió TRUE. try_rsh o try_fingerd tenían éxito, los
3.2.19. hi descriptores de archivo establecidos por esas
Esta rutina intentó infectar hosts cuyas invocaciones se pasaban como argumentos a la
entradas en la lista de hosts estaban marcadas llamada a sendWorm. Si alguno de los tres
como equivalentes. La rutina recorrió la lista intentos de infección tenía éxito, infect
global de hosts en busca de dichas entradas y regresaba pronto con un valor de TRUE. En caso
luego ejecutó la función "infect" con esos hosts. contrario, la rutina devolvía FALSE.
Una infección exitosa regresó pronto con el 3.2.24. load_object
valor TRUE. Esta rutina leyó un archivo de objeto en la
3.2.20. hl estructura de objetos en memoria. El archivo se
Esta rutina estaba diseñada para atacar hosts abrió y se determinó su tamaño mediante una
en redes conectadas directamente. Para cada llamada a la rutina de biblioteca fstat. Se asignó
dirección alternativa del host actual, se llamaba un búfer del tamaño adecuado y se realizó una
a la rutina attack_network con un argumento llamada a read para leer el contenido del
consistente en la dirección enlazada archivo. El búfer se cifró mediante una llamada
lógicamente con el valor de la máscara de red a xorbuf y luego se transfirió al array de objetos.
correspondiente. Un éxito provocaba que la El sufijo del nombre (p. ej., sun3.o, ll.c, vax
rutina retornara antes de tiempo con un valor de . o) se guardó en un campo de la estructura, al
retorno TRUE. igual que el tamaño del objeto.
3.2.21. hul 3.2.25. makemagic
Esta función intentó atacar un host remoto La rutina usó la llamada aleatoria de la
mediante un usuario específico. Primero, biblioteca para generar un número aleatorio que
comprobó que el host no fuera el actual ni que se usaría como número de desafío. A
estuviera marcado como infectado. A continuación, intentó conectarse al puerto
continuación, invocó `getaddrs` para Telnet (#23) del host de destino, utilizando cada
comprobar si existía una dirección válida. dirección alternativa conocida para ese host. Si
Examinó el nombre de usuario en busca de se establecía una conexión exitosa, se
signos de puntuación y, si los encontraba, ejecutaba la llamada de la biblioteca
devolvió la información. A continuación, invocó getsockname para obtener la dirección IP
`other_sleep` con el argumento `1`. A canónica del host actual en relación con el
continuación, el código intentó los ataques destino.
descritos en §4-10. Se realizaron llamadas a A continuación, se realizaron hasta 1024
`sendWorm` si alguno de los ataques lograba intentos para establecer un socket TCP,
establecer un shell en la máquina remota. utilizando los números de puerto generados al
tomar la salida del generador de números popen. El código se repitió mientras se recibía
aleatorios módulo 32767. Si la conexión era la salida del comando netstat:
exitosa, la rutina devolvía el número de puerto, Se leyó una línea. Se realizó una llamada a
el descriptor de archivo del socket, la dirección other_sleep con un tiempo de espera de cero.
IP canónica del host actual y el número de La línea de entrada se analizó en un destino y
desafío. una puerta de enlace. Si la puerta de enlace no
3.2.26. netmaskfor era una dirección IP válida, o si era la dirección
Esta rutina recorría la matriz de interfaces y de bucle invertido ([Link]), se descartaba. El
verificaba la dirección dada con dichas valor se comparó con todas las direcciones de
interfaces. Si se detectaba que la dirección era puerta de enlace ya conocidas; se omitieron los
accesible a través de una interfaz conectada, la duplicados. También se comparó con la lista de
máscara de red devuelta era la máscara de red interfaces locales (redes locales) y se descartó
asociada a esa interfaz. De lo contrario, se si era un duplicado. De lo contrario, se agregó a
devolvía la máscara de red predeterminada la lista de puertas de enlace y se incrementó el
según el tipo de red (Clase A, Clase B, Clase C). contador.
3.2.27. other_sleep 3.2.30. SCAN_GATEWAYS
Esta rutina verificaba una variable global Primero, el código llamó a permute para
llamada other_fd. Si la variable era menor que aleatorizar la lista de puertas de enlace. A
cero, la rutina simplemente llamaba a sleep con continuación, recorrió cada puerta de enlace o
el argumento timeout proporcionado y luego las primeras 20, lo que fuera menor:
devolvía. De lo contrario, la rutina esperaba una Se realizó una llamada a other_sleep con un
llamada al sistema select hasta el valor de tiempo de espera de cero. Se buscó la dirección
timeout. Si el timeout expiraba, la rutina IP de la puerta de enlace en la lista de hosts; se
regresaba. De lo contrario, si el código de le asignó una nueva entrada si no existía
retorno de select indicaba que había una ninguna. El indicador de puerta de enlace se
entrada pendiente en el descriptor other_fd, estableció en el campo "flags" de la entrada de
significaba que había otro Worm en la máquina host. Se realizó una llamada a la rutina de
actual. Se establecía una conexión y se biblioteca gethostbyaddr con el número IP de la
realizaba un intercambio de números "mágicos" puerta de enlace. Los campos de nombre, alias
para verificar la identidad. El Worm local y dirección se agregaron a la lista de hosts, si no
entonces escribía un número aleatorio estaban ya presentes. Luego, se realizó una
(producido por random) al otro Worm a través llamada a gethostbyname y se agregaron
del socket. Se leía la respuesta y se verificaba direcciones alternativas a la lista de hosts. Tras
que provenía del host local ([Link]). El ejecutar este bucle, se inició un segundo bucle
descriptor de archivo se cerraba. Si el valor que hizo prácticamente lo mismo que el
aleatorio enviado más la respuesta era un primero. No hay una razón clara para esto, a
número impar, la variable other_fd se establecía menos que se trate de un remanente de código
en -1 y la variable pleasequit en 1. Esto anterior o un fragmento para futuras adiciones.
significaba que el gusano local moriría cuando 3.2.31. SEND_MESSAGE
las condiciones fueran propicias (cf. doit) y que Esta rutina realizó una llamada a un método
ya no intentaría contactar con otros gusanos en aleatorio y 14 de 15 veces regresó sin hacer
la máquina local. Si la suma era par, el otro nada. En el decimoquinto caso, abrió un socket
gusano estaba destinado a morir. de flujo al host "[Link]" y luego
3.2.28. PERMUTE intentó enviar un byte no inicializado mediante
Esta rutina aleatorizó el orden de una lista de la llamada "sendto". Esto no funcionó (al usar
objetos. Esto se logró ejecutando un bucle una un envío UDP en un socket TCP).
vez por cada elemento de la lista. En cada 3.2.32. sendWorm
iteración del bucle, se llamó al generador de Esta rutina envió el código Worm a través de un
números aleatorios módulo el número de circuito TCP conectado a una máquina remota.
elementos de la lista. El elemento de la lista Primero, verificó que la tabla de objetos
indexado por ese valor se intercambió con el contenía una copia del código 11.c (véase el
elemento de la lista indexado por el valor actual Apéndice B). A continuación, llamó a
del bucle (mediante una llamada a bcopy). makemagic para establecer un socket local y
3.2.29. RT_INIT generar una cadena de desafío. Después,
Esto inicializó la lista de puertas de enlace. codificó y escribió el script detallado
Comenzó poniendo a cero un contador externo, previamente en §4-2a. Finalmente, llamó a
ngateways. A continuación, invocó el comando waithit y devolvió el código resultante de esa
"/usr/ucb/netstat -r -n" mediante una llamada rutina.
Los archivos de objeto enviados a través del Esta rutina intentó establecer una conexión con
enlace se descifraron en memoria primero el puerto SMTP (#25) del host remoto. Si tenía
mediante una llamada a xorbuf y luego se éxito, ejecutaba el diálogo explicado en §4-2b.
volvieron a cifrar. Luego, llamaba a la rutina waithit para
comprobar si la infección se había producido.
3.2.33. supports_rsh Se comprobaban los códigos de retorno tras la
Esta rutina determinaba si el host de destino, transmisión de cada línea y, si un código de
especificado como argumento, era compatible retorno indicaba un problema, la rutina se
con el protocolo rsh derivado de BSD. Para ello, cancelaba tras enviar un mensaje de "salir".
creaba un socket e intentaba una conexión TCP 3.2.39. Waithit
al puerto 514 de la máquina remota. Un tiempo Esta función actuaba como servidor de
de espera o un fallo de conexión generaban un arranque para un programa vector en una
valor de retorno FALSO; de lo contrario, el máquina remota. Esperaba hasta 120 segundos
socket se cerraba y el valor de retorno era en el socket creado por la rutina makemagic y,
VERDADERO. si no se establecía conexión, cerraba el socket y
3.2.34. supports_telnet devolvía un código de error. De igual forma, si lo
Esta rutina determinaba si un host era accesible primero que se recibía no era la cadena de
y admitía el protocolo Telnet (es decir, desafío incluida con el programa de arranque,
probablemente no era un enrutador ni una se cerraba el socket y la rutina regresaba.
máquina similar). Era similar a la de La rutina descifraba cada archivo objeto
"supports_rsh". El código establecía un socket, mediante xorbuf y lo enviaba a través de la
se conectaba a la máquina remota en el puerto conexión al programa vector (véase el Apéndice
23 y devolvía "FALSO" si se producía un error o B). A continuación, se transmitía un script para
se agotaba el tiempo de espera; de lo contrario, compilar y ejecutar el vector.
el socket se cerraba y se devolvía Esto se describió en §4-4. Si el host remoto se
"VERDADERO". infectaba correctamente, se activaba el
3.2.35. try_fingerd indicador de infección en la entrada del host y
Esta rutina intentó establecer una conexión con se cerraba el socket. De lo contrario, la rutina
un demonio finger remoto en el host indicado enviaba cadenas de comandos rm para eliminar
mediante el puerto 79. Si la conexión era cada archivo objeto. La función devolvía el éxito
exitosa, enviaba un búfer sobrecargado, como o el fracaso de la infección.
se describe en §4-8b, y esperaba a ver si el otro 3.2.40. Xorbuf
lado se convertía en un shell. De ser así, Esta rutina era algo peculiar. Realizaba una
devolvía los descriptores de archivo al función simple de cifrado/descifrado mediante
invocador; de lo contrario, cerraba el socket y la operación XOR del búfer pasado como
devolvía un código de error. argumento con los primeros 10 bytes de la
3.2.36. try_password propia rutina xorbuf.
Esta rutina invocó crypt con el intento de Este código no funcionaría en una máquina con
contraseña y comparó el resultado con la un espacio I/D dividido ni en arquitecturas
contraseña cifrada en la entrada pwd del etiquetadas.
usuario actual. Si se encontraba una
coincidencia, la contraseña sin cifrar se 4. ANALISIS DE CÓDIGO
copiaba en la estructura pwd y se invocaba la 4.1. ESTRUCTURA Y ESTILO
rutina attack_user. Un examen del código de ingeniería inversa del
3.2.37. try_rsh Gusano resulta instructivo. Aunque no es lo mismo
Esta función creó dos tuberías y bifurcó un que leer el código original, revela algunas
proceso hijo. El proceso hijo intentó ejecutar un características del autor o autores. Una conclusión
shell remoto en el host especificado en los que puede sorprender a algunos es que la calidad del
parámetros, utilizando el nombre de usuario y la código es mediocre, e incluso podría considerarse
contraseña especificados. A continuación, deficiente. Por ejemplo, hay lugares donde se
intentó invocar el comando rsh ejecutando, en realizan llamadas a funciones con demasiados o
orden, "/usr/ucb/rsh", "/usr/bin/rsh" y muy pocos argumentos. Muchas rutinas tienen
"/bin/rsh". Si la ejecución del shell remoto era variables locales que nunca se utilizan o que
correcta, la función devolvía los descriptores de potencialmente se utilizan antes de inicializarse. En
archivo de la tubería abierta. De lo contrario, al menos un lugar, se pasa una estructura como
cerraba todos los descriptores de archivo, argumento en lugar de su dirección. También hay
eliminaba al proceso hijo con un SIGKILL y lo código inactivo, como rutinas a las que nunca se
despachaba con una llamada a wait3. hace referencia y código que no se puede ejecutar
3.2.38. try_sendmail debido a condiciones que nunca se cumplen
(posiblemente errores). Parece que el/los autor(es) estándar de Berkeley. Se realizaron muchas
nunca usaron la utilidad lint en el programa. En modificaciones interesantes al algoritmo, y las
muchas partes del código, se invocan rutinas del rutinas no parecen haber sido escritas por el mismo
sistema y nunca se verifica el éxito de los códigos de autor que el resto del código. Además, las rutinas
retorno. En muchos lugares, se invoca la rutina del involucradas tienen cierta compatibilidad tanto con
montón del sistema, malloc, y el resultado se usa el cifrado como con el descifrado, aunque solo se
inmediatamente sin ninguna comprobación. Aunque necesitaba el cifrado para el gusano. Esto respalda la
el programa se configuró para no dejar un archivo de suposición de que esta rutina fue escrita por alguien
núcleo ni otra evidencia en caso de un fallo fatal, la distinto al autor del programa y que se incluyó en
falta de comprobaciones simples en los códigos de este código. Sería interesante descubrir dónde se
retorno indica descuido; también sugiere que el originó este código y cómo llegó al programa Worm.
código se escribió y ejecutó con pruebas mínimas o El programa podría haber sido mucho más virulento
nulas. Es posible que algunas comprobaciones se si el autor hubiera tenido más experiencia o hubiera
hayan escrito en el código y se hayan omitido sujetas codificado con menos prisa. Sin embargo, parece
a indicadores de compilación condicionales. Sin probable que este código se haya desarrollado
embargo, habría pocas razones para eliminar dichas durante un largo período de tiempo, por lo que la
comprobaciones de la versión de producción del única conclusión posible es que el autor fue
código. descuidado (o ambos), y quizás que el lanzamiento
Las estructuras elegidas para algunos de los datos del Worm fue prematuro.
internos también son reveladoras. Todo se 4.2. PROBLEMAS DE FUNCIONALIDAD
representó como listas enlazadas de estructuras. Es indiscutible que el programa era funcional. De
Todas las búsquedas se realizaron como pasadas hecho, ¡todos desearíamos que hubiera sido menos
lineales a través de la lista correspondiente. Algunas capaz! Sin embargo, tenemos suerte, ya que el
de estas listas podían ser bastante largas, y sin duda programa tenía fallos que le impedían funcionar a
el gusano invertía un tiempo considerable de CPU pleno rendimiento. Por ejemplo, debido a un error, el
simplemente en mantenerlas y buscarlas. Un poco código no podía infectar hosts en una red de área
de código adicional para implementar contenedores local, aunque pudiera identificarlos.
hash o algún tipo de listas ordenadas habría Otro ejemplo de funcionalidad restringida se refiere a
reducido la sobrecarga del programa, haciéndolo la recopilación de nombres de host para infectar.
mucho más eficiente (y, por lo tanto, más rápido para Como ya se mencionó, el código no pudo recopilar
infectar otros hosts y menos obvio para los nombres de host de los archivos .rhosts del usuario
observadores del sistema). Las listas lineales al principio. Tampoco intentó recopilar nombres de
pueden ser fáciles de codificar, pero cualquier host de otros archivos de usuario y del sistema que
programador experimentado o estudiante avanzado contuvieran dichos nombres (por ejemplo,
de informática debería ser capaz de implementar /etc/[Link]).
una tabla hash o listas de contenedores hash sin Muchas de las operaciones podrían haberse
dificultad. realizado de forma ‘más inteligente’. El caso del uso
En algunos puntos se duplicó el esfuerzo. Un de estructuras lineales ya se ha mencionado. Otro
ejemplo de esto fue el código que intentaba descifrar ejemplo habría sido ordenar las contraseñas de
contraseñas. Incluso si la contraseña de una cuenta usuario por la sal utilizada. Si la misma sal estaba
se hubiera encontrado en una etapa anterior de la presente en más de una contraseña, todas esas
ejecución, el gusano cifraba cada palabra del contraseñas podían comprobarse en paralelo con un
diccionario e intentaba encontrar una coincidencia. solo paso por los diccionarios. En nuestra máquina,
Se puede encontrar una redundancia similar en el por ejemplo, el 5% de las 200 contraseñas
código para construir las listas de hosts a infectar. comparten las mismas sales.
Hay puntos en el código donde parece que el/los No se obtuvo ninguna ventaja si la contraseña de
autor(es) pretendían ejecutar una función específica, root se vio comprometida. Una vez que se ha
pero usaron la invocación incorrecta. El uso del envío descifrado la contraseña de root, es posible bifurcar
UDP en un socket TCP es un ejemplo claro. Otro procesos secundarios que configuren sus uid y
ejemplo se encuentra al principio del programa, variables de entorno para que coincidan con cada
donde el código envía una señal KILL a su proceso usuario designado. Estos procesos podrían entonces
padre. El código circundante da una clara indicación intentar el ataque rsh descrito anteriormente en este
de que el usuario en realidad pretendía ejecutar una informe. En su lugar, root se trata como cualquier
killpg, pero usó la llamada incorrecta. otra cuenta.
La única sección del código que parece Se me ha sugerido que este tratamiento de root pudo
particularmente bien pensada se refiere a las rutinas haber sido una decisión consciente del autor o
de cifrado utilizadas para verificar contraseñas. autores del gusano. Sin conocer la verdadera
Como se ha señalado en [Secl88], este código es motivación del autor, es imposible determinarlo. Sin
nueve veces más rápido que la función de cifrado embargo, considerando el diseño y la intención del
programa, me resulta difícil creer que tal explotación Algunos de los algoritmos utilizados por el gusano
se hubiera omitido si el autor lo hubiera pensado. eran bastante ingeniosos. Uno en particular es
El mismo ataque utilizado contra el demonio finger interesante: al probar contraseñas de la lista
podría haberse extendido a la versión Sun del integrada, o al intentar acceder a los hosts
programa, pero no se hizo. Las únicas explicaciones conectados, el gusano aleatorizaba la lista de
que se me ocurren son que el autor carecía de la candidatos para la prueba. Por lo tanto, si había más
motivación, la capacidad, el tiempo o los recursos de un gusano presente en la máquina local, era más
para desarrollar una versión para Sun. Sin embargo, probable que probaran los candidatos en un orden
en una reunión reciente, se escuchó al profesor Rick diferente, maximizando así su cobertura. Esto
Rashid, de la Universidad Carnegie-Mellon, afirmar implica, sin embargo (al igual que la acción de la
que Robert T. Morris, el supuesto autor del gusano, variable pleasequit) que el/los autores(es) no
había revelado el error fingerd al personal estaba(n) demasiado preocupado(s) por la presencia
administrativo de sistemas de la CMU hace más de de múltiples gusanos en la misma máquina. Más
un año. Suponiendo que este informe sea correcto y concretamente, se permitieron varios gusanos
que el autor del gusano sea el Sr. Morris, es obvio durante un tiempo para maximizar la propagación de
que hubo tiempo suficiente para construir una la infección. Esto también respalda la afirmación de
versión Sun del código. Pedí a tres estudiantes de que el autor no comprendía los efectos de
posgrado de Purdue (Shawn D. Ostermann, Steve J. propagación o carga del gusano.
Chapin y Jim N. Griffioen) que desarrollaran una El diseño del programa vector, el protocolo de
versión Sun 3 del ataque, y lo hicieron en menos de "adelgazamiento" y el uso de la máquina de estados
tres horas. El autor del gusano ciertamente debió interna fueron ingeniosos y no obvios. La estructura
tener acceso a Suns; de lo contrario, no habría general del programa, especialmente el código
podido proporcionar los binarios de Sun para asociado a las direcciones IP, indica un
acompañar al gusano operativo. La motivación conocimiento considerable de redes y las rutinas
tampoco debería ser un factor, considerando todo lo disponibles para respaldarlas. El conocimiento
demás presente en el programa. Con el tiempo y los evidenciado por ese código indicaría una amplia
recursos disponibles, la única razón que no puedo experiencia con recursos de red. Esto, sumado a
descartar de inmediato es que no sabía cómo algunos errores en el código del gusano relacionados
implementar una versión del ataque para Suns. Esto con redes, respalda aún más la tesis de que el autor
parece improbable, pero dada la naturaleza no era un programador cuidadoso; los errores en
inconsistente del resto del código, sin duda es una esas partes del código probablemente no se
posibilidad. Sin embargo, de ser así, surge una nueva debieron a ignorancia o inexperiencia.
pregunta: ¿fue el autor del gusano el autor original 4.3. CAMUFLAJE
del ataque VAX fingerd? Se tuvo mucho cuidado para evitar que el programa
Quizás la deficiencia más obvia del código sea la Worm se detuviera. Esto se evidencia en la cautela
falta de comprensión de la propagación y la carga. La con la que se introducían nuevos archivos en la
razón por la que el gusano se detectó tan máquina, incluyendo el uso de desafíos aleatorios.
rápidamente y causó tanta interrupción fue porque Esto se evidencia en el hecho de que cada cadena
se replicaba exponencialmente en algunas redes y compilada en el Worm estaba cifrada para evitar un
porque cada gusano carecía de historial. Es cierto examen simple. Esto se evidenció en el cuidado con
que se había implementado una comprobación para el que los archivos asociados con el Worm se
ver si la máquina actual ya estaba infectada, pero eliminaron del disco lo antes posible, y el contenido
uno de cada siete gusanos nunca moriría, incluso si correspondiente se cifró en memoria al cargarlo.
hubiera una infestación existente. Además, los Esto se evidenció en la bifurcación continua del
gusanos marcados para autodestrucción proceso y la comprobación (errónea) de otras
continuaban ejecutándose hasta haber realizado al instancias del Worm en el host local.
menos una pasada completa por el archivo de El código también muestra precauciones contra
contraseñas. El/Los autores(es) podría(n) haber proporcionar copias de sí mismo a cualquiera que
adoptado diversas estrategias para ralentizar el intente detener el Worm. Establece sus límites de
crecimiento del gusano o prevenir la reinfestación; recursos para no poder volcar un archivo del núcleo y
no se puede obtener mucho de explicarlas aquí, pero mantiene los datos internos cifrados hasta su uso.
su ausencia en el programa del gusano es Afortunadamente, existen otros métodos para
reveladora. O bien el/los autores(es) desconocía(n) obtener archivos del núcleo e imágenes de datos, y
cómo se propagaría el programa, o bien no le los investigadores pudieron obtener toda la
importaba; la existencia en el gusano de información necesaria para desensamblar y aplicar
mecanismos para limitar el crecimiento tiende a ingeniería inversa al código. No cabe duda, sin
indicar que se trataba de falta de comprensión, más embargo, de que el autor o los autores de El Gusano
que de indiferencia. pretendían hacer que esa tarea fuera lo más difícil
posible.
4.4. COMENTARIOS ESPECÍFICOS conocidas eran de un tipo que el gusano no
Vale la pena hacer algunos comentarios más podía infectar.
específicos. Estos se centran en aspectos Dado que el autor del programa sabía cómo
específicos del código, más que en el programa en acceder a cualquier máquina UNIX, resulta
su conjunto. extraño que no intentara compilarlo en
4.4.1. THE SENDMAIL ATTACK arquitecturas externas para incluirlo con el
Muchos sitios web tienden a experimentar gusano.
cargas considerables debido al intenso tráfico 4.4.3. PORTABILITY CONSIDERATIONS
de correo. Esto es especialmente cierto en Es posible que el autor o los autores del gusano
sitios con explotadores de listas de correo. Por no tuvieran mucha experiencia escribiendo
lo tanto, los administradores de estos sitios han código UNIX portátil, incluyendo scripts de
configurado sus servidores de correo para shell. Considere que en el script de shell
poner en cola el correo entrante y procesarlo utilizado para compilar el vector, se utiliza el
periódicamente. La configuración habitual siguiente comando:
consiste en configurar sendmail para que if [ -f sh [
ejecute la cola cada 30 a 90 minutos. El ataque El uso del carácter [ como sinónimo de la
mediante sendmail fallaría en estas máquinas a función de prueba no es universal. Los usuarios
menos que el programa vector se entregara a de UNIX con experiencia en la creación de
una cola casi vacía en los 120 segundos archivos de shell portables tienden a escribir el
siguientes a su procesamiento. Esto se debe a operador "test" en lugar de confiar en la
que el gusano infectado solo esperaría en el existencia de un enlace a un archivo llamado "["
socket del servidor dos minutos después de en cualquier sistema. También saben que el
entregar el correo infectado. Por lo tanto, en operador "test" está integrado en muchos shells
sistemas con colas retrasadas, el proceso y, por lo tanto, es más rápido que la variante
vector no se compilaría a tiempo para transferir externa [, aunque la mayoría de los shells ahora
el programa gusano principal al objetivo. El también incorporan el alias [ como función).
proceso vector fallaría en su intento de La invocación de prueba utilizada en el código
conexión y finalizaría con un estado distinto de de Worm también utiliza el indicador -f para
cero. Además, el ataque a través de sendmail comprobar la presencia del archivo llamado sh.
invocaba el programa vector sin una ruta Esto nos proporcionó el "condón" de Worm
específica. Es decir, el programa se invocaba publicado el jueves por la noche: 18. Crear un
con "foo" en lugar de "./foo", como se hacía con directorio con el nombre sh en /usr/tmp hace
el ataque basado en shell. Como resultado, en que esta prueba falle, al igual que los intentos
sistemas donde la ruta predeterminada posteriores de crear archivos ejecutables con
utilizada por el shell de sendmail no contenía el ese nombre. Los programadores de shell
directorio actual ("."), la invocación del código experimentados suelen usar el equivalente del
fallaba. Cabe señalar que este fallo interrumpe indicador -e (exist) en la función de prueba csh
el procesamiento de comandos posteriores en circunstancias como esta, para detectar no
(como la rm de los archivos), y esta podría ser la solo directorios, sino también sockets,
razón por la que muchos administradores de dispositivos, FIFOs con nombre, etc.
sistemas descubrieron copias del código fuente El código contiene otros coloquialismos que
del programa vector en sus directorios delatan la falta de experiencia en la escritura de
/usr/tmp. código portable. Un ejemplo es el bucle de
4.4.2. THE MACHINES INVOLVED código donde las unidades de archivo se cierran
Como ya se ha mencionado, este ataque se justo después de que el programa vectorial
realizó únicamente en máquinas Sun 3 y VAX comience a ejecutarse, y de nuevo en el
con BSD UNIX. Se ha observado en al menos programa principal justo después de que
una lista de correo que, si el código de Sun se comience a ejecutarse. En ambos programas,
hubiera compilado con la opción -mc68010, se ejecuta código como el siguiente:
más máquinas Sun habrían sido víctimas del
gusano. Resulta curioso que no se atacaran for (i=0; i<32; i++)
más máquinas. En particular, hay muchas close(i);
máquinas Pyramid, Sequent, Gould, Sun 4 y Sun
i386 en la red. Si también se hubieran incluido La forma portátil de realizar la tarea de cerrar
los archivos binarios de estas, el gusano podría todos los descriptores de archivos (en sistemas
haberse propagado mucho más. De hecho, derivados de Berkeley) es ejecutar:
algunas ubicaciones, como la Universidad
Estatal de Ohio, se libraron por completo de los for (i=0; i<getdtablesize; i++)
efectos del gusano, ya que todas sus máquinas close(i);
O la aún más eficiente suposición desde que la escuché por primera vez, y
for (i= getdtablesize ()-1; i>=0; i--) tras examinar el código a fondo, estoy convencido de
close(i); que este programa no constituye prueba que respalde
Esto se debe a que la cantidad de unidades de tal afirmación. El código aparentemente estaba
archivos disponibles (y, por lo tanto, abiertas) inacabado y fue creado por alguien inteligente, pero no
puede variar de un sistema a otro. especialmente talentoso, al menos en el sentido que
solemos asociar con programadores y diseñadores
talentosos. El código contenía muchos errores y fallos
4.5. RESUMEN que no cometería un programador cuidadoso y
Se pueden extraer muchos otros ejemplos del competente. El código no demuestra una comprensión
código, pero los puntos ya deberían ser obvios: el clara de la buena estructuración de datos, los
autor del programa Worm pudo haber sido un algoritmos ni siquiera de las fallas de seguridad de
programador de UNIX con cierta experiencia, pero no UNIX. Sí contiene ingeniosas explotaciones de dos
era en absoluto el "mago de UNIX" que muchos fallas específicas en las utilidades del sistema, pero
afirman. El código emplea algunas técnicas y trucos eso difícilmente demuestra genio. En general, el código
ingeniosos, pero existen dudas sobre si son obra no es tan impresionante, y su "éxito" se debió tanto a la
original del autor de Worm. El código parece ser el suerte como a la habilidad de programación del autor.
producto de un programador inexperto, apresurado o Sin embargo, la suerte nos favoreció a la mayoría. Los
descuidado. La persona (o personas) que creó este efectos de este gusano fueron (en gran medida)
programa parece carecer de conocimientos benignos y se detuvo fácilmente. Si el código se hubiera
fundamentales sobre algunos algoritmos, probado y desarrollado más, o se hubiera combinado
estructuras de datos y propagación de red, pero al con algo destructivo, el coste habría sido
mismo tiempo posee un conocimiento muy considerablemente mayor. Puedo pensar fácilmente en
sofisticado de las características y recursos de la varias docenas de personas que podrían haber escrito
red. El código no parece haber sido probado (aunque este programa, y no solo haberlo hecho con muchos
cualquier otra prueba que no sea unitaria no sería menos errores (o ninguno), sino que lo hubieran hecho
fácil de hacer), o bien se publicó prematuramente. considerablemente más virulento. Afortunadamente,
De hecho, es posible que ambas conclusiones sean todos esos individuos son profesionales responsables
correctas. La presencia de tanto código muerto y y dedicados que no considerarían semejante acto.
duplicado, junto con el tamaño de algunas Lo que aprendamos de esto sobre la seguridad de
estructuras de datos (como la matriz de código nuestros sistemas ayudará a determinar si este es el
objeto de 20 ranuras), sugiere que el programa fue único incidente de este tipo que necesitamos analizar.
pensado para ser más completo. Este ataque también debería indicar que necesitamos
5. CONCLUSIONES un mejor mecanismo para coordinar la información
Del código se desprende claramente que el gusano fue sobre fallos de seguridad y ataques. La respuesta a
diseñado deliberadamente para dos cosas: infectar el este incidente fue en gran medida improvisada y
mayor número posible de máquinas y ser difícil de resultó en la duplicación de esfuerzos y en la
rastrear y detener. No cabe duda de que se trató de un imposibilidad de difundir información valiosa a los
accidente, aunque su liberación pudo haber sido sitios que la necesitaban. Muchos administradores de
prematura. Aún se desconoce si este gusano, o una sitios descubrieron el problema leyendo el periódico o
versión futura, iba a realizar otras tareas. Aunque se ha viendo la televisión. Las principales fuentes de
alegado la autoría (Robert T. Morris), este no ha información para muchos de los sitios afectados
confesado públicamente ni se ha probado parecen haber sido los grupos de noticias de Usenet y
definitivamente el asunto. Considerando la una lista de correo que preparé cuando se descubrió el
probabilidad de acciones legales tanto civiles como gusano. Aunque útiles, estos métodos no garantizaron
penales, es improbable que se presente una confesión una difusión oportuna y generalizada de información
y una explicación a corto plazo. útil, especialmente porque dependían de Internet para
La especulación se ha centrado en motivaciones tan funcionar. Más de tres semanas después de este
diversas como la venganza, la pura curiosidad incidente, algunos sitios seguían sin estar conectados
intelectual y el deseo de impresionar a alguien. Sin a Internet.
embargo, esto debe seguir siendo especulación por el Esta es la segunda vez en seis meses que la comunidad
momento, ya que no tenemos acceso a una de Internet se ve afectada por el pánico.
declaración definitiva del/de los autor(es). Como La primera vez ocurrió en mayo, cuando corrió el rumor
mínimo, debe haber alguna duda sobre la constitución de que un empleado descontento había colocado una
psicológica de alguien que desarrollaría y ejecutaría "bomba lógica" en el software de Sun. Muchos sitios
dicho software. Mucha gente ha afirmado que los retrasaron la hora de sus sistemas o los apagaron para
autores de este código20 debieron ser "genios evitar daños. El personal de Sun Microsystems
informáticos" de algún tipo. Me ha molestado esa respondió de forma admirable, realizando pruebas
internas para aislar cualquier amenaza de este tipo y
difundiendo información a la comunidad sobre cómo UNIX contribuyó tanto a derrotar al gusano como a su
abordar la situación. Desafortunadamente, casi todos propagación. La inmediatez de la comunicación, la
los demás parecen haber observado el desarrollo de capacidad de copiar archivos fuente y binarios de una
los acontecimientos, contentos de no haber sido ellos máquina a otra, y la amplia disponibilidad tanto de
quienes tuvieron que lidiar con la situación. El gusano fuentes como de expertos, permitieron que personal de
nos ha demostrado que todos nos vemos afectados por todo el país colaborara para resolver la infección,
los eventos en nuestro entorno compartido y que incluso a pesar de la desconexión generalizada de
necesitamos desarrollar mejores métodos de partes de la red. Si bien la reacción inmediata de
información fuera de la red antes de la próxima crisis. algunas personas podría ser restringir la comunicación
Todo este episodio debería hacernos reflexionar sobre o promover diversas opciones de software
la ética y las leyes relativas al acceso a las incompatibles para evitar la recurrencia de un gusano,
computadoras. La tecnología que utilizamos se ha esta sería una reacción totalmente errónea. Aumentar
desarrollado tan rápidamente que no siempre es los obstáculos a la comunicación abierta o reducir el
sencillo determinar dónde están los límites adecuados número de personas con acceso a información
de la acción moral. Muchos profesionales informáticos exhaustiva no detendrá a un atacante decidido; solo
de alto nivel comenzaron sus carreras hace años reducirá la reserva de expertos y recursos disponibles
pirateando los sistemas informáticos de sus para combatir dicho ataque. Además, tal actitud sería
universidades y lugares de trabajo para demostrar su contraria al propósito de tener una red abierta y
experiencia. Sin embargo, los tiempos han cambiado y orientada a la investigación. El gusano fue causado por
el dominio de la informática y la ingeniería informática una falta de ética, así como por fallas en la seguridad;
ahora implica mucho más de lo que se puede un intento de prevención puramente tecnológico no
demostrar mediante el conocimiento profundo de las resolverá el problema en su totalidad y podría causar
fallas de un sistema operativo en particular. Empresas nuevas dificultades.
enteras ahora dependen, con o sin razón, de los
sistemas informáticos. El dinero, las carreras
profesionales e incluso la vida de las personas pueden
depender del funcionamiento ininterrumpido de las
computadoras. Como sociedad, no podemos
permitirnos las consecuencias de tolerar o fomentar
comportamientos que amenacen o dañen los sistemas
informáticos. Como profesionales, los científicos e
ingenieros informáticos no podemos permitirnos
tolerar la romantización de los vándalos y delincuentes
informáticos. Este incidente también debería generar
debate sobre la distribución de información
relacionada con la seguridad. En particular, dado que
cientos de sitios han "capturado" la forma binaria del
gusano, y dado que el personal de dichos sitios cuenta
con herramientas y conocimientos que les permiten
aplicar ingeniería inversa al código del gusano,
deberíamos preguntarnos cuánto tiempo esperamos
que sea beneficioso mantener el código sin publicar.
Como se mencionó en la introducción, al menos once
grupos independientes han producido versiones del
gusano con ingeniería inversa, y preveo que se han
realizado o se intentarán muchas más, especialmente
si las versiones actuales se mantienen privadas.
Incluso si ninguna de estas versiones se publica
formalmente, cientos de personas habrán tenido
acceso a una copia antes de que finalice el año.
Históricamente, intentar garantizar la seguridad del
software mediante la confidencialidad ha demostrado
ser ineficaz a largo plazo. Es vital que eduquemos a los
administradores de sistemas y les pongamos a
disposición correcciones de errores de una forma que
no comprometa su seguridad. Los métodos que
impiden la difusión de información parecen ser
completamente contrarios a ese objetivo. Por último,
es importante destacar que la naturaleza de Internet y

Common questions

Con tecnología de IA

La rutina 'infect' era crucial para la propagación del gusano al verificar que un host no estuviera ya infectado ni inmunizado antes de intentar un ataque mediante diversos métodos como 'try_rsh', 'try_fingerd' y 'try_sendmail'. Si un método tenía éxito, se pasaban los descriptores de archivo a 'sendWorm'. Sin embargo, su rápida replicación saturaba recursos de red, lo que llevó a su detección rápida y posterior contención. La falta de un historial que registrara hosts infectados previamente también contribuyó a su detección, ya que cada instancia del gusano intentaba continuamente infectar los mismos hosts, lo que facilitaba la identificación de su actividad en la red .

El gusano utilizaba métodos de infección como 'try_rsh', 'try_fingerd' y 'try_sendmail' para establecer una conexión remota y enviar su código a la máquina objetivo. Si una de estas conexiones fallaba, marcaba al host como inmune. Su efectividad se basaba en la explotación de servicios de red comunes y mal configurados en la época, que permitían el acceso remoto sin adecuadas medidas de seguridad, como autenticación de usuarios o encriptación de datos. Gracias a estas vulnerabilidades y la falta de monitoreo de tráfico anómalo, el gusano podía propagarse rápidamente en redes extensas. Sin embargo, estas mismas características también revelaban su actividad, facilitando su detección y respuesta .

La rápida propagación del gusano evidenció varias limitaciones en la seguridad informática de la época, como la falta de mecanismos eficaces para gestionar el tráfico inusual de red y detectar infecciones proactivamente. La dependencia en protocolos inseguros como Telnet y las deficiencias en la coordinación entre servicios de seguridad permitieron que el gusano se diseminara rápidamente. Adicionalmente, la poca comunicación y la incapacidad para responder rápidamente a incidentes de seguridad contribuyeron a su impacto. La estructura del gusano también mostró cómo explotaba vulnerabilidades conocidas pero sin parchear, sugiriendo deficiencias en la actualización y mantenimiento de sistemas, así como en la preparación para ciberataques complejos .

El gusano explotaba errores de seguridad de UNIX de manera ingeniosa, como en el caso de las rutinas utilizadas para establecer conexiones a través de vulnerabilidades en 'fingerd' y 'sendmail'. Sin embargo, el diseño general del gusano muestra numerosas fallas de programación, incluyendo código no optimizado, poca gestión de recursos y errores comunes que no haría un programador cuidadoso. Aunque pudo explotar ciertas vulnerabilidades, la falta de sofisticación en su diseño general sugiere que aunque el autor poseía conocimiento de ciertas debilidades de sistema, no tenía un profundo entendimiento de algoritmos y estructuras de datos optimizadas, por lo cual no se podría considerar completamente un diseño sofisticado .

El éxito del gusano no se debió exclusivamente a la capacidad técnica del autor, sino más bien a una conjunción de suerte y negligencia en redes vulnerables. Aunque explotó fallas como las de 'fingerd' y 'sendmail', el código contenía numerosos errores de programación y diseño deficiente, incluyendo código sin terminar y la falta de utilización óptima de estructuras de datos. Las críticas al autor se centran en que posiblemente no contaba con la experiencia de un 'mago de UNIX'; más bien, el éxito del gusano reflejó más las debilidades en la seguridad de red de la época que las habilidades del autor. Esto sugiere que aunque el autor tenía conocimiento de vulnerabilidades existentes, no demuestra un dominio avanzado en programación de alto nivel .

El mecanismo utilizado por el gusano para aleatorizar direcciones IP consistía en generar una lista de todas las direcciones IP de los hosts de puerta de enlace que respondían a la rutina 'try_telnet'. Esta lista era permutada aleatoriamente antes de realizar los intentos de infección. Cada dirección en la lista resultante se enmascaraba con un valor devuelto por 'netmaskfor' y el resultado se usaba para atacar la red con 'attack_network'. Esta estrategia de aleatorización podía aumentar la efectividad del gusano al ayudar a evitar detecciones lineales y patrones de análisis, complicando la tarea de los sistemas de defensa automatizados diseñados para identificar patrones de ataque .

La rutina 'makemagic' era crítica para establecer conexiones seguras y eficaces con los hosts de destino, especialmente mediante la generación de un número aleatorio como desafío al intentar conectarse al puerto Telnet (23). Esta rutina intentaba hasta 1024 conexiones TCP, utilizando números de puerto aleatorios. Esto no solo hacía más difícil predecir y bloquear tales intentos de conexión, sino que también aseguraba robustez en el establecimiento de un canal seguro y desviado. La importancia de 'makemagic' radica en su capacidad para enmascarar las intenciones del gusano, dificultando su detección y monitoreo por sistemas de seguridad, convirtiéndolo en un componente importante del diseño del gusano .

La rutina 'supports_telnet' determinaba si un host era vulnerable al protocolo Telnet intentando establecer una conexión TCP al puerto 23 de la máquina remota. Si la conexión se establecía con éxito, el host era considerado compatible con Telnet, y se devolvía 'VERDADERO'; de lo contrario, el retorno era 'FALSO', lo que implicaba que el host no cumplía con los requerimientos de conexión. Esta rutina incrementaba la vulnerabilidad de la red, ya que identificaba hosts que utilizaban protocolos de comunicación menos seguros, como Telnet, haciendo a las máquinas más susceptibles a ser comprometidas por el gusano .

Aunque Robert T. Morris, el supuesto autor del gusano, pudo haber tenido suficiente tiempo para desarrollar una versión Sun del ataque 'fingerd', no lo hizo. Esto podría deberse a una falta de motivación, capacidad, tiempo o recursos para desarrollar una versión para Sun; argumentos que se ponen en duda dado que los binarios de Sun estaban incluidos. Esto implica que tal vez carecía del conocimiento específico para este desarrollo, lo cual cuestiona la percepción de su capacidad técnica como programador experto. Esta falta de una versión Sun podría indicar una inconsistencia en sus habilidades de programación, sugiriendo que el gusano podría haber sido una mezcla de código desarrollado apresuradamente, lo cual se refleja en críticas sobre la falta de sofisticación de su código en comparación con otros ingenieros más talentosos que podrían haber escrito códigos más eficaces .

La rutina 'other_sleep' realizaba esperas pasivas dependiendo de la variable global 'other_fd', siendo ineficiente ya que podía llevar a tiempos de espera variables innecesarios en el sistema. Si 'other_fd' era menor a cero, la rutina simplemente esperaba el tiempo indicado. De lo contrario, esperaba llamadas al sistema 'select'. Pero, como el retorno de 'select' indicaba pendientes potencialmente poco relevantes, el diseño generaba demoras ineficaces. Esta implementación reflejaba una falta de optimización y comprensión de la eficiencia en el uso de recursos, contribuyendo a la carga innecesaria en el sistema y a una operación menos efectiva del gusano .

También podría gustarte