Aqui está o comando que eu usei para verificar meu shell bash para o bug do Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Alguém pode explicar o comando em detalhes?
Aqui está o comando que eu usei para verificar meu shell bash para o bug do Shellshock:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Alguém pode explicar o comando em detalhes?
Respostas:
Esta resposta é derivada de um artigo original na Revista Fedora de Matthew Miller, licenciado sob a licença Creative Commons Attribution-Share Alike 4.0 .
Deixe-me explicar:
env x='() { :;}; echo OOPS' bash -c :
Isso imprimirá "OOPS" em um sistema vulnerável, mas sairá silenciosamente se o bash tiver sido corrigido.
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
Isso imprimirá "OOPS" em um sistema vulnerável, mas será impresso “this is a test”
se o bash tiver sido corrigido.
E você provavelmente já ouviu falar que isso tem algo a ver com variáveis de ambiente. Mas, por que o código nas variáveis de ambiente está sendo executado? Bem, não deveria ser - mas, por causa de um recurso que sou tentado a chamar de inteligente demais para o seu próprio bem, há espaço para uma falha. Bash é o que você vê como um prompt de terminal, mas também é uma linguagem de script e tem a capacidade de definir funções. Você faz assim:
$ Ubuntu() { echo "Ubuntu is awesome."; }
e então você tem um novo comando. Lembre-se de que o echo
aqui ainda não foi executado; é salvo como o que acontecerá quando executarmos nosso novo comando. Isso será importante em um minuto!
$ Ubuntu
Ubuntu is awesome.
Útil! Mas, digamos, por algum motivo, precisamos executar uma nova instância do bash, como um subprocesso, e queremos executar o meu novo e impressionante comando sob isso. A instrução bash -c somecommand
faz exatamente isso: executa o comando fornecido em um novo shell:
$ bash -c Ubuntu
bash: Ubuntu: command not found
Ooh. Triste. A criança não herdou a definição da função. Mas, ele inerente ao ambiente - uma coleção de pares de valores-chave que foram exportados do shell. (Esse é um conceito completo; se você não estiver familiarizado com isso, confie em mim por enquanto.) E, ao que parece, o bash também pode exportar funções. Tão:
$ export -f Ubuntu
$ bash -c Ubuntu
Ubuntu is awesome.
O que é muito bom - exceto que o mecanismo pelo qual isso é realizado é desonesto . Basicamente, como não há mágica do Linux / Unix para executar funções em variáveis de ambiente, a função de exportação na verdade apenas cria uma variável de ambiente regular contendo a definição da função. Então, quando o segundo shell lê o ambiente “recebido” e encontra uma variável com conteúdo que se parece com uma função, ele a avalia.
Em teoria, isso é perfeitamente seguro , porque, lembre-se, definir uma função não é realmente executa de fato . Exceto - e é por isso que estamos aqui - houve um erro no código em que a avaliação não parou quando o final da definição da função foi atingido. Apenas continua indo.
Isso nunca aconteceria quando a função armazenada em uma variável de ambiente é feita legitimamente, com export -f
. Mas, por que ser legítimo? Um invasor pode criar qualquer variável de ambiente antiga e, se parecer com uma função, novos shells bash acharão que é!
Então, no nosso primeiro exemplo:
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
O env
comando executa um comando com um determinado conjunto de variáveis. Nesse caso, estamos definindo x
algo que se parece com uma função. A função é apenas uma única :
, que na verdade é um comando simples, definido como não fazer nada. Mas então, após o semi-colon
que sinaliza o final da definição da função, há umaecho
comando. Isso não deveria estar lá, mas não há nada que nos impeça de fazê-lo.
Em seguida, o comando fornecido para executar com este novo ambiente é um novo shell bash, novamente com um “ echo this is a test
” ou “não faça nada:
comando ", após o qual ele será encerrado, completamente inofensivo.
Mas - oops! Quando esse novo shell é iniciado e lê o ambiente, ele chega à x
variável e, como se parece com uma função, ele a avalia. A definição da função é carregada inofensivamente - e então nossa carga maliciosa também é acionada. Portanto, se você executar o procedimento acima em um sistema vulnerável, será “OOPS”
impresso de volta. Ou, um invasor pode fazer muito pior do que apenas imprimir coisas.
env
não é necessário. Você pode obter o mesmo resultado (aprovação / reprovação, dependendo se Bash foi atualizado) usando o comando sem ele: x='() { :;}; echo OOPS' bash -c "echo this is a test"
. Isso ocorre porque o precedente de um comando com uma atribuição de variável passa essa variável e seu valor para o ambiente do comando ( bash -c "..."
neste caso).
env
é necessário ou não, é determinado pelo shell a partir do qual se executa o teste, não pelo shell que está sendo testado. (Podem ser os mesmos. Mesmo assim, estamos testando como o bash processa seu próprio ambiente.) Os shell do estilo Bourne aceitam NAME=value command
sintaxe; As conchas no estilo C (por exemplo csh
, tcsh
) não. Portanto, o teste é um pouco mais portátil env
(às vezes, criando confusão sobre como ele funciona).
Na versão sem patch debash
ele armazena definições de funções exportadas como variáveis de ambiente.
Armazene uma função x
como,
$ x() { bar; }
$ export -f x
E verifique sua definição como,
$ env | grep -A1 x
x=() { bar
}
Assim, pode-se explorar isso definindo suas próprias variáveis de ambiente e interpretando-as como definições de função. Por exemplo, env x='() { :;}'
seria tratado como
x() { :;
}
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
De man env
,
env
- execute um programa em um ambiente modificado.
:
não faça nada além de sair com o status de saída 0
. veja mais
Quando uma nova instância do bash sem patches é lançada como bash -c "echo this is a test"
, a variável ambiental criada é tratada como uma função e carregada. Assim, obtém-se a saída
vulnerável isto é um teste
Nota: O eco fora da definição da função foi executado inesperadamente durante a inicialização do bash. A definição da função é apenas um passo para que a avaliação e a exploração ocorram, a própria definição da função e a variável de ambiente usada são arbitrárias. O shell examina as variáveis de ambiente, vê x, que parece atender às restrições que conhece sobre a aparência de uma definição de função, e avalia a linha, também involuntariamente executando o eco (que pode ser qualquer comando, malicioso ou não) . Veja também este
env test='() { echo "anything"; }' bash -c "echo otherthing"
, verá na saída otherthing
. Isso é corrigido no patch. fique à vontade se ainda não estiver claro.
unpatched bash
você pode chamar a função conforme definida, mas em um patch bash
a definição em si não existe.
echo vulnerable
) não é executado. Observe que nos patches mais recentes, a função passada deve ter um prefixo específico ( env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test"
). Alguns patches mais recentes podem ser usados em %%
vez do primeiro ()
.