Existe un falso tópico por ahí que viene a decir, de una u otra forma, que Linux es más seguro que Windows. Para nada. Es cierto que, normalmente, el usuario medio de Linux está más comprometido con la seguridad, abundan más los usuarios expertos y menos los usuarios domésticos y que existe una mayor variedad de posibilidades y herramientas para hacer seguros nuestros sistemas. También que al existir un volumen menor de equipos con Linux no es objetivo prioritario de los creadores de virus. Pero «recién salido de la caja» y en manos de un usuario torpe y/o despreocupado, un Linux es, por regla general, tan poco seguro como cualquier Windows. De veras.
Veamoslo, por ejemplo, desde el punto de vista de la política de usuarios y contraseñas, uno de los aspectos que mas se critica en los Windows de escritorio. Una Debian 7.3 (la última en el momento de escribir esto) te permite poner cualquier contraseña para el root y la cuenta inicial que se crean de forma obligatoria durante la instalación. Y cuando digo cualquiera, digo cualquiera y sin ningún tipo de advertencia. ¡Hasta una de un sólo carácter o el maldito 123456 (que hace años que ya ni siquiera en Hotmail está permitida aunque sigue siendo una de las passwords más usadas)! Además, el único tipo de protección ante ataques de diccionario y/o fuerza bruta es un retraso de tres segundos entre cada intento de login fallido. No, no parece un planteamiento muy seguro a priori ¿Verdad? Bueno, por lo menos no nos permite dejar las cuentas sin contraseña. Algo es algo…
La parte positiva del asunto es que con un poquito de trabajo por nuestra parte este esquema puede mejorar sustancialmente. Para ello, lo primero es conocer como funciona la autenticación de usuarios en Linux. Vamos a ello.
Antes que nada vamos a ubicar algunos de los ficheros importantes en este asunto. En el directorio /etc se encuentran los ficheros passwd y shadow que guardan, respectivamente, las cuentas de usuario y los «hashes» de las contraseñas. Además, repartido entre ellos, existe mucha información relacionada con el proceso de autenticación: si el usuario puede hacer login interactivo o no, el bash que usará, información de caducidad de la cuenta, etc. Veamos una línea típica de cada uno de estos ficheros y hagamos una disección de su contenido.
Empezamos por el fichero passwd. Cada línea se corresponde con un usuario y consta de siete campos en los que el separador es el signo «:». Por ejemplo así:
josemaria:x:1001:1001:Jose Maria Morales,,,:/home/josemaria:/bin/bash
El significado de cada uno de los campos es este:
1 | Nombre que el usuario utilizará en el login |
2 | Tradicionalmente aquí se encontraba la hash del password. Ahora, una x simboliza que la hash de la password se encuentra en el fichero shadow. Un * o un ! indican que la cuenta está desactivada. Por el contrario, si eliminamos la x (o cualquier otra cosa) de este campo, el sistema nos dejará entrar sin necesidad de contraseña pero sólo a través de una conexión "in situ" frente a la máquina mientras que las conexiones remotas no se permitiran. |
3 | UID del usuario |
4 | GID del grupo primario del usuario |
5 | Infomación personal del usuario. Los diferentes campos están separados por comas. |
6 | Directorio home del usuario |
7 | Path absoluto al shell por defecto que usará cuando realice una conexión interactiva. Se suele poner /bin/false cuando no queremos permitir una conexión interactiva. |
Aquí ya podemos hacer la primera «personalización» relativa a la seguridad. Si queremos que un usuario no pueda hacer una conexión interactiva con el sistema basta con que pongamos un * o un ! en el campo 2 o un shell inexistente en el campo 7 (por convención suele ponerse /bin/false). La diferencia entre usar uno u otro método es que el segundo permitirá que, aún así, esa cuenta de usuario pueda seguir usándose para otro tipo de servicios (correo, por ejemplo) mientras que si usamos el primero la cuenta quedará totalmente inutilizable para ningún servicio.
Vayamos ahora con el fichero shadow. Primero un ejemplo. Como podemos ver, en este caso tenemos 8 campos:
josemaria:$6$F3PRa1Vu$fXK1ZYXex67wi5XdbnTokhWle416I87oAtgs0ynFdhn.c6IBqrvGhmnCUC.Ue2AbLJtn9C9ZH.3pgNfSeneTF0:15675:0:99999:7:::
1 | Nombre que el usuario utilizará en el login |
2 | Se trata de un campo compuesto que contiene información del algoritmo que usará el sistema para calcular el hash, la salt que aplicaremos a la password antes de calcular este y el hash resultante. Cada uno de estos tres subcampos se separan por el símbolo $. En el ejemplo de aquí arriba el 6 del primer campo indica que usaremos SHA512 (la opción por defecto en las Debian actuales), la salt es F3PRa1Vu y el resto después del último símbolo $ es la hash ya calculada al resultado de concatenar la salt con el password. Un 5 en el primer campo indica que usaremos SHA256, un 4 SHA1, un 3 NT Hash, un 2 blowfish y un 1 MD5. Un * o un ! en este campo también indican que la cuenta está deshabilitada. |
3 | Fecha del último día en que se cambió la password indicada, como es habitual, mediante el número de días transcurridos desde el 1 de Enero de 1970 |
4 | Número mínimo de días requeridos entre cambios de contraseñas. Un 0 indica que se puede cambiar tan a menudo como se quiera. |
5 | Número máximo de días para obligar a un cambio de contraseña. Por defecto 99999. O sea, casi 274 años. O sea, nunca. |
6 | Número de días antes de que el password expire en que se mostrará un aviso al usuario indicando que debe de cambiarla. Por defecto 7 días |
7 | Número de días del periodo de gracia después de que el password expire transcurridos los cuales la cuenta será deshabilitada. En blanco por defecto (no habrá periodo de gracia). |
8 | Fecha (indicada también mediante el número de días transcurridos desde el 1 de enero de 1970) en que la cuenta será deshabilitada. En blanco por defecto (la cuenta nunca expira). |
La expiración de passwords y de cuentas de los parámetros que hemos visto se puede manejar de dos formas: editando directamente la información del fichero shadow o con el comando chage. Por ejemplo, el siguiente comando fija en 30 días la validez máxima de una contraseña para el usuario josemaria y en 2 el mínimo número de días que deben de transcurrir entre cambios:
chage -M 30 -m 2 josemaria
Otros parámetros interesantes son -d y -E para establecer la fecha del último cambio de contraseña y la de caducidad de la misma respectivamente (en formato YYYY-MM-DD), -I para establecer los días de gracia antes de desactivar la cuenta, o -W para establecer el número de días antes de la fecha de caducidad para emitir una advertencia.
También podemos cambiar todos estos datos de forma interactiva:
O listar los valores establecidos para una cuenta usando el argumento -l:
chage -l josemaria
Pero ¿Dónde se establecen estos valores por defecto para que se tengan en cuenta a la hora de crear nuevos usuarios y no tener que modificarlos uno a uno? En el fichero /etc/login.defs podemos editar los siguientes parámetros que sirven, respectivamente, para ajustar el número máximo y mínimo de días de validez de una password y la antelación a que caduque con que recibiremos una advertencia:
PASS_MAX_DAYS 60 PASS_MIN_DAYS 2 PASS_WARN_AGE 5
En el fichero /etc/default/useradd ajustamos los días de gracia en que las cuentas permarecerán activas después de caducar las contraseñas y la fecha global de expiración de las mismas:
INACTIVE=2 EXPIRE=
Un -1 en el primer campo indica que la cuenta se deshabilitará tan pronto como caduque la contraseña. Si el segundo campo está en blanco indica que la cuenta no tendrá una fecha predeterminada de expiración.
Pero la verdadera potencia en el sistema de identificación de Linux reside en la gran variedad y flexibilidad que tenemos a la hora de usar métodos que refuerzan el sistema clásico de autenticación o nos proporcionan alternativas al mismo mediante módulos adicionales. Estos módulos residen en el directorio /lib/i386-linux-gnu/security/ y se configuran a través de los ficheros que tenemos en /etc/pam.d. En este enlace podemos ver todos los disponibles en una Debian 7 estable, aun los no instalados por defecto. Empecemos por ver dos de los que vienen instalados «de serie». pam_faildelay y pam_tally nos permiten, a través del fichero /etc/pam.d/login, controlar el retraso entre varios intentos de login fallidos y la configuración de bloqueo de cuentas después de sucesivos intentos erroneos con los siguientes parámetros:
auth optional pam_faildelay.so delay=5000000 auth required pam_tally.so deny=5 unlock_time=7200
En la primera línea el retraso entre logins fallidos se especifica en microsegundos (5000000, o sea, 5 segundos). En la segunda línea decimos que tras cinco intentos de login fallido la cuenta se bloqueará durante 7200 segundos (2 horas). En una instalación limpia y por defecto la primera línea aparece configurada a 3 segundos y la segunda no aparece, es decir, la cuenta no se bloquea nunca.
El control manual de las cuentas bloqueadas o intentos fallidos de login puede llevarse mediante dos utilidades: pam_tally o faillog.
Podemos, además, consultar los datos relativos a una única cuenta de usuario con cualquiera de estos dos comandos:
pam_tally --user josemaria faillog -u josemaria
Desbloquear manualmente una cuenta o hacer un reset a los intentos fallidos de la misma así:
pam_tally --user josemaria --reset=0 faillog -r -u josemaria
O modificar el número máximo de intentos fallidos así:
faillog -m 3
El tipo de contraseñas permitidas y alguna otra característica asociada a las mismas se configura en el fichero /etc/pam.d/common-password. La configuración por defecto usa el módulo pam_unix y se define mediante esta línea:
password [success=1 default=ignore] pam_unix.so obscure sha512
El argumento obscure realiza una mínima comprobación de la complejidad de la contraseña: si esta es demasiado simple o una modificación fácilmente reproducible a partir de la anterior, mientras que sha512 define el algoritmo que se usará para guardar el hash en el fichero shadow. Otros argumentos interesantes que podemos añadir son remember, que dicta el número de contraseñas que son memorizadas por el sistema para que el usuario no las repita o minlen que fija la longitud mínima de la contraseña. Por ejemplo, para recordar las 12 contraseñas anteriores y fijar una longitud mínima de 10 caracteres modificaríamos la línea anterior así:
password [success=1 default=ignore] pam_unix.so obscure remember=12 minlen=10 sha512
El módulo pam_cracklib, que no viene instalado por defecto, nos permite una configuración mucho más flexible. Lo instalamos así:
apt-get install libpam-cracklib
Y, tras hacerlo, se nos añadirá automáticamente la siguiente línea en el fichero /etc/pam.d/common-password justo encima de la que define la forma de funcionar del módulo pam_unix:
password requisite pam_cracklib.so retry=3 minlen=8 difok=3
pam_cracklib es mucho más restrictivo que pam_unix a la hora de permitir contraseñas puesto que, además de las comprobaciones de complejidad, contrasta la password elegida por el usuario con las de un diccionario que instala en el directorio /var/cache/cracklib. Además, en su configuración por defecto que acabamos de ver exige una longitud mínima de 8 caracteres de los cuales, al menos, tres no debería de estar presentes en la password anterior (argumento difok). Otros argumentos interesantes son reject_username (rechaza contraseñas que contengan de alguna forma el nombre de usuario escrito normal o invertido) o maxrepeat=n (rechaza contraseñas con más de n caracteres iguales seguidos).
Particularmente flexible es el método que nos permite definir el tipo de caracteres que exigiremos a la contraseña. pam_cracklib considera que existen cuatro grupos de caracteres: letras mayúsculas, letras minúsculas, cifras y signos de puntuación. La forma más sencilla es definir el mínimo número de estos tipos que deberían de estar presentes en cada contraseña con el argumento minclass=n, donde n es un número entre 1 y 4.
Contamos, además, con los argumentos lcredit, ucredit, dcredit y ocredit que representan, respectivamente, a las letras minúsculas, las mayúsculas, los dígitos y los signos de puntuación, los cuatro grupos de caracteres a considerar. Cuando aparecen con valores negativos indican el mínimo número de caracteres de ese grupo con que debería de contar nuestra password. Por ejemplo, minlen= 8 ucredit=-1 lcredit=-1 dcredit=-1 indica que la contraseña debería de tener al menos una mayúscula, una minúscula y un dígito y contar con 8 caractéres mínimos de longitud. Cuando se utilizan con valores positivos, sin embargo, validan nuestra contraseña según un sistema de créditos donde minlen indicaría el número de «puntos» mínimo que validaría una contraseña como correcta. La contraseña sumaría un punto por cada carácter de longitud y los puntos correspondientes a las clases de caracteres que incluya. Pongamos, por ejemplo, que hemos establecido los argumentos minlen= 13 ucredit=1 ocredit=2 dcredit=2. La contraseña tristr4s suma diez puntos (ocho por longitud y dos más por contener un dígito) y no sería valida, mientras que Tristr4s! sumaría 14 (nueve por longitud, una por tener mayúsculas, dos por tener un dígito y otros dos por tener un signo de puntuación) y si sería permitida.
En las páginas del manual de cada uno de estos módulos puedes encontrar algunos otros argumentos interesantes.
Hola. Gracias por el post. Después de leerlo me he puesto a aplicarlo en la instalación que acabo de hacer: Debian Strech con xfce (debian-9.3.0-i386-xfce-CD-1.iso) 647MB.
Pero me he encontrado con que no aplica los cambios realizados (como root) en el fichero /etc/pam.d/login:
auth optional pam_faildelay.so delay=3000000 (cambiado a 10000000, para probar).
auth required pam_tally.so deny=3 unlock_time=120 ( he puesto 3 y 120 para probar).
La ventana de login se sigue bloqueando 3 segundos, después de introducir la password mal.
He probado a intruducirlos en /etc/pam.d/common-auth, pero tampoco se aplican los cambios, a pesar de que se pueden leer dentro de los ficheros (reinicio incluido).
¿Hay que activar algo en otro lugar y me he olvidado? ¿En la versión Strech han vuelto a cambiar demasiadas cosas?.
Gracias.
Buenas Miguel,
No se si ya has resuelto tu problema, por si aun necesitas ayuda, para solucionar lo que tu dices:
En el archivo /ect/pam.d/common-auth tienes que poner la siguiente instrucción como la primera de todas, lo puedes hacer si quieres después de unas cuantas lineas comentadas que vienen por defecto.
auth required pam_tally2.so deny=3 unlock_time=300
Esa instrucción hace que al tercer intento fallido hasta que no pasen 300 segundos no te deja volver a intentarlo.
Saludos
CSB
Consultancy
Miguel: como te comentan, la mayoría de las distribuciones han cambiado pam_tally por pam_tally2 así que sería preciso actualizar alguna de las cosas aquí escritas hace ya cuatro años. Suerte 🙂
Hola he configurado un diccionario para que el userr final no pueda poner una password que se encuentre en el diccionario. Ahora lo que no puedo hacer, especificar que usuarios deben estar dentro de esa politica por asi llamarlo. Se puede configurar por usuario. osea puedo decirle que usuarios deben pasar por el diccionario??
@Sergio: pues nunca me lo he planteado y no se si es posible… Imagino que si (¡ya sabes que en Linux se puede todo!) pero como «roundaround» mientras que encuentras la forma recuerda que el usuario administrador puede asignar la contraseña que le de la gana a quién le de la gana saltándose todas las restricciones 😉
Muchas gracias por la pronta respuesta. Si sabia que el root lo puede hacer. Pero la idea es poder dejarlo fijo y automatico. Gracias seguiremos investigando.