Malwares dirigidos contra los sistemas Linux
Introducción
Linux es un sistema operativo de código abierto. El nombre Linux es un término equivocado, ya que Linux solo es en realidad el núcleo del sistema operativo. El software que rodea al núcleo de Linux se llama GNU y a veces se utiliza el nombre GNU/Linux. Fue creado en 1991 por Linus Torvalds. El código fuente del núcleo está disponible en la siguiente dirección: https://github.com/torvalds/linux
Linux se puede instalar como una distribución. Una distribución contiene un núcleo Linux, así como software GNU y un conjunto de software de terceros que forman un sistema operativo funcional. Las distribuciones pueden contener solo software libre o también software propietario. Esta es una elección que hacen los encargados de mantener la distribución. Existen distribuciones comerciales y distribuciones basadas en una comunidad de mantenedores voluntarios. Por ejemplo, Red Hat Enterprise Linux (RHEL) es una distribución comercial, mantenida por una empresa y Debian es una distribución libre, mantenida por una comunidad de voluntarios.
Históricamente, Linux se ha utilizado en servidores, aunque también existen versiones de escritorio de este sistema operativo. Durante muchos años, existió la leyenda urbana de que el malware no existía en Linux. Obviamente, esto no es cierto. Este capítulo presentará...
Sistema operativo Linux
1. Historia
En los años 70, AT&T desarrolló el sistema Unix. Este sistema era propietario y los investigadores de la Universidad de California lo modificaron y distribuyeron una versión bajo el nombre de BSD (Berkeley Software Distribution). En la década de 1980, Richard Stallman desarrolló su proyecto para un sistema operativo libre compatible con Unix, al que llamó GNU. GNU trabajó en su propio núcleo Hurd, pero este no se publicó hasta años más tarde y no fue adoptado por la comunidad. Sin embargo, Linus Torvalds desarrolló un núcleo libre que también era compatible con Unix: Linux. GNU/Linux nació, por tanto, de dos proyectos complementarios. La primera versión del núcleo Linux (0.0.1) aún está disponible en línea: https://github.com/zavg/linux-0.01.
Las primeras distribuciones de Linux aparecieron en los años noventa. Permiten instalar un sistema operativo coherente y funcional. Estas distribuciones proporcionan el núcleo Linux, herramientas GNU, software de terceros (a veces gratuito, a veces comercial), manuales de usuario y soporte telefónico o por correo electrónico. Existen dos tipos principales de distribución:
-
distribuciones comerciales como Red Hat Enterprise Linux (RHEL), SUSE Linux Enterprise y Ubuntu,
-
distribuciones comunitarias como Debian, Fedora y openSUSE.
Desde 2016, Linux también es compatible con Windows 10 y 11 gracias a Windows Subsystem for Linux (WSL). La versión más reciente de WSL utiliza Hyper-V para ejecutar el sistema operativo Linux. WSL puede ejecutar binarios Linux y aplicaciones gráficas con la ayuda de un servidor X.
Linux es multiarquitectura y funciona en x86, x86_64, Motorola, DEC, Alpha, PowerPC, ARM, RISC, MIPS y SPARC. Por tanto, es un sistema operativo que se utiliza con frecuencia en sistemas embebidos y terminales de red, como los routers. En este capítulo, nos limitaremos a las versiones Intel de este sistema operativo.
La versión actual del kernel Linux es la 6.13.
2. Arquitectura
Como el sistema operativo Linux es de código abierto, existe una gran cantidad de documentación y su funcionamiento interno es público. El sistema operativo se divide en dos espacios: el del usuario, donde se ejecutan las aplicaciones y el del núcleo, que gestiona...
Vectores de infección
1. Comprometer al sistema
Las técnicas para comprometer un sistema Linux son variadas. En el caso del uso ofimático, los vectores de infección son similares a los de otros sistemas operativos. Se puede utilizar un archivo adjunto malicioso, la instalación de una aplicación comprometida o una vulnerabilidad.
Los gestores de paquetes y las librerías de terceros son interesantes vectores de infección específicos de Linux. El lenguaje de desarrollo Python se utiliza ampliamente en Linux y se instala por defecto en la mayoría de las distribuciones. El sistema de paquetes integrado de Python se denomina PyPI (Python Package Index) y descarga automáticamente las dependencias necesarias para una aplicación Python. En diciembre de 2023, los investigadores de ESET descubrieron que más de cien librerías maliciosas estaban disponibles en este gestor de paquetes. Los atacantes utilizaron copias de librerías legítimas populares con un error tipográfico. Por ejemplo, estaba disponible una copia de la librería HexColors, llamada HexColurs por el atacante. Una simple errata al instalar la librería desplegaba esta copia, así como el código malicioso incrustado. Algunas librerías maliciosas se descargaron más de 10.000 veces. En esta campaña, el objetivo del código malicioso era poder ejecutar...
Formato ELF
Los binarios de Linux están en formato ELF (Executable and Linkable Format). Este formato fue creado en 1999 y es utilizado no solo por Linux, sino también por otros sistemas operativos como BSD y consolas como PlayStation y Nintendo DS.
Los archivos ELF tienen la siguiente cabecera:
struct Elf32_Ehdr {
unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes
Elf32_Half e_type; // Type of file (see ET_* below)
Elf32_Half e_machine; // Required architecture for this file (see EM_*)
Elf32_Word e_version; // Must be equal to 1
Elf32_Addr e_entry; // Address to jump to in order to start program
Elf32_Off e_phoff; // Program header table's file offset, in bytes
Elf32_Off e_shoff; // Section header table's file offset, in bytes
Elf32_Word e_flags; // Processor-specific flags
Elf32_Half e_ehsize; // Size of ELF header, in bytes
Elf32_Half e_phentsize; // Size of an entry in the program header table
Elf32_Half e_phnum; // Number of entries in the program header table
Elf32_Half e_shentsize; // Size of an entry in the section header table
Elf32_Half e_shnum; // Number of entries in the section header table
Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table
};
El comando readelf se puede utilizar para ver la cabecera de un archivo:
linux@DESKTOP:~$ readelf -h /bin/ls
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's...Técnicas utilizadas por el malware para Linux
1. Persistencia
En la mayoría de los casos, el malware quiere ser persistente y ejecutarse cuando se reinicia el sistema. Hay muchas formas de conseguirlo. Los servicios descritos anteriormente se utilizan con frecuencia. Pero el atacante debe ser un administrador para crearlos y administrarlos. Existen otros trucos para ejecutar binarios automáticamente en cuanto un usuario inicia sesión en el sistema comprometido sin necesidad de derechos de administrador.
Cuando un usuario inicia sesión o abre un terminal, se lanza una shell. El shell es el binario que proporciona acceso a la línea de comandos en Linux. Existen diferentes tipos de shell, como sh, bash o zsh. Todas las shell cargan un archivo de configuración cuando se ejecutan. Por ejemplo, bash carga automáticamente el archivo .bashrc del directorio del usuario. Este archivo puede contener variables de entorno que necesitan ser configuradas, pero también puede ser utilizado por el atacante para ejecutar un binario malicioso.
El atacante también puede definir alias en este archivo de configuración. El siguiente comando reemplaza al comando ls con una versión maliciosa almacenada en /tmp/:
linux@DESKTOP:~$ alias ls='/tmp/ls'
Obviamente, el malware tiene que funcionar como el comando ls para engañar al usuario. Dado que GNU es de código abierto, es fácil descargar el código fuente del binario y modificarlo para añadir código malicioso conservando la funcionalidad del comando ls.
El atacante también puede modificar la variable de entorno PATH para ejecutar la versión maliciosa de ls. Esta variable se utiliza en Unix para configurar las rutas que contienen binarios ejecutables. Aquí tiene un ejemplo de PATH:
linux@DESKTOP:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:
Cuando se ejecuta un comando, como ls, el intérprete de comandos recorrerá uno a uno los directorios de PATH hasta encontrar el binario. En nuestro caso, ls está en /bin:
linux@DESKTOP:~$ which ls
/bin/ls
Sin embargo, es posible poner /tmp/ primero en el PATH y si un binario ls está en /tmp/, se ejecutará primero:
linux@DESKTOP:~$ export PATH=/tmp:$PATH
linux@DESKTOP:~$ which ls
/tmp/ls
Un atacante puede utilizar estas características...
Análisis de malware
1. Creación del laboratorio de análisis
Al igual que con los otros sistemas operativos mencionados en este libro, es importante tener un laboratorio de análisis en una máquina virtual para no ejecutar código malicioso en su propia máquina.
El malware no se debe ejecutar en Windows Subsystem for Linux (WSL). La partición Linux tiene acceso al sistema anfitrión, los entornos no están aislados. El ransomware de Linux ejecutado en WSL podría cifrar archivos en el sistema anfitrión Windows.
Al igual que en el análisis del malware de Windows, utilizaremos el hipervisor gratuito VirtualBox, que se puede descargar de https://www.virtualbox.org/wiki/Downloads. Como Linux es gratuito y de código abierto, no hay especificaciones para crear la máquina virtual. La creación de máquinas estándar funcionará perfectamente.
Lo único que hay que elegir es qué distribución de Linux instalar. Ubuntu es una opción estándar que permitirá realizar análisis. Existe una distribución especializada en el análisis de malware: REMnux. Las imágenes de VirtualBox se pueden descargar gratuitamente en la siguiente dirección: https://docs.remnux.org/install-distro/get-virtual-appliance. El archivo de imagen se puede importar directamente a VirtualBox.
La distribución REMnux tiene la ventaja de contar con herramientas de análisis preinstaladas:
-
herramientas de análisis estático y dinámico de binarios y scripts,
-
herramientas de análisis de memoria,
-
herramientas de análisis de redes,
-
herramientas de análisis de documentos,
-
herramientas diversas.
La lista completa está disponible en la documentación de REMnux en la siguiente dirección: https://docs.remnux.org/. Todas las herramientas presentadas en este capítulo están preinstaladas en REMnux.
2. Análisis estático
Ghidra soporta archivos ELF. Ghidra es una herramienta gratuita de análisis estático que se describió en el capítulo Ingeniería inversa. Se puede descargar de https://ghidra-sre.org/. No hay diferencias significativas entre utilizar Ghidra para analizar un binario de Windows o uno de Linux.
En Linux, también se puede utilizar el comando objdump para obtener...
Caso práctico de una webshell
Para este primer caso práctico, vamos a analizar una webshell desplegada a través de una vulnerabilidad en un servidor de aplicaciones Tomcat. Tomcat es un servidor de aplicaciones de código abierto para ejecutar aplicaciones Java con la extensión .jsp. La webshell es utilizada por el atacante para controlar el servidor comprometido mediante peticiones web específicas.
A continuación, se muestra una captura de pantalla del archivo malicioso desplegado en este Tomcat vulnerable:

El código está en Java y no está ofuscado. Tomcat ofrece interfaces web, por lo que este código Java se ejecuta en el contexto de una petición web.
La primera sección, de la línea 1 a la 9, sobrecarga la clase ClassLoader, que carga dinámicamente una clase Java.
La segunda sección, de la línea 12 a la 17, comprueba si se envía un parámetro pass durante la petición web. Si la variable está presente, el código malicioso genera una contraseña aleatoria (una clave) utilizando UUID.randomUUID(). Esta clave se muestra en la página web al atacante y se almacena en la sesión con el valor u.
La última sección, de la línea 18 a la 24, se utiliza para descifrar el contenido de una petición POST. La clave AES utilizada para descifrar el contenido de la petición es la generada previamente...
Caso práctico del malware Sysupdate
Aquí está el md5 del archivo Sysupdate utilizado en este caso de estudio: f1009ec318797d6541ad440545062082.
Este es el comienzo del pseudocódigo de Sysupdate.

Esta parte del código comprueba los parámetros de la línea de comandos. El malware soporta los siguientes argumentos: -launch, -run, -r, -i y -f. Por ejemplo, si la opción -launch está presente, se ejecuta la función FUN_0040c5ae() (línea 24). A continuación, se muestra el pseudocódigo de esta función:

En la línea 10 vemos que el archivo /etc/rc.d/rc.local está abierto. Este archivo es un servicio de Linux. A continuación, se escriben varias líneas en este archivo (utilizando la API fwrite()). El propósito de esta función es configurar la persistencia para el malware creando un nuevo servicio. Para facilitar la lectura, esta función puede renombrarse creation_of_service().
No vamos a analizar cada uno de los parámetros admitidos, pero esto es lo que hacen:
-
-launch: crea un servicio para iniciar el malware automáticamente al arrancar el sistema. Con esta opción, el malware no se ejecuta directamente, sino que lo hará al reiniciar el sistema,
-
-run: inicia el malware,
-
-x: ejecuta el malware en modo daemon,
-
-i: crea un servicio para iniciar el malware automáticamente al arrancar el sistema. Con esta opción...
Caso práctico del ataque a XZ Utils
En marzo de 2024, se identificó una vulnerabilidad en XZ Utils: CVE-2024-3094. XZ Utils es una librería de compresión, utilizada en varias aplicaciones de software libre. Resultó que esta vulnerabilidad no era una simple vulnerabilidad, sino un ataque a la cadena de suministro: se introdujo código malicioso en el proyecto. Este código malicioso afecta a todos los proyectos que utilizan esta librería.
Todo comenzó en 2022, cuando un desarrollador llamado Jia Tan empezó a ofrecer actualizaciones de XZ Utils. Las primeras eran legítimas, lo que ayudó a construir la credibilidad de este desarrollador con el proyecto, hasta que se convirtió en uno de sus mantenedores. Poco a poco, commit a commit, el desarrollador integró una puerta trasera en el proyecto. En marzo de 2024, se desplegó todo el código malicioso.
El código malicioso era una macro que se ejecutaba al compilar la librería. Esta macro desencripta un archivo de prueba de unidad (tests/files/bad-3-corrupt_lzma2.xz). Este paso comprueba que el sistema operativo es Linux y desencripta y ejecuta un script Bash. Este script extraerá la puerta trasera final, la librería liblzma_la_crc64-fast.o. Esta librería está construida para ser ejecutada en el binario /usr/bin/sshd, que es el que gestiona el servicio OpenSSH. La puerta trasera permite...
Resumen
En este capítulo hemos visto cómo funciona el sistema operativo Linux, un sistema de código abierto cuyo código fuente es de libre acceso. Esto significa que no hay elementos ocultos, que la documentación está disponible y que todos los mecanismos internos del sistema pueden ser identificados y comprendidos. Sin embargo, sigue existiendo el mito de que en Linux no existe el malware. Los distintos estudios de casos presentados en este capítulo demuestran que, obviamente, esto no es cierto. Los atacantes también tienen apetito por este sistema operativo.