ESET ha analizado y seguido el código malicioso Linux/Ebury, un backdoor de OpenSSH y que roba credenciales de acceso. El resultado de esta investigación es un esfuerzo conjunto con el CERT-Bund, la Swedish National Infrastructure for Computing, la European Organization for Nuclear Research (CERN) y otras organizaciones que conforman un grupo de trabajo internacional.
En este post se desarrolla un análisis profunfo de Linux/Ebury. Este sofisticado backdoor es utilizado para robar contraseñas de OpenSSH y obtener acceso a los servidores comprometidos. De acuerdo a reportes anteriores, este backdoor ha estado in the wild por los últimos dos años. Linux/Ebury tiene dos formas diferentes: una librería maliciosa y una actualización sobre los binarios de OpenSSH. La librería maliciosa es una versión modificada de libkeyutils.so, la cual es una librería compartida utilizada por todos los archivos ejecutables de OpenSSH tales como ssh, sshd y ssh-agent. Más adelante también se describir como trabaja este backdoor y como se asocia a las funcionalidades de OpenSSH. Además se mostrará como captura las claves de acceso y finalmente se proporcionan algunos detalles de como los adiministradores de sistemas pueden identificar si están infectados.
Si un sistema se encuentra infectado con Linux/Ebury, lo más recomendable es reinstalar el sistema operativo. Además es muy importante considerar que todas las contraseñas usadas para acceder al sistema pueden haber sido comprometidas, por lo que todas las contraseñas y las claves SSH necesitan ser cambiadas.
Variantes conocidas
Linux/Ebury sobresale por multiples razones. Aunque este tipo de códigos maliciosos son frecuentes en Windows, es la primera vez que vemos una librería maliciosa que había sido utilizada en sistemas POSIX. Linux/Ebury también utiliza trucos poco comunes para asociarse (hook) a las funciones, descubrir el espacio de direcciones del ejecutable ELF que carga la librería y aplica los parches a su código en tiempo de ejecución . Creemos que antes de usar la libreria externa para asociarse a los procesos de OpenSSH , el autor de Linux/Ebury utiliza un parche para modificar el código fuente de OpenSSH, lo que añade "funcionalidades adicionales" en el software.
Las primeras variantes encontradas modificaban los binarios que quedan en el disco. Los tres archivos afectados son ssh, sshd y ssh-add. También hemos visto el uso de los comandos rpm para eliminar la firma de los paquetes OpenSSH originales (openssh-server , openssh-clients ) y modificar la base de datos RPM para actualizar los hash de los archivos con los de los archivos maliciosos. Esto hará que la salida del comando rpm --verify openssh-servers muestre los archivos como si no se modificaran. Sin embargo, la salida de rpm -qi openssh-servers muestra claramente que a el paquete le está faltando su firma.
Variantes posteriores de Linux/Ebury no modifican los archivos OpenSSH directamente. En lugar de ello, una librería compartida que se carga por todos los archivos ejecutables OpenSSH se modifica para cambiar el comportamiento de los programas. Los cambios son los mismos que las variantes anteriores que modificaban OpenSSH, excepto que algunas funciones son asociadas y los parches al código original se aplican en tiempo de ejecución. La librería compartida que se modifica en el sistema es libkeyutils.so. Por lo general, este archivo es de aproximadamente 10 KB de tamaño. El malware añade aproximadamente 20KB de código malicioso adicional, por lo que el archivo pesa en alrededor de 30 KB en total.
A continuación se muestran dos ejemplos de como se implementa este backdoor. El primero muestra un archivo infectado por Linux/ Ebury junto al archivo libkeyutils.so limpio. El enlace simbólico se modifica para indicar la versión alterada.
El segundo ejemplo muestra la libreria libkeyutils.so que ha sido reemplaza por una versión de Linux/Ebury.
Aunque insertar código malicioso dentro de las librerias ya se ha visto antes, esta es la primera vez que hemos observado esta técnica se utilice en el sistema operativo Linux para modificar el comportamiento de OpenSSH.
Para habilitar las diferentes características del malware, se añadió una función constructor de libkeyutils.so. Esta función se llama cuando se carga la librería y detecta desde donde se ha cargado el binario, aplica parches al código original y se asocia con las funciones de la tabla de importación original.
En las variantes más recientes de Linux/Ebury, los strings se ofuscan con un simple cifrado XOR con una clave estática. Después de desempaquetarse, el malware carga diferentes funciones que requiere el uso de múltiples llamadas a la función dlsym. Linux/Ebury descubre el espacio original de direcciones ejecutable llamando dlopen(NULL, RTLD_NOW)y pasando el identificador devuelto a dlinfo(handle, RTLD_DI_LINKMAP, ...).
Esto funciona incluso si ASLR está habilitado en un sistema. Este comportamiento da a Linux/Ebury la capacidad de llegar hasta la tabla de importación de un ejecutable ELF y sustituir la dirección de la función original importada en la memoria. El resultado es que cuando los programas ssh, sshd o ssh-add llame a una de las funciones que se ha asociado (hooked function), será redirigido a la aplicación libkeyutils.so maliciosa que puede reemplazar el comportamiento original. El siguiente fragmento de código muestra las llamadas a dlopen y dlinfo para encontrar el espacio principal de direcciones de programa y moverse por la información de la cabecera ELF:
Sobre la base de las importaciones y exportaciones del main del ejecutable, Linux/Ebury detectará si está cargada por ssh, sshd o ssh-add. A continuación, se aplicarán diferentes parches sobre el código para lograr su objetivo de robar las credenciales.
Las siguientes funciones se asocian (hokeed) cuando la libkeyutils.so maliciosa se carga dentro del proceso sshd:
-
audit_log_user_message
-
audit_log_acct_message
-
hosts_access
-
connect
-
__syslog_chk
-
write
-
syslog
-
popen
-
hosts_access
-
crypt
-
pam_start
Las funciones de registro están asociadas de manera que cada vez que se usa el backdoor, nada se envía a la función de registro, para no dejar rastro en los archivos de registro. Si el backdoor no está en uso, el registro se comporta normalmente y las llamadas a funciones se redireccionan a las originales.
Otras funciones como pam_start y crypt se utilizan para obtener la contraseña utilizada por el usuario para autenticarse. Curiosamente, pam_start se asociará adicionalmente a pam_authenticate para capturar la contraseña. La función de conexión se asocia de manera que cuando se utiliza el comando Xbnd (documentado más adelante), una llamada a bind con el socket se hace antes de realizar la llamada real a conectar.
Modificación del código
Cuando no puede asociarse a la tabla de importación, Linux/Ebury modificará el segmento de código alterando secciones específicas del programa para redirigir la instrucción de llamada con su propia aplicación. La siguiente figura muestra un ejemplo cuando el programa ssh llama a su propia función key_parse_private_pem y el flujo de ejecución se redirige al código malicioso. La dirección se muestra en rojo, ya que es en el espacio de direcciones libkeyutils.so, fuera de ssh. El hook llama a la implementación original, registra la clave privada en memoria y posteriormente vas a buscar los operadores.
Linux/Ebury cambia cuidadosamente los permisos en la página en la que está escribiendo. Por defecto, el segmento de código no se puede escribir por lo que al tratar de modificar el porgrama va a fallar. La función mprotect se utiliza para agregar el permiso de escritura, así como para eliminarlo después de que el parche se aplica para no levantar sospechas.
Antes de tratar de modificar el segmento de código, el programa establece cuidadosamente un controlador para interceptar cualquier fallo de segmentación que pueda causar. Más específicamente, el controlador será llamado si el proceso recibe una señal SIGSEGV o SIGBUS. En el caso que reciba una señal, Linux/Ebury simplemente aborta su misión y deja que el OpenSSH haga su comportamiento legítimo. La manera de recuperarse de un fallo de segmentación diferente. Antes de hacer algo que podría bloquear el proceso, sigsetjmp se llama para crear un snapshot de la situación actual. Entonces, si ocurre una violación de acceso, utiliza siglongjmp para restablecer a su estado anterior.
Esta técnica para modificar el código es limitado ya que las compensaciones de código para parchear está codificada dentro del troyano libkeyutils.so
. Por lo tanto, su eficacia se limita al binario objetivo de la variante.
Comunmente cada variante de libkeyutils.so
puede funcionar con 3, 4 o 5 diferentes versions de OpenSSH para distribución específica de Linux.
Funcionalidades
El backdoor se activa mediante el envío de datos especialmente diseñados dentro de la cadena de identificación de versión del protocolo cliente SSH. La epecificación SSH sobre el protocolo de identificación de versión dice
Después de abrir el socket, el servidor envía una cadena de identificación, que es de la forma "SSH-<protocolmajor> <protocolminor> -. <version> \n", donde <protocolmajor> y <protocolminor> son enteros y especifican el número de versión (versión de distribución no software). <versoón> es un string con la versión de software del lado del servidor (máximo 40 caracteres), no es interpretado por el lado remoto, pero puede ser útil para depurar.
http://www.openssh.com/txt/ssh-rfc-v1.5.txt
— T. Ylonen
La parte de la versión podría ser cualquier cosa y no debe ser interpretado por el servidor SSH. En el caso de una conexión backdoor Linux/Ebury, el <version> contiene una cadena hexadecimal de veintidós (22) caracteres o más. Se incorpora una contraseña de once (11) caracteres que se cifra primero con la dirección IP del cliente y luego codifica como una cadena hexadecimal, opcionalmente, un comando de (4) byte puede ser encriptado y codificado, después de la contraseña.
Hay que tener en cuenta que también se envía la identificación de la versión de protocolo antes de que handshake se realice, por lo que es una potencial señal de detección de intrusiones en una traza de red.
Una versión ejemplo del protocolo SSH para iniciar un shell de root tiene este aspecto:
SSH-2.0-fb54c28ba102cd73c1fe43
Una vez verificada la clave, el proceso sshd permitirá utilizar cualquier contraseña durante el proceso de autenticación. Si PermitRootLogin, PasswordAuthentication o PermitEmptyPassword están desactivados, verifica que funcione. También deshabilita el registro de sesiones exitosas, quedando como si nada pasara.
En la versión 1.3.1 y posteriores, el SHA1 de la contraseña se mantendrá en el binario en lugar de un string de (11) once caracteres (práctica de seguridad básica de los autores Linux/Ebury). Esto hace que adivinar la contraseña se algo poco práctico a menos que tenga una captura de paquetes de conexión exitosa de los operadores. Por otra parte, la contraseña es diferente de una variante a otra. Esto nos lleva a pensar que los operadores tienen una base de datos de los servidores infectados con sus correspondientes contraseñas de bakcdoor para que poder activarlo exitosamente.
El propósito principal de Linux/Ebury es robar las credenciales de acceso. Las contraseñas robadas son utilizadas para afectar otros sevidores. Este código malicioso no se propaga por si solo, por lo que necesita que sea instalado manualmente o haciendo el deploy del malware con algún script.
En la siguiente entrega de este análisis se mostrará el análisis de las funcionalidades para robar y extraer las contraseñas, algunos comandos adicionales y los indicadores para que los administradores de red sepan si sus servidores están comprometidos.
Robo de contraseñas
Las credenciales son interceptadas en localidades múltiples cuando son usadas o tipeadas por la víctima:
Contraseñas de inicio de sesión exitoso al servidor infectado: Cuando alguien inicia sesión en el sistema infectado con Linux/Ebury, el demonio de sshd graba la contraseña y la envía al servidor exfiltrado.
Cualquier intento de logueo al servidor infectado: Aún cuando el intento de inicio de sesión no es exitoso, el nombre de usuario y contraseña se enviarán a los operadores. Las credenciales son formateadas de otra manera para permitirle a los operadores diferenciar las válidas de las inválidas.
Contraseña en inicio de sesión exitoso desde el servidor infectado: Cuando un usuario usa un cliente ssh en un servidor infectado, Linux/Ebury interceptará la contraseña y la envía al servidor.
Clave privada: Cuando el cliente ssh en un servidor infectado pregunta a un usuario por la clave privada, la clave será enviada al servidor exfiltrado.
Clave privada no cifrada: Cuando una clave privada es utilizada para autenticar a un servidor, la versión no cifrada es interceptada por el malware. A diferencia de las contraseñas, no envía la clave a los servidores de exfiltración. En lugar de eso, se guardará en memoria y esperará que los operadores la recojan con un comando xcat.
Claves privadas agregadas a un agente OpenSSH con ssh-add: Las claves agregadas al agente OpenSSH también son interceptadas por el malware. Tanto las claves no cifradas como la clave tipeada por el usuario son grabadas.
Cualquiera sea el tipo de credencial, Linux/Ebury agregará información relevante a los operadores para poder usarla, como por ejemplo: nombre de usuario, dirección IP de destino y el puerto escucha de OpenSSH.
Exfiltración de contraseñas
Cuando una clave es interceptada por Linux/Ebury, la información es enviada al servidor remoto a través de peticiones de DNS envenenadas a una dirección IP específica. El malware crea una petición de registro A normal que será enviada por UDP al puerto 53. El nombre de dominio solicita contenido cifrado, información codificada en hexadecimal y una dirección IP. La información tiene el siguiente formato:
<información codificada en hexadecimal>.<dirección IP>
Esa información contiene las credenciales que fueron descriptas previamente. Están cifradas con XOR con la clave estática de 4 bytes 0x000d5345 antes de ser codificada en hexadecimal.
La dirección IP incluida en la consulta depende del tipo de credenciales robadas. Si las credenciales pertenecen al servidor infectado, entonces es usada la dirección IP del cliente. De lo contrario, se usa la dirección IP remota a la que se conecta el servidor infectado.
Creemos que los autores del código malicioso eligieron enviar los paquetes que parecen peticiones legítimas de DNS sobre UDP por el puerto 53 para evitar se bloqueado por firewalls. Es muy común poner en lista blanca las peticiones DNS en las configuraciones del firewall porque bloqueandolas puede romper la resolución de nombres.
Hay dos formas en la cual Linux/Ebury puede elegir a cuál servidor enviar los paquetes DNS. El primero, se puede establecer explícitamente por el operador cuando se envia un comando Xver. El segundo método usa un algoritmo para generar un dominio de nombres dinámico. Este dominio de nombre será consultado por A y registros en texto. El registro TXT será usado para verificar que está bajo control de los operadores usando una clave criptográfica. Detalles sobre el algoritmo de generación de dominio y la verificación procesada será publicada en el reporte completo.
Hay tres comandos disponibles para facilitar la gestión del servidor comprometido de parte de los atacantes. Un comando se agrega a la contraseña de puerta trasera antes de ser encriptado. Cuando la puerta trasera identifica un comando, lo interpreta en lugar de iniciar una shell. Aquí está lalista de comandos que pueden ser procesadas por la puerta trasera: xcat, xver y xbnd.
Conclusión
El malware Linux/Ebury claramente es una amenaza compleja con características muy interesantes como hooking de código, manejo de excepciones avanzadas POSIX y varias técnicas de ocultación en un sistema infectado. Basado en la información que capturamos, estimamos que miles de sistemas están actualmente infectados con Linux/Ebury. Consideramos muy importante aclarar que no hemos confirmado debilidades en OpenSSH en si misma. Adicionalmente, el troyano Linux/Ebury se propaga utilizando credenciales robadas colectadas por los operadores. Con las credenciales de administrador, no hay necesidad de explotar una vulnerabilidad 0-day. Sin embargo, algunas partes de la forma con que los operadores trabajan con el robo completo de las credenciales todavía son un misterio.
Detalle de los archivos
Hashes troyanizados libkeyutils.so file SHA-1:
09c8af3be4327c83d4a7124a678bbc81e12a1de4 - Linux/Ebury - Version 1.3.2
2e571993e30742ee04500fbe4a40ee1b14fa64d7 - Linux/Ebury - Version 1.3.4b2
39ec9e03edb25f1c316822605fe4df7a7b1ad94a - Linux/Ebury - Version 1.3.2
3c5ec2ab2c34ab57cba69bb2dee70c980f26b1bf - Linux/Ebury - Version 1.3.2
471ee431030332dd636b8af24a428556ee72df37 – Linux/Ebury - Version 1.2.1
5d3ec6c11c6b5e241df1cc19aa16d50652d6fac0 - Linux/Ebury - Version 1.3.3
74aa801c89d07fa5a9692f8b41cb8dd07e77e407 - Linux/Ebury - Version 1.3.2
7adb38bf14e6bf0d5b24fa3f3c9abed78c061ad1 - Linux/Ebury - Version 1.3.2
9bb6a2157c6a3df16c8d2ad107f957153cba4236 - Linux/Ebury - Version 1.3.2
9e2af0910676ec2d92a1cad1ab89029bc036f599 - Linux/Ebury - Version 1.3.3b
adfcd3e591330b8d84ab2ab1f7814d36e7b7e89f - Linux/Ebury - Version 1.3.2
bf1466936e3bd882b47210c12bf06cb63f7624c0 - Linux/Ebury - Version 1.3.2
d552cbadee27423772a37c59cb830703b757f35e - Linux/Ebury - Version 1.3.3
e14da493d70ea4dd43e772117a61f9dbcff2c41c - Linux/Ebury - Version 1.3.2
f1ada064941f77929c49c8d773cbad9c15eba322 - Linux/Ebury - Version 1.3.2
Traducción y adaptación del post de Marc-Etienne M.Léveillé en We Live Security.