On time password – modulo PAM para Linux
Para las máquinas que deben tener el puerto del SSH abierto a internet tenemos muchos métodos para evitar ataques automátizados, cómo pam_catcha, usar el hosts.deny mediante DenyHosts o el cambio del puerto por defecto a uno más alto.
¿Que hacemos contra los ataques manuales? ¿Que ocurre si a un usuario le hacen un man-in-the-middle porque no verifica el fingerprint? Podemos utilizar los one time passwords mediante un token o un soft-token, pero podemos tener un problema en el caso de perdida el token o si en el momento que lo necesitamos no lo tenemos. Podemos reducir el problema teniendo en cuenta únicamente la hora del sistema (ON time) y un par de cadenas de salt. Así ha nacido el pam_ontimepassword
Éste modulo, inspirado en el pam_catcha, añade un paso más a la autenticación por ssh, en función de la hora del servidor. Para pasar la autenticación de pam_ontimepassword deberemos mirar primero la hora y añadir una cadena de prefijo y otra de sufijo, separadas por espacios, calculando el md5 del conjunto. Por ejemplo, para las 20h y el prefijo “pam” y el sufijo “ontimepassword” podríamos hacer:
# echo -n 'pam 20 onlinepassword' | md5sum 549c1816681de9d873a3967d2ac3596e -
Es muy importante la opción -n del echo ya que sino se añade un intro (\n) al final de la cadena, por lo que el md5 resultante sería diferente.
De esta forma en caso que a un usuario le hicieran un ataque man-in-the-middle como mucho podrían hacer login mientras sea válido el hash de la hora que haya accedido. Por otro lado se pueden generar los 24 hashs y darlo al usuario con una única sencilla regla: En función de la hora se usa la hash que corresponda.
Desde Google Code se puede descargar un paquete con la primera versión de pam_ontimepassword, lo compilamos y lo instalamos con make:
$ cd /usr/local/src $ wget http://ontimepassword.googlecode.com/files/pam_ontimepassword-0.2.tgz $ tar xzf pam_ontimepassword-0.2.tgz $ cd pam_ontimepassword-0.2 $ make gcc -Wunused -c -fPIC -DHAVE_SHADOW -O2 md5.c 2>/dev/null gcc -Wunused -c -fPIC -D_STEALTH_MODE_ -DHAVE_SHADOW -O2 pam_ontimepassword.c gcc -o pam_ontimepassword.so -s -lpam -lcrypt --shared pam_ontimepassword.o md5.o $ sudo make install cp pam_ontimepassword.so /lib/security
A continuación deberemos editar el fichero /etc/pam.d/sshd para añadir el modulo:
auth required pam_ontimepassword.so
Si no añadimos ninguna opción, por defecto, el prefijo es “systemadmin.es” y el sufijo es “6,693*10^–11“. Para personalizar las cadenas simplemente las añadimos a continuación del modulo en el fichero /etc/pam.d/sshd, por ejemplo:
auth required pam_ontimepassword.so prefijo sufijo
A continuación deberemos modificar la configuración del servidor ssh, en el fichero /etc/ssh/sshd_config deshabilitando el acceso por password y habilitando la autenticación por keyborard-interactive:
PasswordAuthentication no ChallengeResponseAuthentication yes UsePAM yes
En la compilación por defecto (o mediante make stealth) y con las cadenas por defecto haríamos lo siguiente:
$ date Sun Sep 12 13:01:26 CEST 2010 $ echo -n 'systemadmin.es 13 6,693*10^–11' | md5sum 5f0c5473c371f13bc57dcc01bea956a6 - $ ssh -l jordi localhost Password: Password: Last login: Sun Sep 12 12:37:56 2010 from localhost
La primera contraseña es el hash que hemos calculado y la segunda la contraseña del usuario con el que conectamos. En este caso no obtendremos ninguna información si se ha validado o no la hash.
En el caso de substituir el make por make ontime el prompt nos dará más pistas para que no nos despistemos al intentar autenticar. En el caso que demos la hash correcta dice “Said the joker to the thief” y en caso contrario “There must be some kind of way out of here“:
$ date Sun Sep 12 14:37:44 CEST 2010 $ echo -n 'systemadmin.es 14 6,693*10^–11' | md5sum f0937d239c0b222a5e33b71216641b92 - $ ssh -l jordi localhost what time is it?: Said the joker to the thief Password: Last login: Sun Sep 12 14:36:23 2010 from localhost
Finalmente en el caso de usar make fortune obtendremos unas frases aleatorias al solicitar la hash:
$ date Sun Sep 12 14:38:33 CEST 2010 $ echo -n 'systemadmin.es 14 6,693*10^–11' | md5sum f0937d239c0b222a5e33b71216641b92 - $ ssh -l jprats localhost Necesitaras algo mes que un password de res per entrar aqui ------------------------------------------------------------- a q te meto un troyano q ja veras: Said the joker to the thief Password: Last login: Sun Sep 12 14:38:12 2010 from localhost
Relacionados
Imprimir
17. September 2010 at 8:20 am :
Muy interesante el artículo. No conocía el pam_catcha, pero lo voy a usar para un problema que tengo:
Forzar a mis usuarios “administradores” (DBAs, administradores de aplicación y desarrolladores) a que no hagan directamente “sudo” a root, sino al usuario del servicio que les toque (oracle, was, etc.) pero sin quitarles el acceso a root.
Por cierto, hay una página para md5: https://www.md5.cz/ (claro que estás mandando la password a un página que no conoces).
17. September 2010 at 8:22 am :
Me gusta!!!
17. September 2010 at 9:40 am :
Hola
muy útil todo lo que has escrito, pero supongo que cuando dices “auth required pam_captcha.so” te refieres a “auth required pam_onetimepassword.so”
Por otro lado decir que lo he probado y no me ha llegado a funcionar :/ En /etc/pam.d/sshd le indico un prefijo y un sufijo, y luego al autenticar hago el md5sum de la cadena prefijo, más la hora, más el sufijo y nanai….. En fin, cosas que pasan.
Buen post!
17. September 2010 at 10:13 am :
Que raro, para ver que ocurre puedes editar el fichero pam_ontimepassword.c descomentando lo siguiente:
En el /var/log/secure te aparecerá la cadena y el md5 que debería ser. Es possible que hagas el md5 sin el -n en el echo?
Ya he corregido el proceso de instalación arriba. Muchas gracias!
17. September 2010 at 10:17 am :
Pasteo los pasos tal cual los acabo de hacer para dar una idea completa de la instalación:
17. September 2010 at 10:46 am :
Hola Jordi,
en mi máquina loguea en /var/log/auth.log, pero para el caso da lo mismo. El tema está en que activando LOG_HASH en auth.log veo que el hash que pasteo en el login ssh no es el mismo que el que se loguea
Usando el mismo prefijo y sufijo que tú, en auth.log me saca un hash con valor 10727091195432214abf985a26a218ea; cuando el que he introducido es 53cf02be1a2969a7e934b05d4af2f60a.
NOTA: utilizo -n con el comando echo; por ahí no van los tiros
17. September 2010 at 11:10 am :
También te dice la cadena, por ejemplo:
Puedes pasar lo que te sale en el log?
17. September 2010 at 11:24 am :
Estamos hablando de lo mismo. El hash que te he posteado antes es del log; pero de todas maneras te paso la cadena completa:
Sep 17 12:21:11 kagate pam_ontimepassword: User damon failed to pass the on time password (from localhost.localdomain) - lol 12 systemadmin: 4d27c8165f500e93a31c84c6a3f81b8e
El hash que he introducido ha sido f5265f8f5223b5028210551d22e4e4eb
17. September 2010 at 11:58 am :
Ya lo he encontrado, la librería de RSA que he usado utiliza long que en una arquitectura de 32 bits son 4 bytes, pero en 64 son 8 bytes. Por lo que genera mal el hash para arquitecturas de 64 bits:
32 bits:
64 bits:
Voy a ver que puedo hacer
17. September 2010 at 12:02 pm :
Sí, es eso seguro porque la arquitectura que yo utilizo es de 64 bits.
Gracias, estás hecho un crack
17. September 2010 at 12:22 pm :
Ya esta solucionado el tema cambiando de unsigned long a unsigned int (podeis ver la diferéncia en el svn).
He colgado un paquete nuevo con los cambios pam_ontimepassword-0.2.tgz y he actualizado el post con la nueva versión.
Muchas gracias por avisar de este fallo
17. September 2010 at 3:45 pm :
Ya me funciona perfecto.
Gracias a tí por solucionarlo
17. September 2010 at 8:49 pm :
Está bien usar métodos de desafío para evitar robots pero tienen que ser algo cómodos para el usuario habitual.
El modulo ontimepassword , salvo que lo haya entendido mal ( que es bastante posible ), requiere :
- obtener la hora del servidor, que no tiene por que coincidir con la hora local. Sería un ‘rdate’ ( nos siempre posible) o acordarte de este pequeño inconveniente y hacer un ‘date’
- calcular el hash MD5 con un prefijo y un sufijo. Estos prefijos y sufijos te los tiene que proporcionar el servidor por un canal seguro. Esto me parece una molestia comparado con pam_captcha
- en caso de comprometerse el hash, comenta que “sólo” es 1 hora. ¿¿ Sólo ??
Si el módulo precisase a nivel de minuto, otro problema sería que siempre hay que hacer ‘rdate’ contra el servidor y como decía antes, esto no siempre es posible.
No me ha convencido