Medidas de Seguridad y "Hardening" en servidores SSH
Seguramente muchos de vosotros conocéis y controláis el protocolo SSH y seguramente, una de vuestras implementaciones preferidas es OpenSSH, sin embargo, en muchas ocasiones olvidamos o desconocemos que se trata de una herramienta que si bien puede facilitar muchísimo las tareas de un administrador de sistemas, también puede ser una herramienta que en las manos de un hacker, puede llevar no solo a comprometer una máquina, sino también todo el segmento de red. Tener plena conciencia de este hecho, es el primer paso para evitar este tipo de problemas, por este motivo es importante conocer las medidas de seguridad que se deben implementar en un servidor SSH, principalmente cuando este se expone a entornos tan "agresivos" como Internet.
Medidas de seguridad en SSH
Para fortalecer la seguridad de un servicio SSH, existen ciertas medidas que deben implementarse con el fin de evitar (o al menos dificultar) ataques contra la infraestructura del tipo MITM entre otros, algunas de estas medidas se indican a continuación, aunque pueden implementarse muchas otras en función a necesidades especificas, estas son unas medidas básicas y de una “casi” obligatoriedad.
En primer lugar, para implementar casi todas las medidas de seguridad que se mencionan a continuación, se debe conocer el fichero de configuración del servidor SSH, que normalmente se encuentra ubicado en "/etc/ssh/sshd_config". Estamos hablando, evidentemente de servidores Linux o algunas otras distribuciones basadas en Unix, sin embargo las directivas que se incluyen en este fichero, son propias del servidor SSH y funcionan igual en cualquiera de la plataformas soportadas por OpenSSH.
No permitir acceso remoto al usuario Root
No se debería permitir el acceso remoto al usuario root, normalmente debería permitirse el acceso a usuarios que tengan cuentas con privilegios limitados, la razón principal de esto, es debido a que, si el servicio SSH es vulnerable a alguna "0 day" o se implementa una mala política de contraseñas, un atacante puede ganar acceso al servidor y del mismo modo que ocurre con otros servicios como Apache, es conveniente que se garantice solamente los privilegios mínimos al proceso. Tambien anotar, que otra muy buena alternativa es implementar una "jaula" tambien conocida como "chroot jail". Para evitar que el usuario "root" pueda acceder de forma remota, se aplica la siguiente directiva al fichero de configuración:
PermitRootLogin no
Permitir acceso remoto solamente a un listado determinado de usuarios
Siguiendo este mismo orden de ideas, también es posible habilitar solamente aquellos usuarios que utilizaran el servicio, definiendo los nombres de las cuentas que tienen permisos realizar una conexión con el servidor SSH. Del mismo modo también se puede declarar de forma explicita quienes no pueden acceder al servidor SSH aunque cuenten con credenciales de acceso validas:
AllowUsers Adastra
DenyUsers Bernardino Templar
Tiempo de gracia para establecer la conexión
Una medida de seguridad importante consiste en definir el número de segundos máximo que tardará el usuario en ingresar sus credenciales, si realmente es quien dice ser, normalmente no debería tardar mucho, para definir este “tiempo de gracia” la directiva en el fichero sshd_config es:
LoginGraceTime 30
Esto definirá un valor de 30 segundos para ingresar usuario/clave.
Paridad entre usuarios y direcciones IP permitidas
Difinir los usuarios, maquinas y cuentas que pueden conectarse al servicio SSH, es una buena medida en entornos donde se utilizan direcciones IP estaticas, donde se sabe, que un usuario determinado se conecta desde una dirección IP concreta.
AllowUsers adastra@192.168.1.35
Con esto, se denegará la conexión cuando no proceda de la dirección IP indicada, aunque el usuario cuente con las credenciales de acceso correctas.
Número máximo de intentos de conexión.
Definir un número bajo de intentos de autenticación, reduce el riesgo y evidentemente el éxito, de ataques por fuerza bruta.
MaxAuthTries 2
Se definen 2 intentos de autenticación máximos.
No permitir passwords vacíos.
Creo que no necesita muchas explicaciones, el titulo lo dice todo.
PermitEmptyPasswords no
Definir un número máximo de usuarios conectados a la maquina.
En ocasiones resulta interesante limitar el número de usuarios conectados a una máquina para evitar saturar el servidor, para ello esta directiva es útil
MaxStartups 10
Permite 10 clientes concurrentes.
Cambiar puerto por defecto.
En algunas ocasiones resulta conveniente cambiar el puerto por defecto (22) por cualquier otro para dificultar las cosas un poco a un atacante, la directiva es:
Port 3334
Cabe anotar que esta opción también es soportada en el fichero de configuración del cliente y en dicho caso, el puerto por el que se intentarán establecer todas las conexiones a servicios SSH será al puerto especificado en el fichero de configuración, a menos que se especifique de forma explicita un puerto distinto por medio de la opción “-p”
Ahora bien, como se ha indicado anteriormente, el fichero de configuración del servidor se encuentra ubicado en /etc/ssh/sshd_config y el fichero de configuración del cliente se encuentra ubicado en /etc/ssh/ssh_config sin embargo, si el cliente tiene el fichero ssh_config ubicado en el directorio ~/.ssh/config ese será el que utilice el cliente de OpenSSH.
No permitir la creación de túneles SSH
Esta medida de seguridad es importante, ya que uno de los vectores de ataque más exitosos para comprometer la red interna desde un segmento de red externo como internet, es por medio del uso de túneles SSH, con los cuales no solamente se puede acceder a máquinas inaccesibles desde el exterior, sino que también, es posible saltarse medidas de seguridad importantes como Firewalls o algún IDS. La directiva para evitar el uso de esta característica en SSH, es:
AllowTcpForwarding no
Autenticación por medio de claves publica/privada
Hasta este punto se ha venido hablando de autenticación por medio de una cuenta de usuario existente en el sistema, sin embargo OpenSSH soporta la autenticación por medio del uso de pares de claves privada/publica, el servidor SSH debe contener la clave publica, mientras que el cliente debe contener la clave privada para realizar la autenticación con el servicio. Si el procedimiento de instalación de las claves en cada uno de los puntos (cliente-servidor) se ha realizado de forma correcta, la autenticación al servicio SSH no será contra un usuario existente en el sistema donde se ejecuta el servicio, sino que será contra la contraseña que se ha empleado para la generación de las claves. Este mecanismo de autenticación es el más robusto y desde luego, el más recomendado para servidores que se encuentran expuestos en internet.
El proceso de generación de las claves publica/privada se detalla a continuación:
Debe existir el directorio .ssh en el directorio personal del usuario que ejecuta el cliente SSH, si no existe, crearlo
>mkdir -p ~/.ssh ; chmod 700 ~/.ssh ;
posteriormente es necesario crear las claves con el uso del comando ssh-keygen.
>ssh-keygen -t rsa
De este modo se crea una clave RSA utilizada para el mecanismo de autenticación.
Ahora es necesario transferir la clave al servicio ssh, para conseguir esto de forma segura se utiliza el comando ssh-copy-id Este comando creará (si no existe) el fichero authorized_keys conteniendo las claves privadas que pueden ser admitidas por el servidor, de este modo, cuando se intente ejecutar una conexión con un servidor SSH, lo primero que se intentará hacer es buscar dicho fichero en el directorio personal de usuario y si este existe, se intentará realizar la conexión utilizando dicha clave, si se intenta realizar la conexión con usuario distinto del que se ha especificado en el comando ssh-copy-id la autenticación se realizará por login y password en la maquina remota.
ssh-copy-id root@192.168.1.33
The authenticity of host ’192.168.1.33 (192.168.1.33)’ can’t be established.RSA key fingerprint is ac:ad:22:07:7c:11:b4:49:ee:3f:32:95:5b:5b:d4:99.Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘localhost’ (RSA) to the list of known hosts.jdaanial@localhost’s password:Now try logging into the machine, with “ssh ‘root@192.168.1.33′”, and check in:.ssh/authorized_keysto make sure we haven’t added extra keys that you weren’t expecting.
ssh root@192.168.1.33
Enter passphrase for key ‘/root/.ssh/id_rsa’:
Como puede apreciarse desde la maquina donde se encuentra el servicio SSH (192.168.1.33) no se ha tenido que realizar ningún tipo de acción, todo se ha ejecutado desde el lado del cliente, este se encarga de generar las claves y de importarlas al servidor, evidentemente no cualquier usuario puede realizar este tipo de acciones, solamente aquellos que tengan las credenciales de acceso correspondientes en el servidor y privilegios de root.
Consideraciones al momento de utilizar claves publica/privada
Tal como se ha indicado en párrafos anteriores, es necesario tomar ciertas medidas de seguridad con el fin de endurecer un servicio SSH, una de estas medidas sin lugar a dudas es el uso de un mecanismo de clave publica/privada que se ha indicado anteriormente, sin embargo este mecanismo por si solo no garantiza la seguridad del servicio, se deben habilitar algunas opciones adicionales en el fichero de configuración del servidor para que realmente funcione como se espera, estas son:
PasswordAuthentication no
En el caso de que se permita el acceso por clave publica y privada, cabe preguntarse ¿realmente es necesario permitir otro mecanismo de autenticación diferente? En el caso de que la opción PasswordAuthentication no sea establecida a “no” de forma explicita, será posible acceder al servidor por medio de una cuenta de usuario existente en el sistema aunque se indique al servidor SSH que el mecanismo de autenticación será por medio de clave privada, por ejemplo
ssh root@192.168.1.33
Enter passphrase for key ‘/root/.ssh/id_rsa’:
Enter passphrase for key ‘/root/.ssh/id_rsa’:
Enter passphrase for key ‘/root/.ssh/id_rsa’:
root@192.168.1.33′s password:
En el comando anterior, el servidor SSH solicita la clave privada para realizar la autenticación con el servicio, sin embargo como puede apreciarse, después de tres intentos de autenticación fallidos el servicio solicita la clave correspondiente al usuario root del sistema, en lugar de terminar la conexión de forma automática que será posiblemente lo mas adecuado.
Estas son solamente algunas medidas de seguridad que se pueden implementar en un servidor SSH para evitar que sea un objetivo fácil para un atacante, sin embargo lo más importante para intentar garantizar la seguridad de un servidor SSH, es hacer uso del sentido común y definir unas políticas de acceso adecuadas dependiendo de las necesidades particulares de cada cual. Esto no siempre es fácil, pero dedicar tiempo a hacerlo, realmente es un trabajo que merece la pena y que puede evitar un gran dolor de cabeza a un administrador de sistemas.