Seguridad en un servidor GNU/Linux

De Apuntes
Saltar a: navegación, buscar

Un servidor recién instalado no está exento de ataques y usualmente requiere de algunas acciones adicionales para mejorar la seguridad del sistema operativo y de la información que resguarda. A continuación se detallan varias opciones que se pueden aplicar. Qué tantas acciones realizar dependerá del nivel de seguridad o usabilidad que se desee alcanzar.

Nótese que esta no es una guía, estilo receta, de copiar y pegar; cada sysadmin deberá analizar los consejos, escoger los más apropiados para su ambiente y adaptarlos según necesidades.

Si conoce alguna buena práctica que no se ha incluido, o desea mejorar algunos de los expuestos, edite este artículo y contribuya.

Una sola persona que administre

Idealmente, un servidor debe ser administrado por una única persona, así esta persona tiene un mayor control de los cambios que se realicen y la responsabilidad de mantener el servicio seguro. Varias personas con cuentas administrativas pueden provocar desorden y, al dificultar el sentar responsabilidad de acciones tomadas, negligencia en su actuar.

Varias personas pueden discutir e incluso decidir sobre la administración de un sistema, pero una única persona es quién debería tener el acceso para aplicar dichas configuraciones.

Crear una cuenta por cada usuario

Es un error compartir una única cuenta de usuario para acceder al sistema. Esto dificulta el control, la contraseña está en muchas manos, si fuese necesario es más complejo bloquear el acceso a una sola persona o definir diferentes niveles de acceso, es difícil sentar responsabilidad de quién realizó una mala acción, etc.

Lo adecuado es asignar una cuenta, con su contraseña, a cada uno de los usuarios. Esto permite también asignar permisos adecuados para cada rol y facilita la gestión de las cuentas del sistema.

Para crear una cuenta, ejecute como administrador:

adduser juanito

La salida del comando será algo como esto:

Adding user `juanito' ...
Adding new group `juanito' (1001) ...
Adding new user `juanito' (1001) with group `juanito' ...
Creating home directory `/home/juanito' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for juanito
Enter the new value, or press ENTER for the default
	Full Name []: Juanito
	Room Number []: 
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] y

Para añadir un usuario a un grupo, ejecute como administrador:

adduser juanito nombregrupo

La salida del comando debería ser algo como lo siguiente:

Adding user `juanito' to group `nombregrupo' ...
Adding user juanito to group nombregrupo
Done.

Par cambiar la contraseña de un usuario, ejecute como administrador:

passwd juanito

Para eliminar una cuenta de usuario, ejecute como administrador:

deluser juanito

La salida del comando será algo como esto:

Removing user `juanito' ...
Warning: group `juanito' has no more members.
Done.

Contraseñas fuertes

Existen diferentes técnicas para romper contraseñas: fuerza bruta, diccionarios, rainbow table, etc. En How Secure Is My Password? puede darse una idea de qué tan segura es una contraseña.

Para evitar crear contraseñas fáciles de vulnerar, se sugieren algunas recomendaciones:

  • Al menos ocho caracteres de longitud
  • Al menos dos tipos de estos caracteres:
    • letras en minúsculas (de la a a la z)
    • letras en mayúsculas (de la A a la Z)
    • números (del 0 al 9)
    • caracteres especiales (? : ; . , ! – $ # * % &)
  • No usar contraseñas comunes (galleta, password, 123456, qwerty, abc123, ...)
  • No escriba la contraseña en papel, pizarra o en archivos de texto plano.

También se puede utilizar algún generador de contraseñas.

Deshabilitar el usuario root

Es una mala práctica ingresar con el usuario root al sistema, pues este tiene acceso irrestricto y permanente a todo el filesystem y ejecuta cada comando con derechos administrativos, aumentando en gran medida el riesgo. Se recomienda bloquear el acceso directo a la cuenta root para evitar estas situaciones y que las tareas administrativas se realicen por medio del comando sudo (Ver más abajo).

Para borrar la contraseña del usuario root se ejecuta el siguiente comando:

passwd -d root

Para bloquear la cuenta del usuario root se ejecuta el siguiente comando:

passwd -l root

Habilitar sudo

Es una mala práctica ingresar con el usuario root al sistema, pues este tiene acceso irrestricto y permanente a todo el filesystem y ejecuta cada comando con derechos administrativos, aumentando en gran medida el riesgo.

La herramienta sudo permite ejecutar un comando, y solo ese comando, con derechos administrativos De esta manera el usuario ingresará como un usuario con restricciones e invocará el acceso administrativo únicamente en los casos que lo ameriten, como el instalar un paquete o editar un archivo de configuración del sistema.

Utilizando sudo se evita tener que compartir la contraseña de root y se tiene un registro de las acciones administrativas por cada usuario. Los registros se encuentran en /var/log/auth.log en Debian/Ubuntu, y en /var/log/secure en Fedora/CentOS.

sudo forma parte de distribuciones como Ubuntu o Fedora. En el caso de otras, como Debian, se debe instalar primero. Para conocer si una distribución Linux cuenta con sudo puede ejecutar:

sudo -V

Para instalar sudo en Debian, ejecute como administrador:

apt update
apt install sudo

Para permitir que un usuario utilice sudo, se debe añadir al grupo respectivo, en Debian/Ubuntu se usa el grupo sudo, en Fedora/CentOS se usa el grupo wheel. Por ejemplo, así se añade el usuario juanito al grupo sudo:

adduser juanito sudo

De esta manera el usuario quedará habilitado para utilizar sudo. Por ejemplo:

sudo apt full-upgrade

sudo permite asignar permisos de una forma más granular, por ejemplo eligiendo qué comandos se pueden ejecutar y con qué permisos. Consulte la documentación de su distribución para más detalles.

Configurar vencimiento de contraseñas

Es común que un usuario mantenga su misma contraseña por semanas, meses e incluso años. Es por eso importante configurar fechas de vencimiento que obliguen al usuario a cambiar su contraseña.

chage es una herramienta que permite configurar vencimiento de contraseñas. Este es un ejemplo de uso:

chage --maxdays 90 --warndays 8 juanito

Donde:

  • --maxdays 90 indica el número máximo de días que un usuario puede utilizar una misma contraseña, en este caso 90 días.
  • --warndays 8 indica cuántos días antes mostrar un aviso de vencimiento, en este caso 8 días.

Si la contraseña vence, se pedirá al usuario que defina una nueva contraseña al momento de autentificarse.

También es posible definir un número de días, después de expirada la contraseña, para que una cuenta se inactive:

chage --maxdays 90 --warndays 8 --inactive 30 juanito

En este caso, después de que pasen 30 días con la contraseña vencida, se bloqueará la cuenta y solo un administrador podrá volver a activarla utilizando el mismo comando chage.

Para más detalles consulte la documentación de chage.

Configurar actualizaciones de seguridad automáticas

Las actualizaciones, en general, deberían aplicarse manualmente y en un ambiente de pruebas, pues existe el riesgo de que algún paquete afecte la estabilidad del sistema. Sin embargo los paquetes de seguridad normalmente implican cambios pequeños para arreglar alguna vulnerabilidad (fixes), no introducen grandes cambios por lo que disminuye el riesgo de una falla.

La comunidad de desarrolladores usualmente corrige vulnerabilidades en tiempo récord, así que en cuestión de unos pocos días, a veces horas, estarán listas para aplicarse. Una aplicación tardía aumenta el riesgo por lo que se recomienda configurar las actualizaciones para este tipo de paquetes.

En Debian/Ubuntu configure las actualizaciones automáticas de la siguiente manera.

Instale el paquete unattended-upgrades:

apt install unattended-upgrades

Configure editando el archivo /etc/apt/apt.conf.d/50unattended-upgrades.

Para monitorear consulte la bitácora unattended-upgrades.log:

tail -f /var/log/unattended-upgrades/unattended-upgrades.log

En Fedora/CentOS se configura de la siguiente manera.

Instale el paquete dnf-automatic:

dnf install dnf-automatic

Configure el archivo /etc/dnf/automatic.conf de acuerdo a sus necesidades.

Habilite el servicio:

systemctl enable --now dnf-automatic.timer

Puede monitorear que paquetes se han actualizado, consultando el log de dnf:

tail -f /var/log/dnf.log

Desactivar acceso de root por SSH

Tener acceso remoto con la cuenta root, la cuenta administrativa que tiene acceso irrestricto, es contraproducente. Lo recomendable es configurar el servidor SSH para bloquear su acceso. De esta manera, para ingresar al servidor se debe hacer con las cuentas creadas a cada usuario del sistema.

Algunos sysadmins crean una cuenta sin derechos administrativos para acceder al servidor por SSH. Una vez autenticados, utilizan el comando su para cambiarse de usuario o bien convertirse en súper usuario.

Antes de bloquear el acceso de root por SSH, asegúrese de contar con un usuario con acceso.

Edite el archivo:

/etc/ssh/sshd_config

Modifique o agregue el parámetro PermitRootLogin:

PermitRootLogin no

Guarde los cambios y reinicie el servicio. En Debian/Ubuntu:

/etc/init.d/ssh restart

En Fedora/CentOS:

/etc/init.d/sshd restart

Limitar IPs que pueden acceder por SSH

Una buena práctica es restringir desde qué IPs se puede acceder el servidor por SSH. Permitiendo únicamente las redes de confianza, como la red local.

Una forma de restringir desde que IP's se puede acceder el servidor es configurando TCP Wrappers. En el archivo hosts.allow se indica las redes con acceso. Utilice el editor de su preferencia para abrir el siguiente archivo:

/etc/hosts.allow

donde se indica desde cuál o cuáles redes se tiene acceso:

sshd : 10.72.18.0/24,172.16.48.0/24

Utilice una coma (,) para separar varias redes.

Por último se edita:

/etc/hosts.deny

y se indica que cualquier otra red se debe bloquear:

sshd : ALL

Se aplicará la primera regla que coincida, comenzando por el archivo hosts.allow, en caso de que no haya coincidencia se aplicará el archivo hosts.deny. Una vez que se guarden los cambios deberían reflejarse inmediatamente.

Existen mucho más opciones, revise el manual de hosts_access para más detalles. También es posible configurar el acceso con iptables o con la configuración de SSH.

Ingreso por SSH con llaves pública/privada en lugar de contraseña

Una forma alternativa para ingresar a un servidor vía SSH es deshabilitar el ingreso por contraseñas y en su lugar utilizar llaves pública y privada para autorizar a una máquina en específico. De esta manera únicamente se podrá ingresar desde la o las computadoras autorizadas.

Primero genere las llaves SSH y exporte la llave pública al servidor.

Luego, cuando esté seguro que tenga acceso sin contraseña desde su computadora, proceda a deshabilitar la autenticación por SSH. Esto se hace modificando el archivo:

/etc/ssh/sshd_config

Busque estas directivas y modifique como se muestra:

PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no

Por último reinicie el servicio. En Debian/Ubuntu:

sudo systemctl restart ssh

O en Fedora/CentOS:

sudo systemctl restart sshd

A partir de este momento, el acceso remoto SSH se podrá hacer únicamente desde las computadoras autorizadas, las que cuenten con la llave privada correspondiente a la llave pública autorizada en el servidor. Cualquier intento utilizando contraseña será rechazado, aunque las credenciales sean las correctas.

Monitoreo de logs y generación de reportes

Las bitácoras o logs registran todos los eventos del sistema, por ejemplo ingresos al sistema, paquetes instalados, fallos, etc. Este es el punto de partida para la identificación de errores o bien, actividades que puedan vulnerar el servidor.

Monitotear los múltiples archivos .log de múltiples servidores puede resultar complicado. Para facilitar dicha tarea existen herramientas como logwatch, el cuál genera reportes que, incluso, pueden ser enviados por correo electrónico. Dichos reportes son configurables de manera que se enfoquen en los puntos de interés para el sysadmin.

Instale el paquete ejecutando, en Debian/Ubuntu:

apt install logwatch

O bien, en Fedora/CentOS:

yum install logwatch

Para probar el servicio, ejecútelo de manera manual. Por ejemplo:

logwatch --detail Low --mailto juanito.perez@ucr.ac.cr --service http --range today


Para configurar los reportes diarios, edite el siguiente archivo:

/usr/share/logwatch/default.conf/logwatch.conf

Estas son algunas de las opciones:

Dirección de correo a dónde enviar los reportes:

MailTo = juanito.perez@ucr.ac.cr

El rango de tiempo a incluir en el reporte

Range = Yesterday

Opciones disponibles: All, Yesterday, Today.

Qué tanta información debe incluir el reporte:

Detail = Medium

Opciones disponibles: Low, Medium, High.

Si desea un reporte de todos los servicios:

Service = All

O bien, consulte el directorio services para conocer el nombre de los servicios a seleccionar:

ls -l /usr/share/logwatch/scripts/services

En este caso, un ejemplo de configuración sería la siguiente:

Service = http
Service = sshd2
Service = sudo

Monitoreo de logs para bloquear ataques por fuerza bruta

Un problema muy usual son los ataques por fuerza bruta, donde el atacante intenta ingresar probando múltiples usuarios y múltiples contraseñas. Estos intentos repetidos quedan registrados en las bitácoras o logs del sistema. Una acción muy recomendable es utilizar una herramienta como fail2ban que monitorea y bloquea de manera automática este tipo de ataques. Por ejemplo si desde una IP hay cinco intentos fallidos, que esta sea bloqueada por 10 minutos. Los logs a monitorear y el tiempo de bloqueo son configurables.

Para instalar el paquete, ejecute, en Debian/Ubuntu:

apt install fail2ban

O, en Fedora/CentOS:

dnf install fail2ban
systemctl enable fail2ban.service
systemctl restart fail2ban.service

Usualmente la configuración predeterminada será suficiente. Sin embargo puede personalizarla según las necesidades.

Para evitar que una actualización sobreescriba la configuración, realice una copia del archivo jail.conf:

cd /etc/fail2ban/
cp jail.conf jail.local

Y modifique esta copia. Utilice su editor de preferencia y abra el archivo:

/etc/fail2ban/jail.local

Ocultar la versión de los servicios instalados

La versión de un programa instalado en un servidor debería ocultarse, pues se puede evidenciar la ejecución de software antiguo, cuyas vulnerabilidades son conocidas. Por ejemplo la versión del servidor web Apache usualmente se muestra en las pantallas de error, cuando se solicita una página que no existe. O bien si es posible acceder archivos readme o changelog de algún gestor de contenido instalado, como Drupal o Wordpress.

Ocultar versión de servidor Apache

Para ello edite, en Debian/Ubuntu:

/etc/apache2/apache2.conf

o en el caso de Fedora/CentOS:

/etc/httpd/conf/httpd.conf

En dicho archivo añada las líneas:

ServerTokens Prod
ServerSignature Off

Guarde y reinicie el servicio:

systemctl restart apache2

Ocultar archivos en gestores de contenido

Además de los archivos index ubicados en el directorio raíz de un Sistema Gestor de Contenido (CMS), es posible que archivos README, INSTALL o CHANGELOG se encuentren accesibles, mostrando información que puede ser útil para un atacante.

Una solución es mover dichos archivos o bien modificar los permisos de acceso, por ejemplo:

chmod 700 readme.txt

Con esta configuración de permisos, únicamente el dueño del mismo tendrá acceso. Por supuesto se asume que el usuario que usa el servicio web, por ejemplo www-data o apache, no es dueño de dicho archivo. De ser así cambie el dueño, por ejemplo:

chmown juanito readme.txt

Estos son algunos de los archivos que no deberían accederse desde la web:

Drupal:

  • CHANGELOG.txt
  • INSTALL.mysql.txt
  • INSTALL.txt
  • MAINTAINERS.txt
  • INSTALL.pgsql.txt
  • LICENSE.txt
  • UPGRADE.txt
  • README.txt

Wordpress:

  • readme.html

Eliminar metatags en Wordpress

En Wordpress es necesario remover la información de versión que se muestra en el header y los rss. Para ello edite su archivo functions.php y añada las siguientes líneas:

// hide the meta tag generator from head and rss
function disable_version() {
   return '';
}
add_filter('the_generator','disable_version');
remove_action('wp_head', 'wp_generator');

Cifrar datos sensibles

Muchas veces se debe almacenar información sensible, por ejemplo información médica de los usuarios, resultados de exámenes académicos, información sobre configuración de sistemas críticos, etc. Estos datos deben protegerse tanto de ataques externos como de la posibilidad de accesos físicos, por ejemplo si se diera el hurto de un disco duro.

El cifrado de datos es una solución muy utilizada, básicamente si el atacante logra robar los datos, verá "basura" y le será súmamente difícil descifrar esa información.

Datos cifrados a través de la web

Una tendencia muy fuerte es cifrar las conexiones vía web utilizando el protocolo HTTPS, que es la versión segura de HTTP. Una excelente opción es utilizar Let's Encrypt, su utilización es relativamente sencilla permitiendo obtener un certificado en unos pocos segundos.

Cifrado de documentos

Existen dos tipos de métodos para cifrar información en un almacenamiento: Filesystem stacked level encryption que cifra a nivel de archivo y Block device level encryption donde se cifra toda una partición.

Transferencia segura de datos

En el caso que se desee transferir archivos de manera remota, la recomendación es utilizar el protocolo SFTP, una extensión del protocolo SSH para la gestión de archivos. Existen múltiples herramientas que utilizan este protocolo como scp, Nautilus File Manager, WinSCP, FileZilla, etc.

Configuración del BIOS

El BIOS debería tener una configuración básica que impida a alguien, con acceso físico al servidor, realizar acciones maliciosas.

Debe desactivarse el arranque desde otros dispositivos, como una memoria USB con un Linux Live, desde donde se tendría acceso irrestricto a los archivos.

Además se debe proteger la configuración del BIOS con una contraseña, para así evitar modificaciones no autorizadas por parte de terceros.

Restringir el acceso físico al servidor

Una persona que logre tener un acceso físico al servidor podría vulnerarlo de muchas maneras. Por ejemplo podría modificar el arranque de un Ubuntu Server para ingresar como usuario root aunque se desconozca la contraseña.

Es recomendable hospedar el servidor en un lugar con acceso restringido, por ejemplo protegido bajo llave, con sistemas biométricos o con tarjetas de acceso.

El BIOS también debe estar correctamente configurado para evitar que un tercero arranque desde otro sistema almacenado en un dispositivo externo.

Gestionar contraseñas en llaveros seguros

Es sumamente importante resguardar los accesos a los sistemas. Es una muy mala práctica escribir las contraseñas en archivos planos o anotarlas en libretas sin ningún resguardo.

La solución es guardarlas en archivos cifrados que se pueden abrir únicamente con una contraseña maestra. Existen varias opciones: