Esta é uma ideia para um segurança. Nossos funcionários devem ter acesso a alguns comandos em um servidor Linux, mas não todos. Eles devem, por exemplo, ter a possibilidade de acessar um arquivo de log ( less logfile
) ou iniciar diferentes comandos ( shutdown.sh
/ run.sh
).
Informações básicas:
Todos os funcionários acessam o servidor com o mesmo nome de usuário: Nosso produto funciona com permissões de usuário "normais", nenhuma "instalação" é necessária. Basta descompactá-lo em seu diretório de usuário e executá-lo. Gerenciamos vários servidores onde nosso aplicativo está "instalado". Em cada máquina existe um usuário johndoe
. Nossos funcionários às vezes precisam acessar o aplicativo na linha de comando para acessar e verificar os arquivos de log ou para reiniciar o aplicativo manualmente. Apenas algumas pessoas devem ter acesso total à linha de comando.
Estamos usando autenticação ppk no servidor.
Seria ótimo se o funcionário1 pudesse acessar apenas o arquivo de registro e o funcionário2 também pudesse fazer X etc ...
Solução:
Como solução utilizarei a command
opção indicada na resposta aceita . Farei meu próprio pequeno script de shell que será o único arquivo que pode ser executado por alguns funcionários. O script oferecerá vários comandos que podem ser executados, mas nenhum outro. Usarei os seguintes parâmetros authorized_keys
de conforme declarado aqui :
command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host
Isso é segurança suficiente para nós. Obrigado, comunidade!
Respostas:
Você também pode restringir as chaves a comandos permitidos (no arquivo authorized_keys).
Ou seja, o usuário não logaria via ssh e teria um conjunto restrito de comandos, mas apenas teria permissão para executar esses comandos via ssh (por exemplo, "ssh somehost bin / showlogfile")
fonte
ssh
segue arsh
tradição de usar o programa shell do usuário do arquivo de senha para executar comandos.Isso significa que podemos resolver isso sem envolver a
ssh
configuração de forma alguma.Se você não quiser que o usuário tenha acesso ao shell, basta substituir o shell desse usuário por um script. Se você olhar
/etc/passwd
, verá que existe um campo que atribui um interpretador de comandos shell para cada usuário. O script é usado como o shell para seu login interativossh user@host
e também para comandosssh user@host command arg ...
.Aqui está um exemplo. Criei um usuário
foo
cujo shell é um script. O script imprime a mensagemmy arguments are:
seguida por seus argumentos (cada um em uma linha separada e entre colchetes angulares) e termina. No caso de log, 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 tentar executar um comando, terá a seguinte aparência:
webserver:~# ssh foo@localhost cat /etc/passwd foo@localhost's password: my arguments are: <-c> <cat /etc/passwd>
Nosso "shell" recebe uma
-c
invocação de estilo, com o comando inteiro como um argumento, da mesma forma que/bin/sh
o receberia.Como você pode ver, o que podemos fazer agora é desenvolver ainda mais o script para que ele reconheça o caso quando for invocado com um
-c
argumento e, então, analise a string (digamos, por correspondência de padrões). As strings permitidas podem ser passadas para o shell real invocando recursivamente/bin/bash -c <string>
. O caso de rejeição pode imprimir uma mensagem de erro e encerrar (incluindo o caso em que-c
está faltando).Você tem que ter cuidado ao escrever isso. Eu recomendo escrever apenas correspondências positivas que permitem apenas coisas muito específicas e não permitem todo o resto.
Nota: se você estiver
root
, você ainda pode entrar nesta conta substituindo o shell nosu
comando, como estesu -s /bin/bash foo
. (Shell substituto de escolha.) Não-root não pode fazer isso.Aqui está um script de exemplo: restrinja o usuário a usar apenas
ssh
paragit
acessar os repositórios em/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 confiando que esses programas Git
git-upload-pack
egit-receive-pack
não têm buracos ou saídas de emergência que darão aos usuários acesso ao sistema.Isso é inerente a esse tipo de esquema de restrição. O usuário é autenticado para executar código em um determinado domínio de segurança, e estamos criando uma restrição para limitar esse domínio a um subdomínio. Por exemplo, se você permitir que um usuário execute o
vim
comando em um arquivo específico para editá-lo, o usuário pode apenas obter um shell com:!sh[Enter]
.fonte
git-receive-pack '/git/';dd if=/dev/urandom of=/dev/sda
?case
não parece correto para mim./bin/bash -c "$2"
é inseguro (semelhante a como funciona a injeção de SQL). Você pode filtrar a string com "aspas mágicas" como PHP. Mas a maneira mais fácil de garantir a segurança absoluta é chamar um comando manualmente e, em seguida, passar os parâmetros entre aspas duplas. Porque a segurança de tudo depende então desse comando ser o elo mais fraco (mais difícil de verificar). O mais interessante é ver como sua resposta tem 22 votos positivos, mas ninguém percebeu isso;) Você atualizará sua própria resposta?set
e, em seguida, pega apenas as duas primeiras palavras dele. O primeiro deve ser umgit-
comando permitido e o segundo deve ser um caminho canonizado, verificado em relação ao prefixo permitido e também verificado quanto à existência. Você pode pensar em alguma maneira de quebrar isso?O que você está procurando é chamado de Shell restrito . O Bash fornece um modo no qual os usuários podem executar apenas comandos presentes em seus diretórios pessoais (e não podem se mover para outros diretórios), o que pode ser bom o suficiente para você.
Achei este tópico muito ilustrativo, embora um pouco datado.
fonte
Por que você não escreve seu próprio shell de login? Seria muito simples usar o Bash para isso, mas você pode usar qualquer linguagem.
Exemplo em Bash
Use seu editor favorito para criar o arquivo
/root/rbash.sh
(pode ser qualquer nome ou caminho, mas deve serchown root:root
echmod 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ê precisa fazer é definir este executável como seu shell de login. Por exemplo, edite seu
/etc/passwd
arquivo e substitua o shell de login atual desse usuário/bin/bash
por/root/rbash.sh
.Este é apenas um exemplo simples, mas você pode torná-lo o mais avançado que quiser, a ideia está aí. Tenha cuidado para não se bloquear alterando o shell de login do seu próprio usuário. E sempre teste símbolos e comandos estranhos para ver se é realmente seguro.
Você pode testá-lo com:
su -s /root/rbash.sh
.Cuidado , certifique-se de combinar todo o comando e tome cuidado com os curingas! Melhor excluir Bash-símbolos, como
;
,&
,&&
,||
,$
, e backticks para ter certeza.Dependendo da liberdade que você dá ao usuário, não ficará muito mais seguro do que isso. Descobri que muitas vezes só preciso criar um usuário que tenha acesso a apenas alguns comandos relevantes e, nesse caso, essa é realmente a melhor solução. No entanto, se você deseja dar mais liberdade, uma prisão e permissões podem ser mais adequadas. Erros são cometidos facilmente e só percebidos quando já é tarde demais.
fonte
ln="service httpd restart"
, com:${ln[@]}
. Ainda assim, certifique-se de pensar sobre as questões de segurança, uma lista de permissões apenas para caracteres alfanuméricos e espaços em branco seria útil nesse caso. Mas você também pode simplesmente fazer:if [[ "$ln" == "restart-httpd"];then service httpd restart;fi
e trabalhar com comandos simples como esse./root/rbash.sh: Permission denied
Eu tentei chmod 777 também/root/rbash.sh
a/etc/shells
? Depende da distribuição. Você também pode tentar desativar temporariamenteselinux
e verificar as mensagens de log em busca de pistas (veja o carimbo de data / hora) nos arquivos do/var/log
.Você deve adquirir `rssh ', o shell restrito
Você pode seguir os guias de restrição mencionados acima, eles são bastante autoexplicativos e simples de seguir. Compreenda os termos `chroot jail 'e como implementar efetivamente as configurações de sshd / terminal e assim por diante.
Visto que a maioria dos seus usuários acessa seus terminais via sshd, você provavelmente também deve olhar o sshd_conifg, o arquivo de configuração daemon SSH, para aplicar certas restrições via SSH. Tenha cuidado, entretanto. Entenda corretamente o que você tenta implementar, pois as ramificações das configurações incorretas são provavelmente terríveis.
fonte
rssh
foi removido do Debian Buster. Acho que a nova moda é a corrida do GNU .GNU Rush pode ser a maneira mais flexível e segura de fazer isso:
fonte
Você pode querer ver como configurar uma prisão .
fonte
Outra maneira de ver isso é usando ACLs POSIX, ele precisa ser suportado por seu sistema de arquivos, no entanto, você pode ter um ajuste fino de todos os comandos no Linux da mesma forma que você tem o mesmo controle no Windows (apenas sem a interface do usuário mais agradável ) ligação
Outra coisa a se observar é o PolicyKit .
Você terá que pesquisar bastante no Google para fazer tudo funcionar, pois definitivamente não é um ponto forte do Linux no momento.
fonte
[Divulgação: escrevi sshdo, que é descrito abaixo]
Se você deseja que o login seja interativo, configurar um shell restrito é provavelmente a resposta certa. Mas se houver um conjunto real de comandos que você deseja permitir (e nada mais) e está tudo bem que esses comandos sejam executados individualmente via ssh (por exemplo, ssh usuário @ host cmd arg blah blah), então um comando genérico que lista o controle para ssh pode ser o que você precisa. Isso é útil quando os comandos são programados de alguma forma na extremidade do cliente e não exige que o usuário realmente digite o comando ssh.
Existe um programa chamado sshdo para fazer isso. Ele controla quais comandos podem ser executados por meio de conexões ssh de entrada. Está disponível para download em:
http://raf.org/sshdo/ (leia as páginas do manual aqui) https://github.com/raforg/sshdo/
Possui um modo de treinamento para permitir todos os comandos que são tentados e uma opção --learn para produzir a configuração necessária para permitir comandos aprendidos permanentemente. Então, 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 de permitir comandos que não estão mais em uso para manter o mínimo de privilégios estritos conforme os requisitos mudam com o tempo.
É muito exigente quanto ao que permite. Não permite um comando com nenhum argumento. Somente comandos shell completos podem ser permitidos.
Mas ele suporta padrões simples para representar comandos semelhantes que variam apenas nos dígitos que aparecem na linha de comando (por exemplo, números de sequência ou carimbos de data / hora).
É como um firewall ou controle de lista branca para comandos ssh.
E ele suporta comandos diferentes sendo permitidos para usuários diferentes.
fonte