Como restringir os usuários SSH a um conjunto predefinido de comandos após início de sessão?

StackOverflow https://stackoverflow.com/questions/402615

  •  03-07-2019
  •  | 
  •  

Pergunta

Esta é uma idéia para um segurança. Nossos funcionários terão acesso a alguns comandos em um servidor linux, mas não todos. Eles devem, por exemplo, têm a possibilidade de acessar um arquivo de log (less logfile) ou iniciar comandos diferentes (shutdown.sh / run.sh).

Informações gerais:

Todos os empregados acessar o servidor com o mesmo nome de usuário: Os nossos runs produtos com permissões de usuário "normais", não "instalação" é necessário. Basta descompactá-lo em seu diretório de usuário e executá-lo. Gerimos vários servidores onde a nossa aplicação é "instalados". Em cada máquina há um johndoe usuário. Nossos funcionários às vezes precisam de acesso ao aplicativo na linha de comando para acessar arquivos e log cheque ou reiniciar o aplicativo com a mão. Somente algumas pessoas devem ter acesso de linha de comando completo.

Estamos usando autenticação PPK no servidor.

Seria ótimo se employee1 só pode acessar o arquivo de registro e employee2 também pode fazer X etc ...

Solução: Como uma solução Vou usar a opção command como indicado no aceitou resposta. Eu vou fazer o meu próprio pequeno script shell que será o único arquivo que pode ser executado por alguns funcionários. O script irá oferecer vários comandos que podem ser executados, mas há outros. Vou usar os seguintes parâmetros no authorized_keys de como afirmado aqui :

command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host

Esta é a segurança suficiente para nós. Graças, comunidade!

Foi útil?

Solução

Você também pode restringir chaves para comandos admissíveis (no arquivo authorized_keys).

i. o utilizador não login via ssh e, em seguida, tem um conjunto limitado de comandos, mas sim apenas seria permitido a executar os comandos via SSH (por exemplo, "bin ssh somehost / showlogfile")

Outras dicas

ssh segue a tradição rsh usando programa de shell do usuário a partir do arquivo de senhas para executar comandos.

Isto significa que nós podemos resolver isso sem envolver configuração ssh de qualquer forma.

Se você não quer que o usuário seja capaz de ter acesso shell, então simplesmente substituir shell daquele usuário com um script. Se você olhar no /etc/passwd você vai ver que há um campo que atribui um interpretador de comandos shell para cada usuário. O script é usado como o shell tanto para a sua ssh user@host login interativo, bem como para os comandos ssh user@host command arg ....

Aqui está um exemplo. Eu criei um foo usuário cuja casca é um script. O script imprime o my arguments are: mensagem seguido por seus argumentos (cada um numa linha separada e no ângulo entre parênteses) e termina. No registo, no caso, não há argumentos. Aqui está o que acontece:

webserver:~# ssh foo@localhost
foo@localhost's password:
Linux webserver [ snip ]
[ snip ]
my arguments are:
Connection to localhost closed.

Se o usuário tenta executar um comando, ele se parece com isso:

webserver:~# ssh foo@localhost cat /etc/passwd
foo@localhost's password:
my arguments are:
<-c>
<cat /etc/passwd>

O nosso "shell" recebe uma invocação estilo -c, com todo o comando como um argumento, exatamente da mesma maneira que /bin/sh iria recebê-lo.

Então, como você pode ver, o que podemos fazer agora é desenvolver o roteiro ainda mais para que ele reconheça o caso quando foi chamado com um argumento -c, e, em seguida, analisa a cadeia (digamos por correspondência de padrões). Aquelas cordas que são permitidos pode ser passado para o shell real, de forma recursiva invocando /bin/bash -c <string>. O caso rejeite pode imprimir uma mensagem de erro e terminar (incluindo o caso quando -c está ausente).

Você tem que ter cuidado como você escreve isto. Eu recomendo escrever partidas única positivos que permitem apenas coisas muito específicas, e tudo disallow mais.

Nota: se você estiver root, você ainda pode fazer login nessa conta, substituindo o shell no comando su, assim su -s /bin/bash foo. (Shell substituto de escolha.) Não-raiz não pode fazer isso.

Aqui está um exemplo de script: restringir o usuário a usar apenas ssh para acesso git a repositórios sob /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"

É claro, estamos confiantes de que esses programas Git git-upload-pack e git-receive-pack não tem buracos ou portinholas que dará aos usuários acesso ao sistema.

Isso é inerente a este tipo de esquema de restrição. O usuário é autenticado para executar código em um determinado domínio de segurança, e estamos kludging em uma restrição para limitar esse domínio para um subdomínio. Por exemplo, se você permitir que um usuário para executar o comando vim em um arquivo específico para editá-lo, o usuário pode simplesmente pegar um shell com :!sh[Enter].

O que você está procurando é chamado Restricted Shell . Bash fornece tal modo no qual os usuários só podem executar comandos presentes em seus diretórios (e eles não podem se deslocar para outros diretórios), que pode ser bom o suficiente para você.

Eu encontrei esta discussão ser muito ilustrativo, se um pouco datado.

Você deve adquirir `rssh', o shell restrito

Você pode seguir as guias de restrição mencionada acima, todos eles são bastante auto-explicativo, e simples de seguir. Compreender os termos `jaula', e como implementar efetivamente sshd / configurações de terminais, e assim por diante.

Ser como a maioria de seus usuários acessar seus terminais via sshd, você também deve provavelmente olhar para sshd_conifg, o arquivo de configuração do daemon do SSH, para aplicar certas restrições via SSH. Tenha cuidado, no entanto. Compreender corretamente o que você tenta implementar, para as ramificações de configurações incorretas são, provavelmente, em vez terrível.

Por que você não escreve o seu próprio login-shell? Seria muito simples de usar Bash para isso, mas você pode usar qualquer linguagem.

Exemplo em Bash

Use o seu editor favorito para criar o /root/rbash.sh arquivo (este pode ser qualquer nome ou caminho, mas deve ser chown root:root e chmod 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

Tudo que você tem a fazer é definir este executável como seu shell de login. Por exemplo, editar seu arquivo /etc/passwd, e substituir o seu shell de login atual do que /bin/bash usuário com /root/rbash.sh.

Este é apenas um exemplo simples, mas você pode torná-lo tão avançado como você quer, a ideia está lá. Tenha cuidado para não se tranca para fora mudando shell de login do seu próprio e único usuário. E sempre testar símbolos e comandos estranhos para ver se ele é realmente seguro.

Você pode testá-lo com:. su -s /root/rbash.sh

Cuidado , certifique-se para coincidir com todo o comando, e ter cuidado com wildcards! Melhor excluir Bash-símbolos como ;, &, &&, ||, $ e backticks para ter certeza.

Dependendo da liberdade que você dá ao usuário, ele não vai ficar muito mais seguro do que isso. Descobri que muitas vezes eu só precisava fazer um usuário que tenha acesso a apenas alguns comandos relevantes, e, nesse caso, esta é realmente a melhor solução. No entanto, você deseja dar mais liberdade, uma prisão e permissões pode ser mais apropriado. Erros podem ser feitas facilmente, e só percebeu quando já é tarde demais.

Você pode querer olhar para a criação de um prisão .

Outra maneira de olhar para isso é usando POSIX ACLs, ele precisa ser suportado pelo seu sistema de arquivos, no entanto, você pode ter ajuste de grão fino de todos os comandos em linux da mesma maneira que você tem o mesmo controle no Windows (apenas sem o mais agradável UI). ligação

Outra coisa é olhar para PolicyKit .

Você vai ter que fazer um pouco de googling para obter tudo funcionando como este não é definitivamente uma força de Linux no momento.

[Divulgação: Eu escrevi sshdo que é descrito abaixo]

Se você quiser o login para ser interativo, em seguida, a criação de um shell restrito é provavelmente a resposta certa. Mas se houver um conjunto real de comandos que você deseja permitir (e nada mais) e é ok para estes comandos a serem executados individualmente via ssh (por exemplo ssh usuário @ host cmd arg blá blá), então um comando genérico whitelisting de controle para ssh pode ser o que você precisa. Isso é útil quando os comandos são script de alguma forma no cliente final e não requer que o usuário realmente digitar o comando ssh.

Há um programa chamado sshdo para fazer isso. Ele controla que comandos podem ser executados através de ligações de entrada de SSH. Ele está disponível para download em:

http://raf.org/sshdo/ (ler páginas de manual aqui) https://github.com/raforg/sshdo/

Ele tem um modo de treinamento para permitir que todos os comandos que são tentadas, e uma opção --learn para produzir a configuração necessária para permitir comandos aprendidos de forma permanente. Em seguida, o modo de treinamento pode ser desligado e quaisquer outros comandos não serão executados.

Ele também tem uma opção --unlearn para parar permitindo que comandos que não estão mais em uso, de modo a manter a estrita menos privilégio, como os requisitos mudam ao longo do tempo.

É muito exigente sobre o que ele permite. Ele não permitirá que um comando com quaisquer argumentos. Somente os comandos completos shell pode ser permitido.

Mas ele faz padrões de apoio simples para representar comandos semelhantes que variam apenas nas dígitos que aparecem na linha de comando (por exemplo, números de seqüência ou data / selos de tempo).

É como um firewall ou whitelisting controle para comandos ssh.

E suporta comandos diferentes sendo permitido para usuários diferentes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top