— Cliff Stoll, The Cuckoo’s Egg
El 2 de noviembre de 1988, fue liberado el gusano de Morris, causando que el 10% de los equipos conectados a Internet, tuvieran saturación haciéndolos inoperables; pero, como lo hizo, que fue lo que este gusano realizaba en los equipos que los inutilizaba por completo.
A grandes rasgos, se identifican 4 etapas del desarrollo del gusano:
1. main
2. initialize
3. doit
4. infect
1. Al iniciar, la función main setea su argumento 0 como el proceso sh. Esto cambia el nombre del proceso del gusano corriendo a sh. Este es el mismo nombre del Bourne Shell, que es un proceso común utilizado por los usuarios para la entrada de datos en sus terminales. Por lo tanto, si alguien verificará la lista de los procesos en ejecución, mientras el gusano se ejecutara en el sistema, no vería nada raro.
1.1. El creador del gusano no quería que el gusano fuera fácil de capturar, ya que una vez que alguien tuviera una copia del gusano en ejecución, sería posible desensamblar el código y descubrir la forma de detenerlo. Con este fin, el siguiente paso del gusano, es setear el tamaño máximo de core dump a cero bytes, de esta forma si el programa fallara, o fuera forzado a fallar, los investigadores no podrían obtener una copia del gusano en ejecución.
2. En la etapa de inicialización, escanea las interfaces de red de la máquina que estén habilitadas, obteniendo las banderas y las direcciones de cada interfaz. También carga la máscara de red que permite determinar el rango de IP’s que son utilizadas por la red local.
Obtiene nombres de hosts, usuarios y contraseñas de los archivos de configuración del sistema (/etc/hosts y /etc/passwd); mediante un ataque de fuerza bruta, intenta adivinar las contraseñas de los usuarios, utilizando su propio nombre de usuario como contraseña y, al mismo tiempo, como diccionario para el ataque. También incluía y utilizaba su propio diccionario de contraseñas comunes; esto con el fin de concentrar una lista de posibles usuarios con acceso a otros equipos.
También, utiliza el /etc/passwd para buscar archivos .forward en los home de los usuarios, a fin de obtener direcciones adicionales de máquinas para los ataques.
3. En este punto, la inicialización se completa y el gusano llama su rutina central, doit, que ejecuta una serie de procedimientos diseñados para buscar y conectarse a otros hosts. Busca relaciones de confianza, archivos .rhosts y host.equiv para generar una lista de posibles objetivos a atacar. Este es el primer intento del gusano para infectar otras máquinas host.
También hay un procedimiento en el que se debe enviar un byte a la dirección 128.32.137.13 (ernie.berkeley.edu), por el puerto 11357, que no funcionó, ya que, el programa utiliza el comando TCP sendto, en lugar de un datagrama UDP. Dado que el programa nunca ha iniciado una relación con el antes mencionado puerto, el comando de TCP falla envíando un mensaje de error: “socket not connected“. Este byte aleatorio (uno de cada quince) parecía ser para el seguimiento de la evolución general del gusano en la red.Después de esto, el gusano procede con el bucle principal del programa.
4. La rutina infect es utilizada por el gusano para infectar equipos de destino con copias de sí mismo. Se ejecutan 3 de los 4 rutinas de ataque (El otro está dirigido por la rutina attack_user, definida en la parte de inicialización). Infect en realidad es bastante simple. Tiene pocas tareas:
– Primeramente verifica, que la dirección a infectar no sea la misma desde donde se esta ejecutando él mismo
– Comprueba que el destino no este marcado como inmune por los anteriores intentos de alcanzarlo
– Verifica que la dirección destino exista, ya que ha sido calculada aleatoriamente a partir de la mascara de red
Pasando esto, la rutina decide que la meta es legítima y entonces, inicia los intentos de ataque. En orden de ejecución, los ataques son los siguientes:
a. try_rsh
Este método intenta ejecutar remotamente una copia del proceso en la maquina objetivo. Si este proceso hijo tiene éxito en su tarea, devuelve los file descriptors del tubo abierto al proceso principal del gusano con el fin de recibir el proceso de un nuevo gusano. Si la ejecución remota falla, se elimina el proceso y se ejecuta nuevamente la rutina infect, utilizando el método try_fingerd.
b. try_fingerd
El demonio finger proporciona informes sobre un sistema informático o una persona en particular dentro de la red. Lee una cadena, y la envía al objetivo como argumento, solicitando una respuesta del mismo. Para obtenerla, utiliza una función de librería standar (gets); la cual, era vulnerable un desbordamiento de búfer, utilizando argumentos de más de 512 bytes, se aprovechaba de dicha vulnerabilidad. Enviando un argumento de 536 bytes, los 24 bytes eran usados para atacar la dirección de respuesta, enviar el código malicioso, copiandolo a un archivo de texto y compilandolo como un ejecutable, para iniciarlo posteriormente.
Si la ejecución fallaba, se elimina el proceso y ejecutaba nuevamente la rutina infect, utilizando el método try_sendmail.
c. try_sendmail
Sendmail es el programa más popular de correo en ambientes unix, normalmente es compilado con la opción DEBUG para pruebas de desarrollo. El método utilizaba esta opción, haciendo una llamada al puerto 25, enviando el gusano como texto plano y compilandolo como ejecutable en la máquina destino, para iniciarlo y replicarlo en el sistema.
Si la ejecución fallaba, se eliminaba el proceso y se ejecutaba nuevamente la rutina infect, marcando el host como inmune y reiniciando el bucle.
A grandes rasgos esta fue el método del ataque del gusano, uno bastante completo, y por lo mismo, muy difícil de detener; la manera en que se consiguió hacerlo fue desconectando las máquinas infectadas y cerrando las vulnerabilidades descritas.
En caso de que quieran experimentar un poco, les dejo el código del gusano; así como un excelente sitio donde pueden encontrar más información y detalles del ataque.
Espero les sirva.
[…] Debilidades en el Protocolo TCP/IP de Robert Morris […]