Verificação dos binários de comando antes da execução

13

Existem métodos para verificar o que você está realmente executando a partir de um script bash?

Digamos que seu script bash está chamando vários comandos (por exemplo: tar, mail, scp, mysqldump) e você está disposto a se certificar de que taré o real, verdadeiro tar, que é determinável pelo rootutilizador sendo o dono do arquivo e diretório pai e o único com permissão de escrita e não alguns /tmp/surprise/tarcom www-dataou apache2sendo o proprietário.

Claro que eu conheço PATHe o ambiente, estou curioso para saber se isso pode ser verificado adicionalmente em um script bash em execução e, se houver, como exatamente?

Exemplo: (pseudocódigo)

tarfile=$(which tar)
isroot=$(ls -l "$tarfile") | grep "root root"
#and so on...
Miloš Đakonović
fonte
2
Se você é tão paranóico, use seus próprios binários!
Ipor Sircer
8
Além de whichnão dizer corretamente o que tarfará, conforme respondido por xhienne, lspoderia ser hackeado para retornar informações falsas sobre o (s) arquivo (s), se houver. Também greppode ser hackeado para retornar informações falsas; isso poderia ser evitado usando a correspondência de shell, mas o shell poderia ser hackeado. E o shell pode ser hackeado para obter resultados errados typeem primeiro lugar - ou substituído totalmente, pois a substituibilidade do shell foi uma inovação importante do Unix em comparação com os sistemas operacionais de 50 anos de idade. Veja o endereço de Turing de 1984 de Ken Thompson. São tartarugas até o fim.
dave_thompson_085
2
Não posso responder isso no Linux - apenas no AIX - que possui um componente chamado Trusted Execution ( TE) - que possui um banco de dados com assinaturas (ou seja, mais extenso que uma soma de verificação MD5. Quando o TE está ativo E um arquivo está no banco de dados, você pode escolher se o programa é executado - ou apenas avisa que não corresponde ao banco de dados.Além disso, existem duas outras configurações: TEP(PATH de execução confiável) e TLP(PATH LIBrary confiável). Somente os programas no TEP podem ser executados e as bibliotecas podem ser carregadas apenas com o directório está incluído no TLP no Linux I existe algo chamado 'AppArmor' que podem ajudá-lo..
Michael feltro
1
Você pode ter esse tipo de segurança, mas não a partir de um script - quando o script estiver sendo executado em um ambiente não controlado, é tarde demais. Pelo que você sabe, tudo o que você pode ver é um chroot configurado por um invasor.
Charles Duffy
2
... se você deseja ter um sistema confiável até o fim, precisa seguir a abordagem do ChromeOS: Tenha seu firmware assinado com uma chave incorporada ao seu hardware; seu gerenciador de inicialização / kernel verificado pelo firmware; sua partição do SO raiz somente leitura usando assinaturas em nível de bloco para verificação; etc. Existem também abordagens semelhantes às que o @MichaelFelt discute disponíveis - consulte a Arquitetura de Medição de Integridade -, mas o impacto no desempenho é maior e o nível de integridade reduzido (uma vez que a verificação de assinaturas binárias não ajuda você com ataques não executáveis conteúdo).
Charles Duffy

Respostas:

24

Em vez de validar binários que você executará, você poderá executar os binários corretos desde o início. Por exemplo, se você quiser ter certeza de que não vai rodar /tmp/surprise/tar, basta executar /usr/bin/tarno seu script. Como alternativa, defina seu $PATHvalor sensato antes de executar qualquer coisa.

Se você não confia em arquivos /usr/bin/e em outros diretórios do sistema, não há como recuperar a confiança. No seu exemplo, você está consultando o proprietário ls, mas como você sabe que pode confiar ls? O mesmo argumento se aplica a outras soluções, como md5sume strace.

Onde é necessária alta confiança na integridade do sistema, são usadas soluções especializadas como o IMA . Mas isso não é algo que você possa usar em um script: todo o sistema deve ser configurado de uma maneira especial, com o conceito de arquivos imutáveis ​​em vigor.

Dmitry Grigoryev
fonte
O que é interrompido quando diferentes distribuições escolhem colocar binários em /binvez de /usr/bin.
Damian Yerrick
O IMA é uma das duas abordagens prontas para produção - a outra é a abordagem dm-verity adotada pelo ChromeOS para validar os rootfs em nível de bloco.
Charles Duffy
@DamianYerrick Fair observação. Defina os $PATHdois caminhos, se necessário, suporte a distribuição múltipla.
Dmitry Grigoryev
O AIX TE (com ou sem RBAC) seria um terceiro componente do kernel "pronto para produção" que conseguirá isso - talvez mais. O TE, uma vez ativado para ser mais do que passivo, impedirá a abertura de arquivos e / ou a execução de programas. Além disso, os aplicativos e o uso da biblioteca podem ser configurados para serem exclusivamente no TEP (caminho de execução confiável) ou TLP (caminho da biblioteca confiável). Consulte ibm.com/support/knowledgecenter/en/ssw_aix_61/… para obter informações básicas
Michael Felt
6

Se um invasor obteve acesso ao seu sistema e pode modificá-lo $PATH(o que não deve ser incluído /tmpem nenhuma circunstância), é tarde demais para começar a se preocupar com as propriedades dos executáveis.

Em vez disso, você deve ler sobre como lidar com uma invasão .

Melhor se concentrar em evitar completamente a intrusão.

Se você possui um sistema em que esse tipo de coisa é importante, pode ser uma boa ideia isolar as partes que precisam ser públicas das partes que precisam ser privadas, além de realizar uma auditoria nos modos de comunicação. entre estes.

Kusalananda
fonte
4

É possível, até certo ponto, verificando o md5sumarquivo. Assim, em sistemas que usam aptgerenciamento de pacotes - no meu caso particular, Ubuntu 16.04 - existe o arquivo /var/lib/dpkg/info/tar.md5sums, que armazena as somas md5 de todos os arquivos provenientes tardurante a instalação. Portanto, você pode escrever uma instrução if simples que verifique se a saída md5sum /bin/tarcorresponde ao que está nesse arquivo.

É claro que isso pressupõe que o arquivo em si não foi violado. Obviamente, isso só pode acontecer quando o invasor obtém acesso root / sudo, quando todas as apostas estão desativadas.

Sergiy Kolodyazhnyy
fonte
8
Mas como você valida /usr/bin/md5sum?
Dmitry Grigoryev
Se um invasor puder substituir /bin/tarou /usr/bin/tar, é muito provável que ele também possa simplesmente substituir md5sumou /var/lib/dpkg/info/tar.md5sums. Ou $SHELL.
Jonas Schäfer
1
Acho que já mencionei no último parágrafo que, para que isso ocorra, um invasor precisará obter acesso root ao sistema e, nesse ponto, tudo é possível. Nos casos em que o invasor não tem acesso root, mas pode alterar a variável PATH para um usuário ou criar um alias onde taraponta para um binário diferente, isso funcionará. Quando um sistema é comprometido no nível da raiz, você tem uma opção - ative-o da órbita #
Sergiy Kolodyazhnyy
3

Sim, existe um método: o embutido type. Ao contrário do whichcomando que apenas pesquisa no PATH, typeele informa se o nome do comando é realmente uma palavra-chave reservada, um builtin, um alias, uma função ou um arquivo de disco.

$ type -t foobar || echo "Not found"
Not found

$ type -t echo
builtin

$ enable -n echo; type -t echo; type -p echo
file
/usr/bin/echo

$ echo() { printf "(echoing) %s\n" "$*"; }; type -t echo
function

$ alias echo="/bin/echo 'I say: ' "; type -t echo
alias

Além disso type -a, você terá todos os candidatos ao seu comando (da primeira à última escolha):

$ type -a echo
echo is aliased to `/bin/echo 'I say: ' '
echo is a function
echo () 
{ 
    printf "(echoing) %s\n" "$*"
}
echo is a shell builtin
echo is /usr/local/bin/echo
echo is /bin/echo

Por fim, se você estiver preocupado apenas com os binários no seu disco, poderá usar type -Papara obter todos os binários no seu PATH (na mesma ordem que acima):

$ type -Pa tar
/home/me/bin/tar                <= oh oh, is this normal?
/bin/tar

Dito isto, por typesi só não lhe dirá exatamente qual comando será chamado no final. Por exemplo, se você taré um alias que chama um binário (por exemplo alias tar="/tmp/tar"), então typevocê diz que é um alias.

xhienne
fonte
type -ainclui todos os formulários (por exemplo, alias e programa externo)
dave_thompson_085
Obrigado @ Dave, é de fato interessante, eu atualizei a minha resposta
xhienne
1
typelhe dirá o quanto o bash sabe, mas se estivermos sob o controle de um invasor mal-intencionado, não há razão para acreditar que o que o bash acha que sabe reflete a verdade real. Pelo que você sabe, há um LD_PRELOADmódulo que intercepta todas as chamadas da biblioteca C que você faz.
Charles Duffy
1
@CharlesDuffy Você está certo, é claro. Não queria responder na direção da segurança. Estou apenas propondo uma resposta para a pergunta no topo: "Existem métodos para verificar o que você está realmente executando a partir de um script bash" e propus uma alternativa para which.
xhienne
Eu nunca vi enableantes. Eu usei o conselho dessas respostas para executar type enablepara descobrir que é um shell embutido e depois help enablepara ver o que ele faz.
Joe
3

Você pode verificar quais comandos estão sendo executados exatamente por um script usando strace. Por exemplo:

strace -f -e execve ./script.sh

Com o seguinte script:

#!/bin/bash
touch testfile.txt
echo "Hello" >> testfile.txt
cat testfile.txt
rm testfile.txt

stracedirá o caminho exato para os comandos executados quando usados ​​com o -e execveparâmetro:

execve("./script.sh", ["./script.sh"], [/* 69 vars */]) = 0 
Process 8524 attached
[pid  8524] execve("/usr/bin/touch", ["touch", "testfile.txt"], [/* 68 vars */]) = 0 
[pid  8524] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8524, si_status=0, si_utime=0, si_stime=0} --- 
Process 8525 attached [pid > 8525] execve("/bin/cat", ["cat", "testfile.txt"], [/* 68 vars */]) = 0
Hello [pid  8525] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8525, si_status=0, si_utime=0, si_stime=0} --- 
Process 8526 attached [pid > 8526] execve("/bin/rm", ["rm", "testfile.txt"], [/* 68 vars */]) = 0
[pid  8526] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8526, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

Parâmetros (do strace man):

-f: Rastreie os processos filhos à medida que são criados pelos processos rastreados atualmente como resultado das chamadas do sistema fork (2), vfork (2) e clone (2). Observe que -p PID -fanexará todos os encadeamentos do processo PID se ele for multiencadeado, não apenas o encadeamento com thread_id = PID.

-e trace=file: Rastreie todas as chamadas do sistema que usam um nome de arquivo como argumento. Você pode pensar nisso como uma abreviação para a -e trace=open,stat,chmod,unlink,...qual é útil ver quais arquivos o processo está fazendo referência. Além disso, o uso da abreviação garantirá que você não se esqueça de incluir acidentalmente uma chamada como lstat na lista.

Zumo de Vidrio
fonte
3
Isso não é de forma alguma utilizável por um script para executar testes automatizados, e não há nenhuma razão específica para acreditar que straceisso não tenha sido subvertido.
Charles Duffy
0

O sistema operacional Linux é baseado em arquivos e muitos comandos executados no linux provavelmente resolverão algumas alterações nos arquivos localizados em sua máquina. Por isso, talvez seja a melhor solução para o seu problema. Você pode testar seus comandos quanto a alterações no sistema de arquivos antes que ele seja executado.

insira a descrição da imagem aqui

Existe um comando 'strace' que decompila seu comando em partes ...

insira a descrição da imagem aqui

Se você realmente deseja aprofundar, deseja fazer o check-out dos descompiladores para os scripts que serão executados. Em outras palavras, você deve verificar a interpretação do montador desse comando. Para festança lá objdump -d. Os scripts bin do Linux são criados principalmente com a Clinguagem de programação, portanto, use um bom Cdescompilador.


fonte