Para llevar a cabo una correcta fortificación de nuestra distribución Linux tenemos que establecer múltiples líneas de defensa y limitar cada usuario o aplicación para que tenga unicamente los privilegios necesarios para ejecutar su tarea. En este post iremos comentando algunas de las líneas de defensa que debemos tener en cuenta para fortificar nuestro sistema siguiendo el orden que se muestra a continuación:
- Fortificación del Firmware
- Fortificación del Bootloader
- Fortificacion del Sistema de ficheros
- Fortificación de Cuentas de Usuario
- Fortificación de Aplicaciones
- Fortificación de Red
Fortificando el firmware
Al encender el equipo se carga un firmware (tipo BIOS o UEFI) que contiene el código necesario para iniciar el proceso de arranque, por lo que la primera medida que podemos aplicar antes del arranque del equipo es proteger el acceso al firmware.
- Pon contraseña a para acceder a la BIOS y/o para bootear la máquina
- Deshabilita el arranque desde medios externos
Fortificando el bootloader: grub2
Tras arrancar el firmware se carga el bootloader, que no es más que un programa que carga el kernel del S.O. En Linux el bootloader que se emplea es grub, el cual por defecto tampoco está libre de amenazas. Si alguien tiene acceso al bootloader y pulsa «C» invocará la shell de grub desde la cual podrá leer ficheros del sistema.
Aunque la shell de grub no es lo único a tener en cuenta, ya que se pueden editar las entradas del menú y añadiendo un simple parámetro, podríamos arrancar en modo de usuario sin que se nos solicite una contraseña.
Al llamar desde init a /bin/bash obtendremos una shell. Desde la shell podremos leer los ficheros del equipo. Si aparte de permisos de lectura quisiéramos poder escribir habría que modificar el parámetro ro (read only) a rw (read write).
Para securizarlo buscaremos limitar el acceso a las funcionalidades del grub que nos permite ver ficheros y modificar las entradas del menú de arranque. Para ello en grub2 definiremos una la lista de superusuarios que tendrán acceso a estas funciones. La creación de superusuarios consiste en editar el archivo «/etc/grub.d/40_custom» añadiendo las siguientes líneas:
set superusers="Usuario"
password Usuario contraseña
Como podemos comprobar, al añadir el password directamente este queda almacenado en texto plano, por lo que para guardarlo hasheado en vez de en plano se puede emplear el siguierte comando para generar un hash.
sudo grub-mkpassword-pbkdf2
Ahora que ya tenemos el hash especificamos el tipo de password y el hash correspondiente, de forma que el contenido del archivo «/etc/grub.d/40_custom» sea parecido a la siguiente imagen.
También podemos limitar la lista de usuarios que pueden utilizar una entrada del menú . Por defecto las entradas del menú sin anotaciones –unrestricted o –users solo pueden ser usadas por el superusuario. Si quisiéramos permitir que una entrada solo sea accesible a un usuario habría que añadir la entrada en el fichero «40_custom», especificando algunas de las siguientes anotaciones:
menuentry "Solo puede iniciarse con superuserio o user1" --users user1
menuentry "Cualquiera lo puede iniciar" --unrestricted
Hay que tener en cuenta que la configuración de usuarios y contraseñas no deben definirse directamente en el archivo grub.cfg, ya que este archivo se sobrescribe cada vez que se actualice la configuración de grub.
Para finalizar y actualizar los cambios al bootloader se ha de ejecutar el comando:
sudo update-grub2
Fortificando el sistema de ficheros:
Para fortificar el sistema de ficheros hay que tener en cuenta las principales amenazas las cuales son:
- Acceso sin autorización a la información almacenada
- Llenar el sistema de archivos evitando así que otros usuarios escriban en el sistema de archivos
- Corrupción del sistema de ficheros que lo vuelva inestable
- Obtener acceso a archivos ejecutables maliciosos con mayores privilegios (En sistemas de ficheros extraibles)
Cifrado de particiones y directorios
Para evitar el acceso no autorizado de alguien que obtenga acceso físico a la máquina podemos encriptar nuestros sistemas de archivos. Para ello a la hora de instalar el S.O crearemos un volumen logico (LVM) sobre el que podemos emplear LUKS para el cifrado. No voy a entrar en detalle sobre la configuración, ya que disponeis de un post dedicado al cifrado de particiones.
Al cifrar toda la partición, en muchos casos terminamos cifrando mucha información innecesariamente (principalmente archivos del sistema) por lo que a veces necesitamos una solución más simple. Usando encfs podemos permitir que un usuario pueda encriptar directorios sin ser root.
apt-get install encfs
Al usar encfs crearemos 2 carpetas una que contendra el contenido en claro y otra en donde se almacenara de forma cifrada el contenido de la primera carpeta. A la carpeta con el contenido en claro unicamente puede acceder el usuario.
De forma adicional para cifrar archivos también es posible utilizar gpg , sea de forma manual o automátizada con algún script como el que teneis en el siguiente post.
Cuotas de uso de disco
Para evitar que un usuario (o un grupo de usuarios) llene el sistema de archivos podemos hacer uso de cuotas. La configuración debe hacerse como root, y consite en primer lugar en editar el archivo «/etc/fstab» añadiendo «usrquota» o «grpquota», dependiendo si se desea cuotas por usuario o grupos, o ambas.
apt-get install quota
Para recargar los cambios en el fstab usaremos el comando:
sudo systemctl daemon-reload
Comandos para la gestión de cuotas:
- quotacheck: crea, comprueba y/o repara archivos de cuotas en un sistema de archivos
- quoteon/quotaoff: activa/desactiva las cuotas en un sistema de archivos
- edquota: permite modificar las cuotas de un usuario (o grupo)
- repquota: informa el estado de las cuotas en un sistema de archivos
Para crear los ficheros externos donde están las cuotas ejecutamos el comando
sudo quotacheck -ugm /
Activamos las cuotas usando el comando
sudo quotaon -v /
Para editar cuotas usaremos el comando
sudo edquota -u testuser
Protección a la hora de montar dispositivos externos
A la hora de montar los dispositivos existen varias cosas a tener en cuenta, un atacante puede introducir en un pendrive un script con el bit de suid como root para escalar privilegios en el sistema o ejecutar un programa C que ejecute una shell como root.
Para evitar este tipo de amenazas hay varias opciones de montaje a tener en cuenta:
- nodev: Ignora los dispositivos especiales en ese sitema de ficheros
- nosuid: Ignora los bits suid y sgid
- noexec: Prohibe la ejecución de programas en ese punto de montaje
La opción de montaje nosuid debería utilizarse siempre en sistemas de archivos en red y extraíbles.Por otro lado la opción noexec es aconsejable utilizarla en sobre dispositivos extraibles. Estas opciones de montaje se añaden en el fichero «/etc/fstab». A parte de los dispositivos extraibles también es buena practica de seguridad añadir estas opciones de montaje sobre las carpetas «/tmp», «/var/tmp» y «/dev/shm», ya que se tratan de directorios de almacenamiento temporal que puden ser aprovechables por parte de un atacante para comprometer el sistema.
/dev/sda3 /tmp ext4 defaults,nosuid,noexec,nodev 0 2
Hay que tener en cuenta que muchas distros modernas ya incluyen estas opciones de montaje. Para consultar que opciones de montaje se han aplicado podemos consultar el fichero <</proc/mounts>>
Permisos de los ficheros
En lo que respecta al acceso no autorizado, debemos tener cuidado con los permisos de los ficheros y directorios.Algunos consejos a tener en cuenta son:
- Los directorios home deben tener permisos 700
- Los archivos de configuración de los distintos demonios no deben ser leídos por todo el mundo
- Quitar los permisos de ejecución que no sean estrictamente necesarios.
- Todos los directorios del sistema deben ser no escribibles excepto para el usuario root
- /tmp debe tener permisos de escritura en todo el mundo, pero con el sticky bit activado
Fortalecimiento de cuentas de usuario:
Las principales amenazas asociadas a las cuentas de usuario son:
- Algún usuario no sea quien dice ser
- Algún usuario esta usando demasiados recursos del sistema impidiendo que funcione correctamente
- Algún usuario posee mas privilegios de los que realmente necesita
- Uso de la cuenta root
Autenticación de los usuarios
Para prevenir que un usuario no sea quien dice ser podemos fortalecer el proceso de autenticación usando los módulos PAM. Usar módulos PAM nos permite cambiar el algoritmo de autenticación sin hacer cambios en las aplicaciones, permite añadir nuevos métodos de autenticación de forma sencilla, a parte de permitir modificar las políticas de autenticación imponiendo reglas sobre la generación de contraseñas, limitando los terminales desde los que el usuario puede iniciar sesión y usar los registros para detectar comportamientos extraños.
El formato para configurar un modulo PAM es:
service type control module-path module-arguments
Algunos de los módulos PAM más típicos son:
- pam_unix – Definición del tipo de hash y características de las contraseñas
- pam_cracklib – Características adicionales para las contraseñas
- pam_securetty – Limita el login de root para algunos dispositivos
- pam_faildelay – Establece una espera tras varios intentos de login fallidos
A modo de ejemplo de la potencia de PAM, estableceremos un doble factor de autenticación con google authenticator para acceder vía ssh. Para ello no hay más que clonar el repositorio de GitHub google-authenticator-libpam y seguir las instrucciones de compilación. Una vez compilado ejecutamos google-authenticator para generar un QR que escanearemos con la aplicación. Para aplicarlo en el servidor ssh únicamente tenemos que modificar la configuración del modulo PAM relativo a sshd añadiendo al final la configuración de google authenticator. Los ficheros de configuración de los módulos PAM los podemos encontrar en la ruta «/etc/pam.d/»
Como podréis observar ahora al acceder vía ssh nos solicita el código de segundo factor de autenticación.
Limitar recursos de usuarios
Utilizando el modulo pam_limit podemos limitar el máximo de sesiones simultáneas de inicio de sesión, el tamaño máximo de archivo, el uso máximo de memoria para un usuario evitando así el uso de recursos en exceso.
Shell restringida
Podemos limitar aún más lo que un usuario puede hacer en el sistema utilizando un shell restringido. Para invocar un shell bash restringido podemos usar bash -r (restricted) o el ejecutable rbash.
sudo useradd user1 -s /bin/rbash
En un shell restringido es posible definir exactamente el conjunto de ejecutables que el usuario puede ejecutar en la máquina. En el caso de rbash podemos crear un directorio «bin» dentro del home del usuario y editando el fichero .bash_profile añadir la variable $PATH=/home/user1/bin.
Para añadir los ejecutables que el usuario puede usar crearemos un link simbolico al nuevo path.
sudo ln -s /bin/ls /home/user1/bin
Acceso como root
Usando módulos PAM podemos restringir el acceso a la cuenta root directamente desde la terminal, obligando a iniciar sesión primero como un usuario normal y luego usar el comando su, de esta forma quedara registrado en los logs quien acede como root.
Por ultimo a través del comando sudo y la definición de sudoers es posible definir un acceso de administrador limitado de forma que tan solo pueda realizar algunas tareas.
Fortalecimiento a nivel de aplicación:
Eliminar las aplicaciones que no sean necesarias
En primer lugar, debemos eliminar las aplicaciones que no necesitemos, para identificar estas aplicaciones podemos hacer a ojo o usar utilidades que busquen los paquetes sin usar en base al timestamp de los ejecutables.
Eliminar paquetes
apt-get remove <paquete>
Desactivar con servicios
systemctl disable <service>
Enmascarar servicios para que nada se pueda comunicar con él
systemctl mask <service>
Limita los recursos de las aplicaciones
Por otro lado también podemos limitar los recursos que consumen las aplicaciones con cpulimit (limita la cpu asociada a un proceso), prlimit (limita los recursos asociados a un proceso) y cgroups (limita los recursos para un conjunto de procesos).
cpulimit -p 4112 -l 25
Restringiendo aplicaciones
Hay que tener en cuenta que un proceso en Linux conoce solo 2 directorios el actual, y el root.
El comando chrdir nos permite cambiar el directorio actual de un proceso y chroot nos permite cambiar de forma virtual directorio root, creando espacios aislados del sistema de archivos pero ojo la memoria no se aísla! aun puede ser alcanzable por procesos root.
Esto puede ser útil en ftp, web sencillas o incluso si disponemos de algún cliente torrent para evitar que por alguna vulnerabilidad del cliente puedan leer nuestros archivos. Muchas veces chroot no es suficiente, por lo que es conveniente emplear otras técnicas para aislar y restringir las aplicaciones.
AppArmor nos permite restringir el acceso a ciertas aplicaciones, scripts o programas para únicamente hacer ciertas tareas o tener acceso a ciertas partes del sistema. AppArmor nos permite generar un perfil con los datos del funcionamiento normal de la aplicación de forma que no permita a la aplicación realizar cosas fuera del perfil.
En primer lugar descargaremos las utilidades y los perfiles:
sudo apt-get install apparmor-utils apparmor-profiles
Comprobaremos que apparmor se esta ejecutando correctamente:
sudo aa-status
Si queremos restringir una app, podemos generar un perfil ejecutando el siguiente comando.
sudo aa-genprof <path_absoluto_programa>
Los perfiles generados los podemos encontrar en <</etc/apparmor.d/>>. Para pasar a modo estricto los perfiles generados ejecutamos:
sudo aa-enforce /etc/apparmor.d/*
AppArmor no proporciona sandboxing, sino que limita a qué partes del sistema puede acceder la aplicación. Especifica los recursos concretos que una aplicación no puede usar. Sin embargo, estos recursos no están aislados, por lo que dos aplicaciones que se ejecutan con AppArmor con acceso al mismo recurso podrían interactuar.
Sandboxing
En las técnicas de sandboxing se crea un entorno virtual para ejecutar los procesos de forma aislada. Principalmente nos sirve para ejecutar aplicaciones no confiable de forma segura, ya que al tratarse de un entorno aislado, en caso de una vulnerabilidad o malware existente este no se propagaría por el sistema. Existen diversas opciones de sandboxing como lxc, docker, FireJail..etc.
FireJail aprovecha los espacios de nombres de Linux para proporcionar aislamiento a nivel de usuario, montaje, red y proceso. Este aislamiento proporciona a la aplicación su propia caja de arena para hacer lo que quiera mientras evita que esos cambios afecten al resto del sistema.
apt-get install firejail
Para ejecutar una aplicación de forma segura con firejails podemos usar:
firejail --seccomp --nonewprivs --private-tmp firefox
Fortificando a nivel de red:
Filtrados de paquetes
Las iptables se tratan de un modulo del kernel de Linux que actúa como un firewall de estado filtrando los paquetes de red. Funciona mediante tablas que contienen cadenas que a su vez contienen una agrupación de reglas que indican que paquetes debe permitir entrar y cuales no.
Consejos de definición de reglas:
- Desde un servidor no debería ser posible navegar
- Implementar mecanismo que dropeen Ddos o limiten el ancho de banda
- Implementar un control de estado
- Todo lo que no este permitido debe estar bloqueado
Hay que tener en cuenta que el orden de las reglas afecta al funcionamiento, algunas ejemplos de reglas que pueden ser interesantes son:
Bloquear una dirección IP
iptables -A INPUT -s 192.168.0.200 -j DROP
Rechazar todo el tráfico por defecto
iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP
Permitir el trafico por el puerto 22 (ssh) en la red local
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT iptables -A INPUT -s 192.168.0.0/24 -m state --state NEW -p tcp --dport 22 -j ACCEPT
Protección frente a Ddos
iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
Hacer que las reglas sean persistentes
apt-get install iptables-persistent iptables-save → Guarda las reglas Iptables iptables-restore → Carga las reglas del backup
Tcp Wrappers
Un TCP Wrapper provee de un control de acceso simple y administración de logs estandarizada para aplicaciones que soporten y reciban conexiones de red. Son ACL para filtrar accesos de la red a Servicios locales. Funcionan con TCP,UDP e ICMP. Los wrappers no funcionan con servicios de llamadas procedente de remoto; ej: RCP sobre TCP.
Los wrappers trabajan en capa 7 y pueden filtrar consultas aun cuando se utilice cifrados, a diferencia del firewall de iptables que trabaja en capa 3 actuando a nivel de paquetes sin ser consciente de la conexión. Otra diferencia es que con iptables controlamos el trafico tanto entrante como saliente mientras que con los wrapper solo podemos controlar el entrante.
Principalmente posee dos ficheros de configuración:
- «etc/hosts.allow» : Este archivo contiene los nombres de hosts que tienen permitido utilizar servicios de red.
- «/etc/hosts.deny» : Este archivo contiene los nombres de hosts que no pueden utilizar servicios de red.
- El fichero hosts.allow tiene preferencia sobre el hosts.deny.
Sintaxis:
lista_sercicios: lista_cliente [: comando_shell]
Para configurarlo, lo recomendable seria denegar todas las conexiones en el hosts.deny y habilitar en el hosts.allow las conexiones entrantes que permitamos , como por ejemplo las conexiones ssh que provengan de la red local.
Ejemplo hosts.deny
ALL: ALL
Ejemplo de host.allow
sshd: 192.168.0.0/255.255.255.0 EXCEPT 192.168.0.100
Referencias:
- https://offsec.red/hardening-kali-linux-2019-4/
- https://www.creadpag.com/2018/05/aprendamos-hardening-usando-debian.html
- https://linux.die.net/man/5/pam.d
Para más información consultar el manual de seguridad de debian
Deja un comentario