systemadmin.es > Seguridad > On time password – modulo PAM para Linux

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

13 comments to “On time password – modulo PAM para Linux”

  1. 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).

  2. Me gusta!!! :D

  3. 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!

  4. Que raro, para ver que ocurre puedes editar el fichero pam_ontimepassword.c descomentando lo siguiente:

    #define _LOG_HASH_
    

    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!

  5. Pasteo los pasos tal cual los acabo de hacer para dar una idea completa de la instalación:

    $ wget http://ontimepassword.googlecode.com/files/pam_ontimepassword-0.1.tgz
    --2010-09-17 11:14:42--  http://ontimepassword.googlecode.com/files/pam_ontimepassword-0.1.tgz
    Resolving ontimepassword.googlecode.com... 72.14.255.82
    Connecting to ontimepassword.googlecode.com|72.14.255.82|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 6603 (6.4K) [application/x-gzip]
    Saving to: “pam_ontimepassword-0.1.tgz”
    
    100%[====================================================================================================================================================================>] 6,603       --.-K/s   in 0.1s    
    
    2010-09-17 11:14:42 (58.9 KB/s) - “pam_ontimepassword-0.1.tgz” saved [6603/6603]
    
    $ tar xzf pam_ontimepassword-0.1.tgz 
    $ cd pam_ontimepassword-0.1
    [jprats@picamoixons pam_ontimepassword-0.1]$ ls
    Makefile  md5.c  md5.h  pam_ontimepassword.c
    $ 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
    $ sudo vi /etc/pam.d/sshd 
    $ sudo cat /etc/pam.d/sshd
    #%PAM-1.0
    auth	   required	pam_sepermit.so
    auth	   required	pam_ontimepassword.so lol systemadmin
    auth       include      password-auth
    account    required     pam_nologin.so
    account    include      password-auth
    password   include      password-auth
    # pam_selinux.so close should be the first session rule
    session    required     pam_selinux.so close
    session    required     pam_loginuid.so
    # pam_selinux.so open should only be followed by sessions to be executed in the user context
    session    required     pam_selinux.so open env_params
    session    optional     pam_keyinit.so force revoke
    session    include      password-auth
    $ date
    Fri Sep 17 11:15:29 CEST 2010
    $ echo -n 'lol 11 systemadmin' | md5sum 
    53cf02be1a2969a7e934b05d4af2f60a  -
    $ ssh -l jprats localhost
    Password: 
    Password: 
    Last login: Thu Sep 16 20:52:13 2010 from localhost
    $ 
    
  6. 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 :)

  7. También te dice la cadena, por ejemplo:

    Sep 17 12:06:44 picamoixons pam_ontimepassword: User jprats passed the on time password (from localhost) - lol 12 systemadmin: f5265f8f5223b5028210551d22e4e4eb
    

    Puedes pasar lo que te sale en el log?

  8. 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

  9. 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:

    $ uname -i
    i386
    $ ./md5driver -sejemplo
    2f1767dc31e7a8dc68b2c21bf07984ff "ejemplo"
    

    64 bits:

    $ uname -i
    x86_64
    $ ./md5driver -sejemplo
    ea4ab9636e16fd6864f7ab12927a258a "ejemplo"
    

    Voy a ver que puedo hacer

  10. Sí, es eso seguro porque la arquitectura que yo utilizo es de 64 bits.

    Gracias, estás hecho un crack :)

  11. 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 :)

  12. Ya me funciona perfecto.
    Gracias a tí por solucionarlo :)

  13. 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

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>