Introducción
En la primera parte, examinamos cómo funcionan los rootkits de Linux: su evolución, taxonomía y técnicas para manipular el espacio de usuario y el espacio del núcleo. En esta segunda parte, nos centramos en la ingeniería de detección. Comenzamos mostrando por qué la detección estática suele ser poco fiable contra rootkits de Linux, incluso cuando los binarios solo se modifican de forma trivial, y luego pasamos a señales de comportamiento y de ejecución que los defensores pueden usar en su lugar. Desde el abuso compartido de objetos y la carga de LKM hasta la eBPF, io_uring, persistencia y evasión de defensa, este artículo se centra en formas prácticas de detectar e investigar la actividad de rootkit en entornos reales.
Detección estática mediante VirusTotal
Antes de centrar en técnicas de detección conductual, es útil examinar qué tan bien los mecanismos tradicionales de detección estática identifican los rootkits de Linux. Para ello, realizamos un pequeño experimento empleando VirusTotal como proxy para la detección antivirus tradicional basada en firmas. Se ensambló un conjunto de datos de diez rootkits de Linux a partir de artículos de investigación públicos y repositorios de código abierto. Cada muestra se subió a VirusTotal o se recuperó de las presentaciones existentes.
Para cada rootkit, registramos el número de motores antivirus que marcaron el binario original. Luego realizamos dos pruebas adicionales:
- Binarios eliminados, creados usando
strip --strip-all, eliminando tablas de símbolos y otros metadatos no esenciales. - Binarios trivialmente modificados, creados agregando un solo byte nulo al archivo original: un cambio intencionadamente poco sofisticado.
El objetivo no era evadir la detección mediante una ofuscación avanzada, sino evaluar cuán frágiles son las firmas estáticas al enfrentar incluso a las modificaciones binarias más simples.
Tabla 1: Visión técnica del conjunto de datos de rootkit analizado
| Rootkit | Detecciones básicas | Desnudado | Byte nulo añadido |
|---|---|---|---|
| Azazel | 36/66 | 19/66 | 21/66 |
| Atormentado* | 32/66 | 32/66 | 21/66 |
| BrokePKG | 7/66 | 3/66 | 3/66 |
| Diamorfina | 33/66 | 8/64 | 22/66 |
| Kovid | 27/66 | 1/66 | 15/66 |
| Mobkit | 29/66 | 6/66 | 17/66 |
| Reptil | 32/66 | 3/66 | 20/66 |
| Snapekit | 30/66 | 3/66 | 19/66 |
| Simbionte | 42/66 | 8/66 | 22/66 |
| TripleCross | 31/66 | 17/66 | 19/66 |
* A Bedevil se le elimina por defecto, y por tanto, las detecciones básicas y las eliminadas son las mismas
Observaciones
Como era de esperar, el desmantelamiento de los binarios generalmente provocaba una fuerte caída en las tasas de detección. En varios casos, las detecciones cayeron casi a cero, lo que sugiere que algunos motores antivirus dependen en gran medida de la información de símbolos u otros metadatos fácilmente extraibles. Aún más revelador es el impacto de agregar un solo byte nulo: una modificación que no altera la lógica del programa, el flujo de ejecución ni el comportamiento, pero que aún así degrada significativamente la detección de muchas muestras.
Esto pone de manifiesto una debilidad fundamental de la detección estática basada en firmas. Si un cambio de un byte puede afectar de manera significativa los resultados de detección, los atacantes no necesitan una ofuscación sofisticada para evadir escáneres estáticos.
Técnicas de ofuscación en rootkits
Curiosamente, la mayoría de los rootkits en este conjunto de datos emplean poca o ninguna ofuscación estática avanzada. Cuando hay ofuscación, normalmente se limita a la codificación XOR simple de cadenas o datos de configuración, o a técnicas ligeras de empaquetado que alteran ligeramente la disposición binaria. Estos métodos son económicos de implementar y suficientes para neutralizar muchas firmas estáticas.
La ausencia de una ofuscación más avanzada en estas muestras es notable. Muchos son rootkits de prueba de concepto de código abierto diseñados para demostrar técnicas en lugar de evadir agresivamente la detección. Sin embargo, incluso con poca o ninguna obstrucción, la detección estática resulta poco fiable.
Por qué la detección estática no es suficiente
Este experimento refuerza un punto clave: la detección estática por sí sola es fundamentalmente insuficiente para una detección fiable en rootkits. La fragilidad de las firmas estáticas (especialmente ante modificaciones triviales) significa que los defensores no pueden confiar en indicadores basados en archivos o detección basada en hash para descubrir amenazas sigilosas.
Cuando los binarios pueden alterar sin afectar el comportamiento, la única señal consistente que queda es el comportamiento del rootkit en tiempo de ejecución. Por esa razón, el resto de este blog cambia su enfoque de los artefactos estáticos al análisis dinámico y la detección de comportamiento, examinando cómo interactúan los rootkits con el sistema operativo, manipulan el flujo de ejecución y dejan rastros observables durante la ejecución.
Ahí es donde la ingeniería de detección se vuelve tanto más desafiante como mucho más eficaz.
Ingeniería de detección dinámica
Técnicas de detección de carga de rootkit de Userland
Los rootkits de userland a menudo secuestran el proceso dinámico de enlace, inyectando objetos compartidos maliciosos en los procesos destino sin necesidad de acceso a nivel de núcleo. Una infección comienza con la creación de un archivo objeto compartido. La detección de archivos de objetos compartidos recién creados puede detectar mediante una regla de detección similar a la que se muestra a continuación:
file where event.action == "creation" and
(file.extension like~ "so" or file.name like~ "*.so.*")
Estos archivos suelen escribir en rutas escribibles o efímeras como /tmp/, /dev/shm/o subdirectorios ocultos bajo directorios de usuario personal. Los atacantes pueden descargarlos, compilarlos o descartarlos directamente desde un cargador. Este conocimiento puede aplicar a la regla de detección anterior para reducir el ruido.
Por ejemplo, en la telemetría mostrada arriba, podemos ver al actor de amenaza usando scp para descargar un archivo objeto compartido en un subdirectorio oculto dentro de /tmp, y luego moverlo a un directorio de biblioteca, intentando integrar. Detectamos esta y amenazas similares a través de:
- Objeto compartido creado por un proceso previamente desconocido
- Creation of Hidden Shared Object File
Una vez que el archivo de objeto compartido está presente en el sistema, el atacante tiene varias opciones para activarlo. Los mecanismos más empleados son la variable de entorno LD_PRELOAD , el archivo /etc/ld.so.preload y las rutas de configuración de enlazadores dinámicos como /etc/ld.so.conf.
La variable de entorno LD_PRELOAD permite a un atacante especificar un objeto compartido que se cargará antes que cualquier otra librería durante la ejecución de un binario enlazado dinámicamente. Esto permite una anulación completa de libc funciones, como execve(), open()o readdir(). Este método funciona por proceso y no requiere acceso root.
Para detectar esta técnica, se requiere telemetría para la variable de entorno LD_PRELOAD . Una vez disponible, se puede escribir cualquier lógica de detección para detectar valores de LD_PRELOAD poco comunes. Por ejemplo:
process where event.type == "start" and event.action == "exec" and
process.env_vars != null
Como se muestra en la Figura 1, este también fue el siguiente paso para los atacantes. Los atacantes se desplazaron libz.so.1 de /tmp/.X12-unix/libz.so.1 a /usr/local/lib/libz.so.1.
Para mayor fidelidad, implementamos esta lógica usando el tipo de regla new_terms, marcando solo en entradas de objetos compartidos no vistos previamente dentro de la variable LD_PRELOAD medio:
- Unusual Preload Environment Variable Process Execution
- Argumentos inusuales de línea de comandos LD_PRELOAD/LD_LIBRARY_PATH
Por supuesto, si se recogen más variables de entorno LD_PRELOAD y LD_LIBRARY_PATH , la regla anterior debería modificar para incluir específicamente estos dos elementos. Para reducir el ruido, se debe realizar un análisis estadístico y/o una evaluación de líneas base.
Otro método de activación es aprovechar el archivo /etc/ld.so.preload . Si está presente, este archivo obliga al enlazador dinámico a inyectar el objeto compartido listado en cada binario enlazado dinámicamente del sistema, lo que resulta en la inyección global.
Un método similar implica modificar la configuración del enlazador dinámico para priorizar rutas maliciosas de bibliotecas. Esto se puede lograr modificando /etc/ld.so.conf o agregando entradas a /etc/ld.so.conf.d/, seguido de ejecutar ldconfig para actualizar la caché. Esto cambia el camino de resolución de bibliotecas críticas, como libc.so.6.
Estos escenarios pueden detectar monitorizando los archivos /etc/ld.so.preload y /etc/ld.so.conf , así como el directorio /etc/ld.so.conf.d/ para eventos de creación/modificación. Usando esta telemetría en bruto, se puede implementar una regla de detección para marcar estos eventos:
file where event.action in ("creation", "rename") and
file.path like ("/etc/ld.so.preload", "/etc/ld.so.conf", "/etc/ld.so.conf.d/*")
Frecuentemente vemos esta cadena, donde se crea un objeto compartido y luego se modifica el enlace dinámico.
Que detectamos mediante las siguientes reglas de detección:
Encadenar estas dos alertas en un solo anfitrión merece una investigación.
Técnicas de detección de rootkit en espacio kernel
Cargar un LKM manualmente suele requerir el uso de utilidades integradas en la línea de comandos como modprobe, insmody kmod. Detectar la ejecución de estas utilidades detectará la fase de carga (cuando se realiza manualmente).
process where event.type == "start" and event.action == "exec" and (
(process.name == "kmod" and process.args == "insmod" and
process.args like~ "*.ko*") or
(process.name == "kmod" and process.args == "modprobe" and
not process.args in ("-r", "--remove")) or
(process.name == "insmod" and process.args like~ "*.ko*") or
(process.name == "modprobe" and not process.args in ("-r", "--remove"))
)
Muchos rootkits de código abierto se publican sin cargador y dependen de utilidades de carga LKM preinstaladas. Un ejemplo es Singularidad, que proporciona un script load_and_persistence.sh , que realiza varias acciones, tras las cuales finalmente llama a insmod "$MODULE_DIR/$MODULE_NAME.ko". Aunque insmod se llama en el comando, en realidad insmod kmod bajo el capó, con insmod como argumento de proceso. Un ejemplo de carga de singularidad:
Que pueden detectar fácilmente mediante las siguientes reglas de detección:
- Carga de módulos del núcleo mediante utilidad incorporada
- Carga de módulos del núcleo desde una ubicación inusual
Sin embargo, este enfoque de detección está lejos de ser infalible, ya que muchos rootkits dependen de un cargador para cargar el LKM, evitando así la ejecución de estas utilidades de usuario.
Por ejemplo, el cargador de Reptile invoca directamente la llamada de sistema init_module con un blob del kernel descifrado en memoria:
#define init_module(module_image, len, param_values) syscall(__NR_init_module, module_image, len, param_values)
int main(void) {
[...]
do_decrypt(reptile_blob, len, DECRYPT_KEY);
module_image = malloc(len);
memcpy(module_image, reptile_blob, len);
init_module(module_image, len, "");
[...]
}
Además, el módulo kmatryoshka de Reptile actúa como un cargador de cadena dentro del núcleo que descifra y carga otro LKM oculto usando un puntero directo de función a sys_init_module, localizado vía kallsyms_on_each_symbol(). Esto oculta aún más el mecanismo de carga para la visibilidad del usuario.
Por ello, es esencial entender qué hacen estas compañías de servicios en el interior; son simplemente envoltorios alrededor de las llamadas init_module() y finit_module() sistema. Por tanto, la detección efectiva debería centrar en rastrear directamente estas llamadas de sistema, en lugar de en las herramientas que las invocan.
Para garantizar la disponibilidad de las fuentes de datos necesarias para cargar los LKMs, se pueden emplear diversas herramientas de seguridad. Contralor o Gestor de Auditoría son opciones adecuadas. Para facilitar la recopilación de llamadas de sistema init_module() y finit_module , se puede implementar la configuración posterior.
-a always,exit -F arch=b64 -S finit_module -S init_module
-a always,exit -F arch=b32 -S finit_module -S init_module
Combinar esta telemetría en bruto con una regla de detección que alerta cuando ocurre este evento permite una defensa fuerte.
driver where event.action == "loaded-kernel-module" and
auditd.data.syscall in ("init_module", "finit_module")
Esta estrategia permitirá la detección de la carga del módulo del kernel, independientemente de la utilidad empleada para el evento de carga. En el ejemplo siguiente, vemos una detección positiva del rootkit de diamorfina .
Esta regla preconstruida está disponible aquí:
Guía adicional de ingeniería de detección de Linux a través de Auditd se presenta en la investigación de ingeniería de detección de Linux con Auditd.
Módulos fuera del árbol y sin signo
Otra señal de un LKM malicioso es la presencia de la bandera de "contaminación" del kernel. Cuando el núcleo detecta que se carga un módulo que no forma parte del árbol oficial del núcleo, carece de una firma válida o emplea una licencia no permisiva, marca el núcleo como "contaminado". Este es un mecanismo de integridad incorporado que indica que el núcleo está en un estado potencialmente no confiable. Un ejemplo de esto se muestra a continuación, donde se carga el módulo reveng_rtkit :
[ 2853.023215] reveng_rtkit: loading out-of-tree module taints kernel.
[ 2853.023219] reveng_rtkit: module license 'unspecified' taints kernel.
[ 2853.023220] Disabling lock debugging due to kernel taint
[ 2853.023297] reveng_rtkit: module verification failed: signature and/or required key missing - tainting kernel
El núcleo identifica el módulo como fuera del árbol, con una licencia no especificada y la ausencia de verificación criptográfica. Esto hace que el núcleo quede marcado como contaminado.
Para detectar este comportamiento, es necesario analizar e ingerir el registro del sistema y del núcleo. Una vez que la telemetría de registro del núcleo está disponible, la simple correspondencia de patrones o la detección basada en reglas pueden marcar estos eventos. La carga de módulos fuera del árbol puede detectar a través de:
event.dataset:"system.syslog" and process.name:"kernel" and
message:"loading out-of-tree module taints kernel."
Y una lógica de detección similar puede implementar para detectar la carga de módulos sin signo:
event.dataset:"system.syslog" and process.name:"kernel" and
message:"module verification failed: signature and/or required key missing - tainting kernel"
Usando la lógica de detección anterior, observamos verdaderos positivos en telemetría, intentando cargar la Singularidad:
Estas reglas están disponibles por defecto en:
La entrada del registro siempre mostrará el nombre del módulo que activó el evento, facilitando la triaje. Cuando el LKM no está presente en el sistema durante una comprobación manual provocada por esta alerta, puede indicar que el LKM se está ocultando.
Señales de apagada
Muchos rootkits (de código abierto) aprovechan señales kill , especialmente aquellas en rangos superiores no asignados (32+), como canales de comunicación encubiertos o disparadores para acciones maliciosas. Por ejemplo, un rootkit podría interceptar una señal de kill con números altos específicos (por ejemplo, kill -64 <pid>). Al recibir esta señal, la carga útil del rootkit podía configurar para elevar privilegios, ejecutar comandos, activar capacidades de ocultación o establecer una puerta trasera.
Para detectar esto, podemos aprovechar Auditd y crear una regla que recoja todas las señales de corte:
-a exit,always -F arch=b64 -S kill -k kill_rule
Los argumentos que se kill() presentan son kill(pid, sig). Podemos consultar a1 (la señal) para marcar cualquier señal de corte superior a 32.
process where event.action == "killed-pid" and
auditd.data.syscall == "kill" and auditd.data.a1 in (
"21", "22", "23", "24", "25", "26", "27", "28", "29", "2a",
"2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34",
"35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e",
"3f", "40", "41", "42", "43", "44", "45", "46", "47"
)
Analizar la llamada de kill() en busca de valores de señal inusuales mediante Auditd presenta una fuerte oportunidad de detección frente a rootkits que emplean estas señales, como se observa en técnicas como las empleadas por Diamorphine. Las reglas preconstruidas relacionadas con las muertes están disponibles en:
Segfaults
Por último, es esencial reconocer que los rootkits en espacio kernel son inherentemente frágiles. Los LKM suelen compilar para una versión y configuración específica del kernel. Un símbolo resuelto incorrectamente o una escritura de memoria desalineada pueden desencadenar un fallo de segmentación. Aunque estos fallos pueden no exponer inmediatamente la funcionalidad del rootkit, proporcionan señales forenses fuertes.
Para detectar esto, es necesario habilitar la recopilación de syslog en bruto. A partir de ahí, escribir una regla de detección para marcar mensajes segfault puede ayudar a identificar comportamientos maliciosos o inestabilidad del núcleo, ambos que merecen la investigación:
event.dataset:"system.syslog" and process.name:"kernel" and message:"segfault"
Esta regla de detección está disponible desde el primer momento como regla de bloque básico:
Combinar la visibilidad de carga de módulos a nivel de llamada syscall con contaminación del kernel, mensajes fuera del árbol, detección de señales de interrupción y alertas de segfault sienta las bases para una estrategia en capas para detectar rootkits basados en LKM.
Rootkits eBPF
Los rootkits eBPF explotan la funcionalidad legítima del subsistema BPF del núcleo de Linux. Los programas pueden cargar y conectarse dinámicamente usando utilidades como bpftool o mediante cargadores personalizados que abusan de las llamadas de sistema bpf() .
Detectar rootkits basados en eBPF requiere visibilidad tanto de bpf() llamadas syscalls como del uso de helpers sensibles para eBPF. Los indicadores clave implicados incluyen:
bpf(BPF_MAP_CREATE, ...)bpf(BPF_MAP_LOOKUP_ELEM, ...)bpf(BPF_MAP_UPDATE_ELEM, ...)bpf(BPF_PROG_LOAD, ...)bpf(BPF_PROG_ATTACH, ...)
Aprovechando Auditd, se puede crear una regla de auditoría donde a0 se aprovecha para especificar las llamadas de sistema BPF específicas de interés:
-a always,exit -F arch=b64 -S bpf -F a0=0 -k bpf_map_create
-a always,exit -F arch=b64 -S bpf -F a0=1 -k bpf_map_lookup_elem
-a always,exit -F arch=b64 -S bpf -F a0=2 -k bpf_map_update_elem
-a always,exit -F arch=b64 -S bpf -F a0=5 -k bpf_prog_load
-a always,exit -F arch=b64 -S bpf -F a0=8 -k bpf_prog_attach
Estos deben ajustar según el entorno para cerciorar que los programas benignos (por ejemplo, EDRs u otras herramientas de observabilidad) que aprovechan eBPF no generen ruido. Otra señal importante es el uso de funciones auxiliares de eBPF.
La función de ayuda bpf_probe_write_user
El ayudante de bpf_probe_write_user permite que los programas eBPF en espacio kernel escriban directamente en la memoria de usuario. Aunque está destinada a la depuración, esta función puede ser abusada por rootkits.
La detección sigue siendo un reto, pero los kernels de Linux suelen registrar el uso de ayudantes sensibles, como bpf_probe_write_user. La monitorización de estas entradas ofrece una oportunidad de detección, que requiere la recopilación bruta de syslogs y reglas específicas de detección, como las siguientes:
event.dataset:"system.syslog" and process.name:"kernel" and
message:"bpf_probe_write_user"
Esta regla alertará en cualquier entrada de registro del núcleo que indique el uso de bpf_probe_write_user. Aunque herramientas legítimas pueden invocarlo ocasionalmente, el uso inesperado o frecuente, especialmente junto con comportamientos sospechosos de procesos, merece investigación. El contexto, como el punto de unión del programa eBPF y el proceso de usuario, ayuda a la triaje. Esta regla de detección está disponible aquí:
A continuación, algunos ejemplos evidentes de verdaderos positivos detectados por esta lógica:
La regla se activa en nysm (un contenedor post-explotación sigiloso) y en boopkit (una puerta trasera eBPF de Linux).
io_uring rootkits
La investigación de ARMO (2025) introdujo una nueva técnica de evasión de defensa que aprovecha io_uring, un diseño para E/S asíncrona, para reducir la actividad observable de las llamadas de sistema y eludir la telemetría estándar. Esta técnica está limitada a las versiones del kernel 5.1 y superiores y evita el uso de ganchos. Aunque el método fue descubierto recientemente por investigadores de rootkits, sigue en desarrollo activo y sigue siendo relativamente inmaduro en cuanto a sus características. Un ejemplo de herramienta que aprovecha esta técnica es RingReaper. Los rootkits pueden hacer operaciones de archivo, red y otras operaciones de E/S por lotes mediante io_uring_enter(). A continuación se muestra un ejemplo de código.
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_read(sqe, fd, buf, size, offset);
io_uring_submit(&ring);
Estas llamadas se colocan en cola y envían una solicitud de lectura usando io_uring, evitando los caminos típicos de telemetría de las llamadas de sistema.
A diferencia del hooking en tabla syscall o la inyección basada en LD_PRELOAD, io_uring no es un mecanismo de entrega de rootkit en sí mismo, sino que proporciona un medio más furtivo para interactuar con el sistema de archivos y los dispositivos tras el compromiso. Aunque io_uring no puede ejecutar binarios directamente (debido a la falta de capacidades similares a execve), permite acciones maliciosas como la creación de archivos, enumeración y exfiltración de datos, minimizando la observabilidad.
Detectar rootkits basados en io_uringrequiere visibilidad sobre las llamadas de sistema que sustentan su funcionamiento, como io_uring_setup(), io_uring_enter()y io_uring_register().
Aunque las soluciones EDR pueden tener dificultades para captar los efectos indirectos de io_uring, Auditd puede rastrear estas llamadas de sistema directamente. La siguiente regla de auditoría recoge eventos relevantes para su análisis:
-a always,exit -F arch=b64 -k io_uring
-S io_uring_setup -S io_uring_enter -S io_uring_register
Sin embargo, esto solo expone el uso de la llamada sys, no el archivo u objeto específico al que se accede. La verdadera "magia" de io_uring ocurre en las librerías de usuario (por ejemplo, liburing), por lo que el análisis de los argumentos de syscall es esencial.
Por ejemplo, monitorizar io_uring_enter() con to_submit > 0 indica que se está agrupando una operación de E/S, mientras que alternar llamadas con min_complete > 0 señala un sondeo de finalización. Correlacionar con atributos del proceso (por ejemplo, UID=0, rutas inusuales como /dev/shm, /tmpo ubicaciones respaldadas por tmpfs) mejora la eficacia de la detección.
Un método práctico para rastrear io_uring actividad es mediante eBPF con herramientas como BCC, dirigidas a puntos de trazado como sys_enter_io_uring_enter. Esto permite a los analistas monitorizar el comportamiento de los procesos y los descriptores activos de archivos durante las operaciones de io_uring :
tracepoint:syscalls:sys_enter_io_uring_enter
{
printf("\nPID %d (%s) called io_uring_enter with fd=%d, to_submit=%d, min_complete=%d, flags=%d\n",
pid, comm, args->fd, args->to_submit, args->min_complete, args->flags);
printf("Manually inspect with: ls -l /proc/%d/fd\n", pid);
}
Para ilustrar esto, se probaron varias técnicas introducidas por RingReaper. El rastreo en tiempo real revela los descriptores de archivo en uso, ayudando a identificar actividades sospechosas como leer /run/utmp para detectar en qué usuarios están conectados:
La actividad de escribir en un archivo, en este ejemplo /root/test:
O listar la información del proceso a través de ps leyendo el contenido comm de cada PID activo:
Aunque la monitorización de llamadas de sistema revela io_uring uso, no revela directamente la naturaleza de la E/S sin una correlación adicional. io_uring es una técnica relativamente nueva y, por tanto, sigue siendo sigilosa; sin embargo, también tiene varias limitaciones. io_uring no puede ejecutar código directamente; sin embargo, los atacantes pueden abusar de las escrituras de archivos (por ejemplo, cron jobs, reglas udev) para lograr una ejecución retardada o indirecta, como demuestran las técnicas de persistencia empleadas por las familias de malware Reptile y Sedexp .
Técnicas de persistencia de rootkit
Los rootkits, ya sea en espacio de usuario o kernel, requieren algún tipo de persistencia para mantener funcionales durante reinicios o sesiones de usuario. Los métodos varían según el tipo y los privilegios del rootkit, pero suelen implicar abusar de archivos de configuración, gestión de servicios o scripts de inicialización del sistema.
Rootkits de Userland – persistencia de variables de entorno
Al usar LD_PRELOAD para activar un rootkit de usuario, el comportamiento no es persistente por defecto. Para lograr persistencia, los atacantes pueden modificar archivos de inicialización de shell (por ejemplo, ~/.bashrc, ~/.zshrco /etc/profile) para exportar variables de entorno como LD_PRELOAD o LD_LIBRARY_PATH. Estas modificaciones cercioran que cada nueva sesión de shell herede automáticamente el entorno necesario para activar el rootkit. Cabe destacar que estos archivos existen tanto para el contexto de usuario como para el de raíz. Por lo tanto, incluso los usuarios no privilegiados pueden introducir persistencia que secuestra el flujo de ejecución a su nivel de privilegios.
Para detectar esto, se puede usar una regla similar a la que se muestra a continuación:
file where event.action in ("rename", "creation") and file.path like (
// system-wide configurations
"/etc/profile", "/etc/profile.d/*", "/etc/bash.bashrc",
"/etc/bash.bash_logout", "/etc/zsh/*", "/etc/csh.cshrc",
"/etc/csh.login", "/etc/fish/config.fish", "/etc/ksh.kshrc",
// root and user configurations
"/home/*/.profile", "/home/*/.bashrc", "/home/*/.bash_login",
"/home/*/.bash_logout", "/home/*/.bash_profile", "/root/.profile",
"/root/.bashrc", "/root/.bash_login", "/root/.bash_logout",
"/root/.bash_profile", "/root/.bash_aliases", "/home/*/.bash_aliases",
"/home/*/.zprofile", "/home/*/.zshrc", "/root/.zprofile", "/root/.zshrc",
"/home/*/.cshrc", "/home/*/.login", "/home/*/.logout", "/root/.cshrc",
"/root/.login", "/root/.logout", "/home/*/.config/fish/config.fish",
"/root/.config/fish/config.fish", "/home/*/.kshrc", "/root/.kshrc"
)
Dependiendo del entorno, varias de estas conchas pueden no estar en uso, y se puede crear una regla de detección más adaptada, centrada solo en bash o zsh, por ejemplo. La lógica completa de detección que emplea Elastic Defend y la integración File Integrity Monitoring de Elastic puede encontrar aquí:
Para más información, se presenta un desglose completo de esta técnica de persistencia, incluyendo varias otras formas de detectar su abuso, en Linux Detection Engineering - Una introducción a los mecanismos de persistencia.
Rootkits de usuario: persistencia basada en la configuración
Modificar los archivos de configuración /etc/ld.so.preload, /etc/ld.so.confo /etc/ld.so.conf.d/ permite que los rootkits persistan globalmente entre usuarios y sesiones (más información sobre este vector de persistencia está disponible en Linux Detection Engineering - A Continuation on Persistence Mechanisms). Una vez escrito, el enlazador dinámico continuará inyectando el objeto compartido malicioso a menos que estas configuraciones se reviertan explícitamente. Estos métodos son persistentes por diseño. Las estrategias de detección reflejan las descritas en la sección anterior y se basan en monitorizar eventos de creación o modificación de archivos en estas rutas.
Kits raíz en espacio kernel – persistencia LKM
Al igual que los rootkits de userland, los LKMs no son persistentes por defecto. Un atacante debe configurar explícitamente el sistema para que recargue el módulo malicioso al arrancar. Esto se consigue típicamente aprovechando mecanismos legítimos de carga de módulos del kernel:
Archivo de módulos: modules
Este archivo lista módulos del núcleo que deben cargar automáticamente durante el arranque del sistema. Agregar un nombre de archivo .ko malicioso aquí cerciora que modprobe lo cargue al arrancar. Este archivo está ubicado en /etc/modules.
Directorio de configuración para modprobe
Este directorio contiene archivos de configuración para la utilidad modprobe . Los atacantes pueden usar aliasing para disfrazar su rootkit o cargarlo automáticamente cuando ocurre un evento específico del núcleo (por ejemplo, cuando se sondea un dispositivo). Estos archivos de configuración de modprobe se encuentran en /etc/modprobe.d/, /run/modprobe.d/, /usr/local/lib/modprobe.d/, /usr/lib/modprobe.d/y /lib/modprobe.d/.
Configura los módulos del núcleo para que se carguen al arrancar: modules-load.d
Estos archivos de configuración especifican qué módulos cargar al principio del proceso de arranque y se encuentran en /etc/modules-load.d/, /run/modules-load.d/, /usr/local/lib/modules-load.d/y /usr/lib/modules-load.d/.
Para detectar todas las técnicas de persistencia mencionadas anteriormente, se puede crear una regla de detección similar a la siguiente:
file where event.action in ("rename", "creation") and file.path like (
"/etc/modules",
"/etc/modprobe.d/*",
"/run/modprobe.d/*",
"/usr/local/lib/modprobe.d/*",
"/usr/lib/modprobe.d/*",
"/lib/modprobe.d/*",
"/etc/modules-load.d/*",
"/run/modules-load.d/*",
"/usr/local/lib/modules-load.d/*",
"/usr/lib/modules-load.d/*"
)
Esta regla preconstruida que combina todos los caminos listados anteriormente en una sola regla de detección está disponible aquí:
Un ejemplo de rootkit que despliega automáticamente la persistencia usando este método es Singularity. Dentro de su despliegue, se ejecutan los siguientes comandos:
read -p "Enter the module name (without .ko): " MODULE_NAME
CONF_DIR="/etc/modules-load.d"
mkdir -p "$CONF_DIR"
echo "[*] Setting up persistence..."
echo "$MODULE_NAME" > "$CONF_DIR/$MODULE_NAME.conf"
Por defecto, esto significa que singularity.conf se creará como una nueva entrada bajo /etc/modules-load.d/. Al analizar la telemetría, detectamos esta técnica simplemente monitorizando la creación de nuevos archivos:
Estos directorios también se emplean para LKMs benignos y, por tanto, serán propensos a falsos positivos. Otro método de persistencia implica usar una técnica basada en disparos o calendarios para cargar el módulo del núcleo ejecutando el cargador.
Persistencia basada en Udev – Ejemplo de reptiles
Un método de persistencia menos común pero poderosa implica abusar de udev, el gestor de dispositivos Linux que gestiona eventos dinámicos de dispositivos. Udev ejecuta scripts basados en reglas cuando se cumplen condiciones específicas. Un desglose completo de esta técnica se presenta en Linux Detection Engineering - A Sequel on Persistence Mechanisms. El rootkit de Reptile demuestra esta técnica instalando una regla maliciosa de udev bajo /etc/udev/rules.d/:
ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile"
Esta regla probablemente se inspiró en el malware Sedexp descubierto por Levelblue. Así es como funciona la regla:
ACTION=="add": Se activa cuando se agrega un nuevo dispositivo al sistema.ENV{MAJOR}=="1": Empareja dispositivos con número mayor "1", típicamente dispositivos relacionados con la memoria como/dev/mem,/dev/null,/dev/zeroy/dev/random.ENV{MINOR}=="8": Reduce aún más la condición a/dev/random.RUN+="/lib/udev/reptile": Ejecuta el binario Reptile loader cuando se detecta el dispositivo anterior.
Esta regla establece la persistencia al activar la ejecución de un binario cargador cada vez que se carga el dispositivo /dev/random . Como generador de números aleatorios ampliamente empleado, esencial para numerosas aplicaciones de sistema y el proceso de arranque, este método es eficaz. La activación solo ocurre en eventos específicos del dispositivo, y la ejecución se realiza con privilegios root a través del udev daemon. Para detectar esta técnica, se puede crear una regla de detección similar a la siguiente:
file where event.action in ("rename", "creation") and file.extension == "rules" and file.path like (
"/lib/udev/*",
"/etc/udev/rules.d/*",
"/usr/lib/udev/rules.d/*",
"/run/udev/rules.d/*",
"/usr/local/lib/udev/rules.d/*"
)
Cubrimos la creación y modificación de estos archivos mediante las siguientes reglas predefinidas:
Mecanismos generales de persistencia
Además de las rutas de carga de módulos del núcleo, los atacantes pueden recurrir a métodos de persistencia más genéricos de Linux para recargar rootkits de usuario o en espacio de núcleo a través del cargador:
Systemd: Crear o agregar a un servicio/temporizador bajo cualquier directorio (por ejemplo, /etc/systemd/system/) que soporte el cargador al arrancar.
file where event.action in ("rename", "creation") and file.path like (
"/etc/systemd/system/*", "/etc/systemd/user/*",
"/usr/local/lib/systemd/system/*", "/lib/systemd/system/*",
"/usr/lib/systemd/system/*", "/usr/lib/systemd/user/*",
"/home/*.config/systemd/user/*", "/home/*.local/share/systemd/user/*",
"/root/.config/systemd/user/*", "/root/.local/share/systemd/user/*"
) and file.extension in ("service", "timer")
Scripts de inicialización: Crear o agregar a un script malicioso de control de ejecución (/etc/rc.local), SysVinit (/etc/init.d/) o Upstart (/etc/init/).
file where event.action in ("creation", "rename") and
file.path like (
"/etc/init.d/*", "/etc/init/*", "/etc/rc.local", "/etc/rc.common"
)
Trabajos cron: Crear o agregar a un trabajo cron que permita la ejecución repetida de un cargador.
file where event.action in ("rename", "creation") and
file.path like (
"/etc/cron.allow", "/etc/cron.deny", "/etc/cron.d/*",
"/etc/cron.hourly/*", "/etc/cron.daily/*", "/etc/cron.weekly/*",
"/etc/cron.monthly/*", "/etc/crontab", "/var/spool/cron/crontabs/*",
"/var/spool/anacron/*"
)
Sudoers: Crear o agregar a una configuración maliciosa de sudoers como puerta trasera.
file where event.type in ("creation", "change") and
file.path like "/etc/sudoers*"
Estos métodos son ampliamente empleados, flexibles y a menudo más fáciles de detectar mediante telemetría de línea de proceso o modificación de archivos.
La lista de reglas de detección predefinidas para detectar estas técnicas de persistencia se muestra a continuación:
- Systemd Service Created
- Systemd Timer Created
- System V Init Script Created
- rc.local/rc.common File Creation
- Cron Job Created or Modified
- Actividad de archivos de Sudoers
- Persistencia potencial mediante modificación de archivos
Técnicas de evasión defensiva en rootkit
Aunque los rootkits son, por definición, herramientas para evadir defensas, muchos implementan técnicas adicionales para permanecer indetectables durante y luego del despliegue. Estos métodos están diseñados para evitar la visibilidad en los registros, evadir agentes de detección de endpoints e interferir con los flujos de trabajo comunes de investigación. La siguiente sección describe las técnicas clave de evasión empleadas por los rootkits modernos de Linux, categorizadas según sus objetivos operativos.
Intentos de mantener sigilosos durante el despliegue
Los actores maliciosos suelen centrar en tácticas de ejecución sigilosa desde una perspectiva forense. Por ejemplo, un actor de amenazas puede almacenar y ejecutar sus cargas útiles desde el directorio de memoria compartida /dev/shm , ya que este es un sistema de archivos completamente virtual y, por tanto, las cargas útiles nunca tocarán el disco. Esto es genial desde el punto de vista forense, pero como ingenieros de detección conductual, encontramos este comportamiento muy sospechoso y poco común.
Como ejemplo, aunque no es un actor de amenaza real, el autor de Singularity sugiere el siguiente método de despliegue:
cd /dev/shm
git clone https://github.com/MatheuZSecurity/Singularity
cd Singularity
sudo bash setup.sh
sudo bash scripts/x.sh
Hay varios cables trampa que deben instalar para detectar este comportamiento con una tasa de falsos positivos casi nula, empezando por clonar un repositorio de GitHub en el directorio /dev/shm .
sequence by process.entity_id, host.id with maxspan=10s
[process where event.type == "start" and event.action == "exec" and (
(process.name == "git" and process.args == "clone") or
(
process.name in ("wget", "curl") and
process.command_line like~ "*github*"
)
)]
[file where event.type == "creation" and
file.path like ("/tmp/*", "/var/tmp/*", "/dev/shm/*")]
Clonar directorios en /tmp y /var/tmp es común, por lo que estos podrían eliminar de esta regla en entornos donde clonar repositorios es habitual. Sin embargo, la misma actividad en /dev/shmes muy poco común.
El script setup.sh , llamado por el cargador, continúa compilando el LKM en un subdirectorio /dev/shm/ . Los actores reales de amenazas generalmente no se reúnen en el propio anfitrión, sin embargo, no es raro que esto ocurra de cualquier manera.
sequence with maxspan=10s
[process where event.type == "start" and event.action == "exec" and
process.name like (
"*gcc*", "*g++*", "c++", "cc", "c99", "c89", "cc1*", "clang*",
"musl-clang", "tcc", "zig", "ccache", "distcc"
)] as event0
[file where event.action == "creation" and file.path like "/dev/shm/*" and
process.name like (
"ld", "ld.*", "lld", "ld.lld", "mold", "collect2", "*-linux-gnu-ld*",
"*-pc-linux-gnu-ld*"
) and
stringcontains~(event0.process.command_line, file.name)]
Esta lógica de endpoint detecta la ejecución de un compilador, seguida de que el enlazador crea un archivo en /dev/shm (o un subdirectorio).
Y finalmente, dado que clonó todo el repositorio en /dev/shm, y ejecutó setup.sh y x.sh, observaremos la ejecución de procesos desde el directorio de memoria compartida, lo cual es poco común en la mayoría de los entornos:
process where event.type == "start" and event.action == "exec" and
process.executable like ("/dev/shm/*", "/run/shm/*")
Estas reglas están disponibles en los repositorios de reglas de detección y protecciones-artefactos:
- Repositorio git o descarga de archivos en directorio sospechoso
- Compilación de Linux en el directorio sospechoso
- Binary Executed from Shared Memory Directory
Disfrazar de procesos legítimos
Para evitar el escrutinio durante la enumeración de procesos o la monitorización del sistema, los rootkits suelen renombrar sus procesos e hilos para que coincidan con componentes benignos del sistema. Disfraces comunes incluyen:
kworker,migration, orcu_sched(hilos del núcleo)sshd,systemd,dbus-daemon, obash(demonios de las tierras usuarias)
Estos nombres se eligen para integrar con la salida de herramientas como ps, topo htop, dificultando la detección manual. Ejemplos de rootkits que aprovechan esta técnica incluyen Reptile y PUMAKIT. Reptile genera eventos de red inusuales a través de kworker al inicializar:
network where event.type == "start" and event.action == "connection_attempted"
and process.name like~ ("kworker*", "kthreadd") and not (
destination.ip == null or
destination.ip == "0.0.0.0" or
cidrmatch(
destination.ip,
"10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12",
"192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32",
"192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24",
"192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24",
"224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15",
"198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1",
"FE80::/10", "FF00::/8"
)
)
El siguiente ejemplo muestra la funcionalidad de port knocking de Reptile, donde el kernel thread se bifurca, cambia su ID de sesión a 0 y configura la conexión de red:
También se observa que Reptile aprovecha el mismo proceso kworker para crear archivos:
file where event.type == "creation" and
process.name like~ ("kworker*", "kthreadd")
PUMAKIT genera hilos kernel para ejecutar comandos de userland a través de kthreadd, pero se observó una actividad similar en un proceso kworker en otros rootkits:
process where event.type == "start" and event.action == "exec" and
process.parent.name like~ ("kworker*", "kthreadd") and
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and
process.args == "-c"
Estas reglas kworker y kthreadd pueden generar falsos positivos debido a las operaciones internas del núcleo de Linux. Estos pueden excluir fácilmente según el entorno, o se pueden agregar argumentos adicionales de línea de comandos a la lógica.
Estas reglas están disponibles en los repositorios de reglas de detección y protecciones-artefactos:
- Actividad de red detectada mediante Kworker
- Creación de archivos sospechosos vía Kworker
- Elevación sospechosa del UID Kworker
- Ejecución de comandos de shell mediante Kworker
Además, procesos maliciosos, como un dropper inicial o un mecanismo de persistencia, pueden hacer pasar por hilos del kernel y aprovechar una función integrada de shell para hacerlo. Aprovechando el comando exec -a , cualquier proceso puede generar con un nombre elegido por el atacante. El enmascaramiento de procesos del kernel puede detectar mediante la siguiente consulta de detección:
process where event.type == "start" and event.action == "exec" and
process.command_line like "[*]" and process.args_count == 1
Este comportamiento se muestra a continuación, donde varios malware intentaron hacer pasar por un kernel worker o un proceso de servicio sitio web.
Esta técnica también es comúnmente abusada por actores maliciosos que aprovechan el kit de herramientas The Hacker's Choice (THC), especialmente al desplegar gsocket.
Las reglas relacionadas con el enmascaramiento de kernel, y el enmascaramiento vía exec -a en general, están disponibles en el repositorio de artefactos de protecciones:
- Proceso que se hace pasar por Proceso del Núcleo
- Enmascaramiento de procesos potenciales a través de Exec
Otra técnica que se observa en libertad, y también en Horse Pill, es el uso de prctl para pisar su nombre de proceso. Para cerciorar que esta telemetría esté disponible, se puede crear una regla auditada personalizada:
-a exit,always -F arch=b64 -S prctl -k prctl_detection
Y acompañado de la siguiente lógica de detección:
process where host.os.type == "linux" and auditd.data.syscall == "prctl" and
auditd.data.a0 == "f"
Permitirá la detección de esta técnica. En la captura de pantalla de abajo, podemos ver ejemplos de telemetría de esta técnica empleada, donde el process.executable es un disparate y prctl se usará para disfrazar el sistema como un proceso legítimo.
Esta regla, incluidas sus instrucciones de configuración, está disponible aquí:
Aunque existen muchas formas de disfrazar, estas son las más comunes que se observan.
Limpieza de registros y auditorías
Muchos rootkits incluyen rutinas que borran rastros de su instalación o actividad de los registros. Una de estas técnicas es borrar el historial de conchas de la víctima. Esto puede detectar de dos maneras. Un método es detectar la eliminación del archivo de historial de la shell:
file where event.type == "deletion" and file.name in (
".bash_history", ".zsh_history", ".sh_history", ".ksh_history",
".history", ".csh_history", ".tcsh_history", "fish_history"
)
El segundo método es detectar ejecuciones de procesos con argumentos de línea de comandos relacionados con el borrado del historial del shell:
process where event.type == "start" and event.action == "exec" and (
(
process.args in ("rm", "echo") or
(
process.args == "ln" and process.args == "-sf" and
process.args == "/dev/null"
) or
(process.args == "truncate" and process.args == "-s0")
)
and process.command_line like~ (
"*.bash_history*", "*.zsh_history*", "*.sh_history*", "*.ksh_history*",
"*.history*", "*.csh_history*", "*.tcsh_history*", "*fish_history*"
)
) or
(process.name == "history" and process.args == "-c") or
(
process.args == "export" and
process.args like~ ("HISTFILE=/dev/null", "HISTFILESIZE=0")
) or
(process.args == "unset" and process.args like~ "HISTFILE") or
(process.args == "set" and process.args == "history" and process.args == "+o")
Tener activas ambas reglas de detección (proceso y archivo) permitirá una estrategia de defensa en profundidad más robusta.
Al cargar, los rootkits pueden contaminar el kernel o generar mensajes fuera del árbol que pueden identificar al analizar syslog y kernel logs. Para borrar sus rastros, los rootkits pueden eliminar estos archivos de registro:
file where event.type == "deletion" and file.path in (
"/var/log/syslog", "/var/log/messages", "/var/log/secure",
"/var/log/auth.log", "/var/log/boot.log", "/var/log/kern.log",
"/var/log/dmesg"
)
O borrar el búfer de mensajes del kernel a través de dmesg:
process where event.type == "start" and event.action == "exec" and
process.name == "dmesg" and process.args in ("-c", "--clear")
Un ejemplo de rootkit que limpia automáticamente el dmesg es el rootkit bds, que se carga ejecutando /opt/bds_elf/bds_start.sh:
Otra forma de borrar estos registros es usando journalctl:
process where event.type == "start" and event.action == "exec" and
process.name == "journalctl" and
process.args like ("--vacuum-time=*", "--vacuum-size=*", "--vacuum-files=*")
Esta es una técnica que fue empleada por Singularidad:
Otra técnica empleada por el script loader de Singularity es eliminar todos los archivos asociados al rootkit en caso de que no pueda cargar, o una vez que complete su proceso de carga. Para una eliminación más completa, el autor eligió el uso de shred en lugar de rm. rm (eliminar) simplemente elimina el puntero del archivo, haciéndolo rápido pero permitiendo la recuperación de datos. shred sobreescribir los datos del archivo varias veces con datos aleatorios, cerciorando que no puedan recuperar. Esto hace que la eliminación sea más permanente pero, al mismo tiempo, más ruidosa desde el punto de vista de la detección de comportamiento, ya que shred no se usa comúnmente en la mayoría de los sistemas Linux.
process where event.type == "start" and event.action == "exec" and
process.name == "shred" and (
// Any short-flag cluster containing at least one of u/z,
// and containing no extra "-" after the first one
process.args regex~ "-[^-]*[uz][^-]*" or
process.args in ("--remove", "--zero")
) and
not process.parent.name == "logrotate"
La regex anterior cerciora que los intentos de evadir la detección combinando o modificando banderas se vuelvan más difíciles. A continuación se muestra un ejemplo de Singularity buscando cualquier archivo relacionado con su despliegue y triturándolos:
Estas técnicas de eliminación de archivos y registros pueden detectar mediante varias reglas de detección listas para usar:
- System Log File Deletion
- Attempt to Clear Kernel Ring Buffer
- Intento de borrar registros mediante Journalctl
- File Deletion via Shred
Una vez que un rootkit termina de borrar sus rastros, puede hacer un timetómetro de los archivos que alteró para cerciorar de que no quede ninguna pista de modificación de archivo:
process where event.type == "start" and event.action == "exec" and
process.name == "touch" and
process.args like (
"-t*", "-d*", "-a*", "-m*", "-r*", "--date=*", "--reference=*", "--time=*"
)
Un ejemplo de esto se muestra aquí, donde un actor de amenaza emplea la marca de tiempo del archivo /etc/ld.so.conf como tiempo de referencia para los archivos en la unidad /dev/shm en un intento de integrar:
Esta es una técnica para la que agregamos cobertura tanto mediante reglas de detección como artefactos de protección:
Aunque siempre hay más técnicas que no discutimos en esta investigación, estamos seguros de que esta investigación ayudará a profundizar en la comprensión del paisaje de rootkits de Linux y su ingeniería de detección.
Técnicas de prevención de rootkit
Prevenir rootkits en Linux requiere una estrategia de defensa en capas que combine el endurecimiento del núcleo y del usuario, un estricto control de acceso y una monitorización continua. Los marcos obligatorios de control de acceso, como SELinux y AppArmor, limitan el comportamiento de los procesos y las oportunidades de persistencia en la zona de usuario. Mientras tanto, las técnicas de endurecimiento del núcleo, incluyendo Lockdown Mode, KASLR, SMEP/SMAP y herramientas como LKRG, mitigan el riesgo de compromiso a nivel de núcleo. Restringir el uso de módulos del núcleo deshabilitando la carga dinámica o la aplicación de la firma de módulos reduce aún más los vectores comunes para el despliegue de rootkits.
La visibilidad del comportamiento malicioso se mejora mediante Auditd y monitorización de la integridad de archivos para llamadas de sistema y actividad de archivos, así como mediante soluciones EDR que identifican y previenen comportamientos sospechosos en tiempo de ejecución. La seguridad se refuerza aún más minimizando los privilegios de proceso mediante seccomp-bpf, capacidades Linux y el LSM sin vía terrestre, restringiendo así el acceso a llamadas de sistema y las interacciones con el sistema de archivos.
Las actualizaciones puntuales del kernel y del software, apoyadas por parches en tiempo real cuando sea necesario, cierran vulnerabilidades conocidas antes de que sean explotadas. Además, las configuraciones del sistema de archivos y del dispositivo deben reforzar volviendo a montar sistemas de archivos sensibles con flags restrictivos y deshabilitando el acceso a interfaces de memoria del núcleo, como /dev/mem y /proc/kallsyms.
Ningún control único puede impedir los rootkits por completo. Una defensa en capas, que combine endurecimiento de configuración, detección estática y dinámica, y preparación forense, sigue siendo esencial.
Conclusión
En la primera parte de este serial, examinamos cómo operan internamente los rootkits de Linux, explorando su evolución, taxonomía y técnicas para manipular el espacio de usuario y el espacio del núcleo. En esta segunda parte, trasladamos ese conocimiento a estrategias prácticas de detección, centrándonos en las señales conductuales y la telemetría en tiempo de ejecución que exponen la actividad de rootkits.
Aunque el malware de Windows sigue dominando el foco de los proveedores comerciales de seguridad y las comunidades de investigación de amenazas, Linux sigue siendo relativamente poco investigado, a pesar de alimentar la mayoría de la infraestructura en la nube, entornos informáticos de alto rendimiento y servicios de Internet del mundo.
Nuestro análisis destaca que los rootkits de Linux están evolucionando. La creciente adopción de tecnologías como eBPF, io_uringy cargas de trabajo Linux contenedorizadas introduce nuevas superficies de ataque que aún no están bien comprendidas ni ampliamente protegidas.
Animamos a la comunidad de seguridad a:
- Invierte en ingeniería de detección centrada en Linux tanto desde ángulos estáticos como dinámicos.
- Comparte abiertamente los hallazgos de la investigación, pruebas de concepto y estrategias de detección para acelerar el conocimiento colectivo entre los defensores.
- Colaborar entre proveedores, el mundo académico e industria para llevar la defensa de rootkit de Linux hacia el mismo nivel de madurez alcanzado en Windows.
Solo mejorando colectivamente la visibilidad, la detección y las capacidades de respuesta podrán los defensores mantener por delante de este panorama de amenazas sigiloso y en rápida evolución.
