Esta es una idea de seguridad. Nuestros empleados tendrán acceso a algunos comandos en un servidor Linux, pero no a todos. Por ejemplo, deberán tener la posibilidad de acceder a un archivo de registro ( less logfile
) o iniciar diferentes comandos ( shutdown.sh
/ run.sh
).
Información de contexto:
Todos los empleados acceden al servidor con el mismo nombre de usuario: nuestro producto se ejecuta con permisos de usuario "normales", no se necesita "instalación". Simplemente descomprímalo en su directorio de usuario y ejecútelo. Gestionamos varios servidores donde está "instalada" nuestra aplicación. En cada máquina hay un usuario johndoe
. A veces, nuestros empleados necesitan acceder a la aplicación en la línea de comandos para acceder y comprobar los archivos de registro o para reiniciar la aplicación manualmente. Solo algunas personas tendrán acceso completo a la línea de comandos.
Estamos usando la autenticación ppk en el servidor.
Sería genial si employee1 solo pudiera acceder al archivo de registro y employee2 también pudiera hacer X, etc.
Solución:
como solución, usaré la command
opción como se indica en la respuesta aceptada . Haré mi propio pequeño script de shell que será el único archivo que se puede ejecutar para algunos empleados. El script ofrecerá varios comandos que se pueden ejecutar, pero ningún otro. Usaré los siguientes parámetros authorized_keys
como se indica aquí :
command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host
Esto es suficiente seguridad para nosotros. ¡Gracias, comunidad!
Respuestas:
También puede restringir las claves a los comandos permitidos (en el archivo Authorized_keys).
Es decir, el usuario no iniciaría sesión a través de ssh y luego tendría un conjunto restringido de comandos, sino que solo se le permitiría ejecutar esos comandos a través de ssh (por ejemplo, "ssh somehost bin / showlogfile")
fuente
ssh
sigue larsh
tradición al usar el programa de shell del usuario del archivo de contraseña para ejecutar comandos.Esto significa que podemos resolver esto sin involucrar la
ssh
configuración de ninguna manera.Si no desea que el usuario pueda tener acceso al shell, simplemente reemplace el shell de ese usuario con un script. Si mira
/etc/passwd
, verá que hay un campo que asigna un intérprete de comandos de shell a cada usuario. El script se utiliza como shell tanto para su inicio de sesión interactivossh user@host
como para los comandosssh user@host command arg ...
.Aquí hay un ejemplo. Creé un usuario
foo
cuyo shell es un script. El script imprime el mensajemy arguments are:
seguido de sus argumentos (cada uno en una línea separada y entre paréntesis angulares) y termina. En el caso de registro, no hay argumentos. Esto es lo que sucede:webserver:~# ssh foo@localhost foo@localhost's password: Linux webserver [ snip ] [ snip ] my arguments are: Connection to localhost closed.
Si el usuario intenta ejecutar un comando, se verá así:
webserver:~# ssh foo@localhost cat /etc/passwd foo@localhost's password: my arguments are: <-c> <cat /etc/passwd>
Nuestro "caparazón" recibe un
-c
invocación de estilo, con el comando completo como un argumento, de la misma manera que/bin/sh
lo recibiría.Entonces, como puede ver, lo que podemos hacer ahora es desarrollar más el script para que reconozca el caso cuando ha sido invocado con un
-c
argumento, y luego analiza la cadena (digamos, por coincidencia de patrones). Las cadenas permitidas se pueden pasar al shell real invocando de forma recursiva/bin/bash -c <string>
. El caso de rechazo puede imprimir un mensaje de error y terminar (incluido el caso cuando-c
falta).Tienes que tener cuidado al escribir esto. Recomiendo escribir solo coincidencias positivas que permitan solo cosas muy específicas y no permitan todo lo demás.
Nota: si es así
root
, aún puede iniciar sesión en esta cuenta anulando el shell en elsu
comando, asísu -s /bin/bash foo
. (Shell sustituto de su elección). No root no puede hacer esto.Aquí hay un script de ejemplo: restrinja al usuario a usar solo
ssh
paragit
acceder a los repositorios bajo/git
.#!/bin/sh if [ $# -ne 2 ] || [ "$1" != "-c" ] ; then printf "interactive login not permitted\n" exit 1 fi set -- $2 if [ $# != 2 ] ; then printf "wrong number of arguments\n" exit 1 fi case "$1" in ( git-upload-pack | git-receive-pack ) ;; # continue execution ( * ) printf "command not allowed\n" exit 1 ;; esac # Canonicalize the path name: we don't want escape out of # git via ../ path components. gitpath=$(readlink -f "$2") # GNU Coreutils specific case "$gitpath" in ( /git/* ) ;; # continue execution ( * ) printf "access denied outside of /git\n" exit 1 ;; esac if ! [ -e "$gitpath" ] ; then printf "that git repo doesn't exist\n" exit 1 fi "$1" "$gitpath"
Por supuesto, estamos confiando en que estos programas de Git
git-upload-pack
ygit-receive-pack
no tienen agujeros o trampillas de evacuación que le darán a los usuarios el acceso al sistema.Eso es inherente a este tipo de esquema de restricción. El usuario está autenticado para ejecutar código en un determinado dominio de seguridad, y estamos imponiendo una restricción para limitar ese dominio a un subdominio. Por ejemplo, si permite que un usuario ejecute el
vim
comando en un archivo específico para editarlo, el usuario puede obtener un shell con:!sh[Enter]
.fuente
git-receive-pack '/git/';dd if=/dev/urandom of=/dev/sda
?case
no me parece correcto./bin/bash -c "$2"
es inseguro (similar a cómo funciona la inyección SQL). Puede filtrar la cadena con "comillas mágicas" como PHP. Pero la manera más fácil de garantizar la seguridad es llamar a un comando manualmente y luego pasar los parámetros entre comillas dobles. Porque la seguridad de todo depende de que ese comando sea el enlace más débil (más difícil de verificar). Lo más interesante es ver cómo tu respuesta tiene 22 votos a favor, pero nadie se dio cuenta de esto;) ¿Actualizarás tu propia respuesta?set
y luego toma solo las dos primeras palabras. El primero debe ser ungit-
comando permitido y el segundo debe ser una ruta que se canonicalice, se verifique con el prefijo permitido y también se verifique su existencia. ¿Puedes pensar en alguna forma de romper esto?Lo que está buscando se llama Shell restringido . Bash proporciona un modo en el que los usuarios solo pueden ejecutar comandos presentes en sus directorios de inicio (y no pueden moverse a otros directorios), lo que podría ser lo suficientemente bueno para usted.
Encontré este hilo muy ilustrativo, aunque un poco anticuado.
fuente
Debería adquirir `rssh ', el shell restringido
Puede seguir las guías de restricción mencionadas anteriormente, todas se explican por sí mismas y son fáciles de seguir. Comprenda los términos "jail chroot" y cómo implementar de manera efectiva las configuraciones de sshd / terminal, y así sucesivamente.
Dado que la mayoría de sus usuarios acceden a sus terminales a través de sshd, probablemente también debería buscar en sshd_conifg, el archivo de configuración del demonio SSH, para aplicar ciertas restricciones a través de SSH. Sin embargo, tenga cuidado. Comprenda correctamente lo que intenta implementar, ya que las ramificaciones de configuraciones incorrectas probablemente sean bastante espantosas.
fuente
rssh
fue eliminado de Debian Buster. Creo que el nuevo atractivo es GNU rush .¿Por qué no escribe su propio shell de inicio de sesión? Sería bastante simple usar Bash para esto, pero puede usar cualquier idioma.
Ejemplo en Bash
Utilice su editor favorito para crear el archivo
/root/rbash.sh
(puede ser cualquier nombre o ruta, pero debería serchown root:root
ychmod 700
):#!/bin/bash commands=("man" "pwd" "ls" "whoami") timestamp(){ date +'%Y-%m-%s %H:%M:%S'; } log(){ echo -e "$(timestamp)\t$1\t$(whoami)\t$2" > /var/log/rbash.log; } trycmd() { # Provide an option to exit the shell if [[ "$ln" == "exit" ]] || [[ "$ln" == "q" ]] then exit # You can do exact string matching for some alias: elif [[ "$ln" == "help" ]] then echo "Type exit or q to quit." echo "Commands you can use:" echo " help" echo " echo" echo "${commands[@]}" | tr ' ' '\n' | awk '{print " " $0}' # You can use custom regular expression matching: elif [[ "$ln" =~ ^echo\ .*$ ]] then ln="${ln:5}" echo "$ln" # Beware, these double quotes are important to prevent malicious injection # For example, optionally you can log this command log COMMAND "echo $ln" # Or you could even check an array of commands: else ok=false for cmd in "${commands[@]}" do if [[ "$cmd" == "$ln" ]] then ok=true fi done if $ok then $ln else log DENIED "$cmd" fi fi } # Optionally show a friendly welcome-message with instructions since it is a custom shell echo "$(timestamp) Welcome, $(whoami). Type 'help' for information." # Optionally log the login log LOGIN "$@" # Optionally log the logout trap "trap=\"\";log LOGOUT;exit" EXIT # Optionally check for '-c custom_command' arguments passed directly to shell # Then you can also use ssh user@host custom_command, which will execute /root/rbash.sh if [[ "$1" == "-c" ]] then shift trycmd "$@" else while echo -n "> " && read ln do trycmd "$ln" done fi
Todo lo que tiene que hacer es configurar este ejecutable como su shell de inicio de sesión. Por ejemplo, edite su
/etc/passwd
archivo y reemplace su shell de inicio de sesión actual de ese usuario/bin/bash
con/root/rbash.sh
.Este es solo un ejemplo simple, pero puede hacerlo tan avanzado como desee, la idea está ahí. Tenga cuidado de no bloquearse cambiando el shell de inicio de sesión de su propio usuario. Y siempre pruebe los símbolos y comandos extraños para ver si es realmente seguro.
Puede probarlo con:
su -s /root/rbash.sh
.¡Cuidado , asegúrese de hacer coincidir todo el comando y tenga cuidado con los comodines! Mejor excluye Bash-símbolos tales como
;
,&
,&&
,||
,$
, y acentos abiertos para estar seguro.Dependiendo de la libertad que le dé al usuario, no será mucho más seguro que esto. Descubrí que a menudo solo necesitaba crear un usuario que tuviera acceso a solo unos pocos comandos relevantes, y en ese caso, esta es realmente la mejor solución. Sin embargo, si desea dar más libertad, una cárcel y permisos podrían ser más apropiados. Los errores se cometen fácilmente y solo se notan cuando ya es demasiado tarde.
fuente
ln="service httpd restart"
, con:${ln[@]}
. Aún así, asegúrese de pensar en los problemas de seguridad, una lista blanca solo para caracteres alfanuméricos y espacios en blanco sería útil en tal caso. Pero también puede simplemente hacer:if [[ "$ln" == "restart-httpd"];then service httpd restart;fi
y trabajar con comandos simples como ese./root/rbash.sh: Permission denied
Probé chmod 777 también/root/rbash.sh
a/etc/shells
? Depende de la distribución. También puede intentar deshabilitar temporalmenteselinux
y verificar los mensajes de registro en busca de pistas (mire la marca de tiempo) en archivos en formato/var/log
.Es posible que desee considerar la instalación de una cárcel .
fuente
GNU Rush puede ser la forma más flexible y segura de lograr esto:
fuente
Otra forma de ver esto es usando POSIX ACL, necesita ser compatible con su sistema de archivos, sin embargo, puede tener un ajuste detallado de todos los comandos en Linux de la misma manera que tiene el mismo control en Windows (solo que sin la interfaz de usuario más agradable ). enlace
Otra cosa a considerar es PolicyKit .
Tendrá que buscar bastante en Google para que todo funcione, ya que definitivamente no es una fortaleza de Linux en este momento.
fuente
[Divulgación: escribí sshdo que se describe a continuación]
Si desea que el inicio de sesión sea interactivo, configurar un shell restringido probablemente sea la respuesta correcta. Pero si hay un conjunto real de comandos que desea permitir (y nada más) y está bien que estos comandos se ejecuten individualmente a través de ssh (por ejemplo, ssh user @ host cmd arg blah blah), entonces un control genérico de lista blanca de comandos para ssh podría ser lo que necesita. Esto es útil cuando los comandos están programados de alguna manera en el extremo del cliente y no requiere que el usuario escriba realmente el comando ssh.
Hay un programa llamado sshdo para hacer esto. Controla qué comandos se pueden ejecutar a través de conexiones ssh entrantes. Está disponible para descargar en:
http://raf.org/sshdo/ (lea las páginas del manual aquí) https://github.com/raforg/sshdo/
Tiene un modo de entrenamiento para permitir todos los comandos que se intentan y una opción --learn para producir la configuración necesaria para permitir los comandos aprendidos de forma permanente. Entonces el modo de entrenamiento se puede desactivar y no se ejecutará ningún otro comando.
También tiene una opción --unlearn para dejar de permitir comandos que ya no están en uso para mantener el mínimo privilegio estricto a medida que los requisitos cambian con el tiempo.
Es muy quisquilloso con lo que permite. No permitirá un comando con argumentos. Solo se pueden permitir comandos de shell completos.
Pero admite patrones simples para representar comandos similares que varían solo en los dígitos que aparecen en la línea de comando (por ejemplo, números de secuencia o sellos de fecha / hora).
Es como un firewall o un control de lista blanca para comandos ssh.
Y admite diferentes comandos permitidos para diferentes usuarios.
fuente