GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo crear una entrada PAM condicional

Aquí hay una solución que funciona para mí. Mi /etc/pam.d/sudo :

#%PAM-1.0
auth            [success=1]     pam_exec.so    /tmp/test-pam
auth            required        pam_deny.so
auth            include         system-auth
account         include         system-auth
session         include         system-auth

Y /tmp/test-pam :

#! /bin/bash
/bin/last -i -p now ${PAM_TTY#/dev/} | \
    /bin/awk 'NR==1 { if ($3 != "0.0.0.0") exit 9; exit 0; }'

Obtengo este comportamiento:

$ sudo date
[sudo] password for jdoe:
Thu Jun 28 23:51:58 MDT 2018
$ ssh localhost
Last login: Thu Jun 28 23:40:23 2018 from ::1
valli$ sudo date
/tmp/test-pam failed: exit code 9
[sudo] password for jdoe:
sudo: PAM authentication error: System error
valli$

La primera línea agregada al pam.d/sudo predeterminado llamadas pam_exec y, si tiene éxito, salta la siguiente entrada. La segunda línea simplemente niega el acceso incondicionalmente.

En /tmp/test-pam Llamo a last para obtener la dirección IP asociada con el TTY desde el que se invocó pam. ${PAM_TTY#/dev/} elimina /dev/ desde el frente del valor, porque last no reconoce la ruta completa del dispositivo. El -i bandera hace last muestra la dirección IP o el marcador de posición 0.0.0.0 si no hay dirección IP; de forma predeterminada, muestra una cadena de información que es mucho más difícil de verificar. Esta es también la razón por la que usé last en lugar de who o w; esos no tienen una opción similar. El -p now la opción no es estrictamente necesaria, como veremos awk solo está comprobando la primera línea de salida, pero restringe last para mostrar solo los usuarios que actualmente están conectados.

El awk el comando solo verifica la primera línea, y si el tercer campo no es 0.0.0.0 sale con un error. Dado que este es el último comando en /tmp/test-pam , el código de salida de awk se convierte en el código de salida del script.

En mi sistema, ninguna de las pruebas que intentabas en tu deny-ssh-user.sh trabajaría. Si pones env > /tmp/test-pam.log en la parte superior de su secuencia de comandos, verá que se ha eliminado el entorno, por lo que no se establecerá ninguna de sus variables SSH_FOO. Y $PPID podría apuntar a cualquier número de procesos. Por ejemplo, ejecute perl -e 'system("sudo cat /etc/passwd")' y vea que $PPID se refiere al perl proceso.

Esto es Arch Linux, núcleo 4.16.11-1-ARCH , en caso de que importe. Sin embargo, no creo que deba hacerlo.


Bueno, resulta que en realidad soy un idiota, el pam_exec.so El módulo está perfectamente bien para crear condicionales PAM.

Tim Smith tenía razón al evaluar que ambas pruebas en mi /etc/security/deny-ssh-user.sh el script NUNCA estableció la variable SSH_SESSION a la verdad No tomé eso en consideración porque el script funciona en un shell normal, pero el contexto del entorno se elimina cuando lo ejecuta pam_exec.so .

Terminé reescribiendo el script para usar el last utilidad como su ejemplo, sin embargo, tuve que cambiar algo porque los interruptores para last difieren de Arch Linux a RedHat.

Aquí está el script revisado en /etc/security/deny-ssh-user.sh:

#!/bin/bash
# Returns 1 if the user is logged in through SSH
# Returns 0 if the user is not logged in through SSH
SSH_SESSION=false

function isSshSession {
    local terminal="${1}"
    if $(/usr/bin/last -i | 
        /usr/bin/grep "${terminal}" |
        /usr/bin/grep 'still logged in' |
        /usr/bin/awk '{print $3}' |
        /usr/bin/grep -q --invert-match '0\.0\.0\.0'); then
        echo true
    else
        echo false
    fi
}

function stripTerminal {
    local terminal="${1}"

    # PAM_TTY is in the form /dev/pts/X
    # Last utility displays TTY in the form pts/x
    # Returns the first five characters stripped from TTY
    echo "${terminal:5}"
}

lastTerminal=$( stripTerminal "${PAM_TTY}")
SSH_SESSION=$(isSshSession "${lastTerminal}")

if "${SSH_SESSION}"; then
    exit 1
else
    exit 0
fi

Contenido de /etc/pam.d/sudo

....
auth    [success=ok default=1]    pam_exec.so /etc/security/deny-ssh-user.sh
auth    sufficient    pam_module_to_skip.so
....

Linux
  1. Cómo crear un script de un comando de Linux

  2. Cómo crear un libro de jugadas de Ansible

  3. Cómo crear etiquetas Git

  4. Cómo crear un subdominio

  5. Cómo crear un enlace a un directorio

Cómo crear un StatefulSet en Kubernetes

Cómo crear una cola SQS en AWS

Cómo crear una tabla de DynamoDB en AWS

Cómo crear accesos directos en el escritorio de Linux

Cómo crear un alias SSH en Linux

Cómo crear un alias en Linux