PAM: Conociendo la autenticación en Linux

CiberSeguridad 19 de dic. de 2023

Autenticación PAM

En Linux, la autenticación de los usuarios en el sistema está estandarizado mediante el uso de PAM (Pluggable Authentication Modules).
El uso de diferentes módulos para cada servicio facilita que cada uno de ellos no tenga que implementar el mecanismo de acceso, sino simplemente pasar las credenciales a PAM y este se encargue de indicar si el usuario tiene acceso a no.

Como varios servicios pueden establecer diferentes políticas de acceso, PAM nos permite particularizar la configuración según el servicio y personalizar su modo de funcionamiento.

Documentación sobre PAM

Si quieres tener una referencia completa sobre PAM, te recomiendo que te instales en tu equipo la documentación off-line que te proporciona Debian, para ello abre tu terminal y escribe:

sudo apt -y install libpam-doc
Instalar documentación sobre libPAM

La documentación quedará instalada en la ruta: /usr/share/doc/libpam-doc
Dentro tienes documentación en formato HTML o TXT (comprimido con gzip)

Puedes ver la documentación instalada en tu navegador escribiendo en la barra de direcciones la URL:
file:///usr/share/doc/libpam-doc/html/index.html

Ficheros y Estructura

Por defecto Linux, usará la ruta /etc/pam.d/ para localizar los ficheros necesarios que le indiquen las operaciones que debe de ejecutar para cada servicio que requiera autenticación.
En caso de que no encuentre nada allí, usará la configuración que exista en el fichero /etc/pam.conf

Dependiendo del software instalado, en la ruta /etc/pam.d si listamos su contenido veremos una serie de ficheros:

ls /etc/pam.d/

atd chfn chpasswd chsh common-account common-auth common-password
common-session common-session-noninteractive cron cups login newusers
other passwd ppp runuser runuser-l sshd su sudo sudo-i su-l

Lo primero que debemos saber es que existen 3 tipos de ficheros:

  • common-...: Son los ficheros base para la autenticación de casi todos los demás servicios.
  • other: Este fichero se usa cuando a un programa no se le haya indicado ninguna configuración.
  • Resto de ficheros: Cada programa instalará una configuración especial si necesita algún tipo de autenticación.
    Ejemplo: login (para logarse en el equipo), passwd (para permitir cambio de contraseña) ó su (como vimos en un artículo anterior).

Sintaxis de un fichero PAM para un Servicio/Aplicación

# Comentario
# La almohadilla indica que se trata de un comentario

# Incluir otro modulo/fichero PAM para simplificar sintaxis
# y carga de otras reglas existentes que queremos incluir:
@include moduloPAM

# Reglas del Servicio/Aplicación
tipo control modulo-libreria opciones-modulo

Parte de las Reglas en PAM

tipo
Existen 4 tipos de reglas:

  • auth: Autorización. Comprobación del usuario/contraseña ó credencial/token suministrados para determinar si nson válidas y pertenecen a un usuario existente.
  • account: Cuenta. Comprueba que el usuario autorizado anteriormente tiene permiso de acceso al equipo/servidor o no ya sea por limitaciones de grupos, limitación horaria, etc.
  • password: Cualquier tarea relacionada con la gestión de contraseñas (cambio de contraseña).
  • session: Gestiona los procesos que hay que ejecutar y comprobar antes de iniciar la sesión del usuario y también para los cierres de sesión (creacion/copia de ficheros, montar/desmontar filesystem, etc)

Si el valor de tipo de la lista anterior se antepone con un carácter -, la biblioteca PAM no se registrará en el registro del sistema si no es posible cargar el módulo porque falta en el sistema.
Esto puede resultar útil especialmente para módulos que no siempre están instalados en el sistema y no son necesarios para la correcta autenticación y autorización de la sesión de inicio de sesión.

Cada tipo de regla se reúne en lo que se denomina 'modulo apilado' y la evaluación se realiza para toda la pila de cada tipo. La devolución del resultado PAM se produce cuando se ha evaluado toda la pila y reglas de un mismo tipo. Además se ejecutan en el orden

control
Esta parte indica el comportamiento de PAM-API en caso de que el módulo no tenga éxito en su tarea de autenticación.
Hay dos tipos de sintaxis para este campo de control:

  • control simple: Tiene una única palabra clave simple.
  • control avanzado: Sintaxis que implica una selección entre corchetes de pares valor=acción

Control Simple
Puede tener los siguientes valores:

  • required: El error en este control PAM conducirá en última instancia a devolver un fallo de PAM-API, pero solo después de que se hayan invocado los módulos apilados restantes (para este servicio y tipo).
  • requisite:Al igual que requerido, se evalua y si no se cumple directamente se devuelve un error a la aplicación que solicito la validacion PAM. Se devuelve el error asociado al modulo requerido o que falta.
  • sufficient: Si dicho módulo tiene éxito y ningún módulo requerido anteriormente ha fallado, el marco PAM devuelve el éxito a la aplicación o a la pila PAM superior inmediatamente sin llamar a ningún módulo adicional en la pila. Se ignora una falla de un módulo suficiente y el procesamiento de la pila de módulos PAM continúa sin verse afectado.
  • optional: El éxito o el fracaso de este módulo solo es importante si es el único módulo en la pila asociado con este tipo de servicio.

Control avanzado / substack (subpila)

Un subpila/substack permite incluir una serie de controles extras a un tipo de control según una serie de argumentos u opciones para un tipo determinado.
Un subpila tiene un comportamiento diferente a un control simple ya que la subpila no provoca que se omita el resto de la pila de módulos completa, sino solo la subpila.
En un substack se pueden definir salto a otra parte de esa misma subpila para ignorar ciertas parte.
Los saltos en una subpila no pueden hacer que una evaluación salte fuera de ella. La subpila se considera como un "bloque" en su conjunto.
Si una subpila incluye por ejemplo la acción de reinicio reset, restablecerá el estado de una pila de módulos al estado en el que se encontraba al comienzo de la evaluación de la subpila.

Sintaxis no anidada (subpila)
[valor1=accion1 valor2=accion2 ... valorN=accionN]

Sintaxis anidada (subpila)
Si necesitamos incluir una serie de valores y acciones como un bloque de una subpila, hay que usar como cierre de corchetes \] en la parte interior:
[valor1=accion1 [valor21=accion21 valor22=accion22\] ... valorN=accionN]

Valores/funciones posibles a evaluar en el control

Valor Explicación
abort Error crítico.
acct_expired La cuenta de usuario ha expirado.
auth_err Error en la autenticación.
authinfo_unavail No puede accederse a la información de autenticación.
authtok_disable_aging Autenticacion con tokek deshabilitada
authtok_err Error en el uso del token de autenticación.
authtok_expired Ha caducado el Token de autenticación
authtok_lock_busy Sistema de bloque del Token ocupado
authtok_recover_err No se puede recuperar la información de autenticación.
bad_item Elemento (item) de autenticación incorrecto
buf_err Error en el buffer de memoria.
conv_again La función de negociación(conversation) depende de evento y datos que aun no están disponibles
conv_err Error en la conversación.
cred_err Error al fijar las credenciales de usuario.
cred_expired Las credenciales del usuario han caducado.
cred_insufficient Sin acceso a datos de autenticación por falta de credenciales.
cred_unavail Credenciales de usuario no disponibles.
default Cualquier valor no mencionado implícitamente.
ignore Ignorar. No considerar el módulo.
incomplete Falta algun proceso. Reiniciar el módulo para que se complete.
maxtries Numero máximo número de intentos.
module_unknown Módulo desconocido. El módulo no existe
new_authtok_reqd Se necesita un nuevo token de autenticación.
no_module_data Módulo sin datos.
open_err No puede cargarse el módulo.
perm_denied Permiso denegado.
service_err Error de servicio en el módulo.
session_err Error de sesión.
success Proceso finalizado correctamente.
symbol_err Símbolo no encontrado.
system_err Error de sistema.
try_again Reintento. Servicio de verificación preliminar mediante contraseña.
user_unknown Usuario desconocido.

Acciones/resultados con los que comparará el valor/función en el control

Accion/Resultado Explicación
bad Resultado es un fallo
die Resultado es un fallo, pero no se sigue comprobando nada
done Resultado correcto. No hace falta seguir comprobando en el substak
ignore El resultado no afecta al resultado global
ok El módulo acabo correctamente
reset Se resetea el resultado global del proceso/substack
N (número) Número de directivas del substack que se saltarán

Módulo - Librería

En esta parte de la regla, hay que especificar que librería del sistema es la encargada de realizar la tarea que se le pida (auth, account, password, session) para poder usar las funciones internas que realicen esa validación.
El nombre de estos módulos/librerías son `nombre_libreria.so`

Dependiendo del sistema y la arquitectura, la ruta de ubicación de estas librerías de seguridad (security) puede ser diferente.

Ejemplos de rutas para security:

/lib/security
/lib64/security
/usr/lib/security
/usr/lib64/security
...
/usr/lib/x86_64-linux-gnu/security

Opciones del Módulo

Esta última parte de la regla, podemos detallar exactamente que es lo que esperamos obtener para que la regla aplique unos valores u otros y nos diga si se puede autenticar al usuario, puede cambiar la clave, etc.

Ejemplo y Explicación

Si tenemos por ejemplo una regla como la siguiente para una aplicación:

Línea| Regla
........................
Lin 1| auth     [success=2 default=ignore]    pam_unix.so nullok_secure
Lin 2| auth [success=1 default=ignore] pam_ldap.so use_first_pass minimum_uid=1000
Lin 3| auth     requisite         pam_deny.so
Lin 4| auth     required          pam_permit.so
........................

Linea 1: Al llegar a esta parte, se carga el modulo de autenticación de unix (pam_unix.so) se comprueba con nullok_secure, si el usuario es local (success=2) y se saltan las siguiente 2 lineas del modulo del substack y comprobará la línea 4 (pam_permit) y accedería como usuario.
En caso caso de fallo simplemente se ignora (default=ignore) e iría a la siguiente línea de las reglas (línea 2).

Línea 2: Se cargan las libreria de ldap (pam_ldap.so) y se verifica que su UID sea mayor que 1000 (mininum_uid=1000) y se comprueba la autenticación el usuario. Si es correcto (success=1) se salta una línea y ejecutará la línea 4 (que permite acceder al usuario).
Si falla, continuará (default=ignore) y ejecutará la siguiente línea (línea 3) en la que se le deniega el acceso.

Línea 3: Todo los que pasa por esta linea marcada como requisito (requisite) produce una denegación de acceso.

Línea 4: Todo lo que pase por esta línea marcada como obligatoria (required) permitirá el acceso.

Otro ejemplo

En el artículo anterior usamos el modulo `su` de PAM para modificar su comportamiento e incluimos:

Línea  | Regla 
........................
Línea 1| auth [success=ignore default=1] pam_succeed_if.so user = tomato
Línea 2| auth sufficient pam_succeed_if.so use_uid user ingroup tomato
........................

En este caso si el usuario es tomato (él mismo) se ignora (success=ignore) y se salta una línea (default=1), continuando con los procesos que tenga definidos.

En la siguiente línea es suficiente (sufficiente) con que el UID del usuario esté dentro el grupo (ingroup tomato) y se indica que la validación se ha completado y se continuará con los procesos definidos dentro del módulo su.

Esquema del funcionamiento PAM

  ╔════════════════╗
  ║ Aplicacion: X  ║
  ╠════════════════╣        /  ┌───────────┐     ╔═════════════════╗
  │ Autenticación  ├──⊳──⊳──\──┤           ├──⊲──╣ Fich config PAM ║
  │       +        ├──⊲──⊲──/──┤ Linux-PAM │     ╠═════════════════╣
  │[Conversación()]├───┐    \  │           │     │ X auth .. a.so  │
  ├────────────────┤   │       └────┬──────┘     │ X auth .. b.so  │
  │    Usuario     │   │      ┌─────┤            │          ┌──────┘
  │      del       │   ∆      │     │            └──────────┘
  │    servicio    │   │      ∇     ∆
  └────────────────┘   └──────┼─────┼─────────┬──────┬──────┐
                              │     │         │      │      │
                          ┌───┴─────┴───┐     │      │      │
                          │   auth      ├───[ a ]──[ b ]──[ c ]
                          ├─────────────┤
                          │   account   ├───[ b ]──[ d ]
                          ├─────────────┤
                          │   password  ├───[ b ]──[ c ]
                          ├─────────────┤
                          │   session   ├───[ e ]──[ c ]
                          └─────────────┘

A la izquierda del todo tenemos la Aplicación X, con la que el usuario se va a conectar.
La aplicación X interactúa con la biblioteca Linux-PAM (en el centro) que consulta si hay algún archivo de autenticación configurada para ella y carga las librerías/módulos (ficheros .so) del sistema para la aplicación.

Estos módulos pueden tener 4 tipos de gestión (parte de abajo). Apilados según el orden de la configuración de las reglas: auth, account, password y/o session.

Se inicia una "conversación" con el contenido de la regla definida y las opciones que se encuentren el en el fichero PAM para cada tipo se permitirá o no el acceso al usuario.
La evaluación se realiza por el conjunto de la "pila": auth+account+password+session y no son obligatorias todas las evaluaciones.

Si un programa va a utilizar PAM, entonces debe tener funciones PAM definidas explícitamente en su código o no podrá usar PAM.
En cualquier momento (si se dispone del código fuente del programa) se pueden implementar fácilmente las funciones PAM apropiadas para implementar la autenticación mediante Linux-PAM.

Si instaló libpam-doc en su equipo, puede ver cómo implementar el uso de PAM en su aplicación.

Etiquetas

Luis GuLo

🐧 SysAdmin GNU/Linux - 🐳 Docker - 🖥️ Bash Scripting - 🐪 Perl - 🐬 MySQL - 👥 Formador de TI - 👥 Formador de SysAdmin's - 💢 Ansible - ☁️ Cloud Computing - ❤️ Debian GNU/Linux