Explicação do comando para verificar o shellshock

32

Aqui está o comando que usei para verificar meu shell bash para o bug do Shellshock:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

Alguém por favor pode explicar o comando em detalhes?

    
por heemayl 28.09.2014 / 07:35

2 respostas

45

Esta resposta é um derivado de um artigo original da original na Revista Fedora . 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 imprime “this is a test” se o bash tiver sido corrigido.

E você provavelmente já ouviu falar que tem algo a ver com variáveis ​​de ambiente. Mas, por que o código nas variáveis ​​de ambiente é executado? Bem, não é para ser - mas, por causa de um recurso que sou tentado a chamar um pouco 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 isso assim:

$ Ubuntu()  { echo "Ubuntu is awesome."; }

e então você tem um novo comando. Lembre-se de que o echo aqui não é executado ainda; é apenas 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 meu novo comando incrível sob esse ponto. A instrução bash -c somecommand faz exatamente isso: executa o comando especificado 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, inerente ao ambiente - uma coleção de pares de valores-chave que foram exportados do shell. (Este é um conceito todo "nuther"; se você não estiver familiarizado com isso, confie em mim agora.) E, ao que parece, o bash também pode exportar funções. Então:

$ export -f Ubuntu
$ bash -c Ubuntu
  Ubuntu is awesome.

O que é bom e bom - exceto que o mecanismo pelo qual isso é realizado é sorta desertor . Basicamente, como não há magia Linux / Unix para fazer funções em variáveis ​​de ambiente, a função de exportação apenas cria uma variável de ambiente regular contendo a definição da função. Então, quando o segundo shell lê o ambiente de “entrada” e encontra uma variável com conteúdo semelhante a uma função, ela é avaliada.

Em teoria, isso é perfeitamente seguro , porque, lembre-se, a definição de uma função não é realmente executada . Exceto - e é por isso que estamos aqui - houve um erro no código em que a avaliação não foi interrompida quando o fim da definição da função foi atingido. Ele simplesmente continua.

Isso nunca aconteceria quando a função armazenada em uma variável de ambiente fosse feita legitimamente, com export -f . Mas por que ser legítimo? Um invasor pode inventar qualquer variável de ambiente antiga, e se parecer com uma função, novos shells de bash vão pensar que é!

Então, no nosso primeiro exemplo:

env x='() { :;}; echo OOPS' bash -c "echo this is a test"

O comando env executa um comando com um determinado conjunto de variáveis. Nesse caso, estamos definindo x como algo que parece uma função. A função é apenas um único : , que na verdade é um comando simples que é definido como não fazer nada. Mas, depois do semi-colon que sinaliza o fim da definição da função, há um comando echo . Isso não deveria estar lá, mas não há nada que nos impeça de fazer isso.

Então, o comando dado para rodar com este novo ambiente é um novo bash shell, novamente com um comando " echo this is a test " ou "do nothing : ", após o qual ele será finalizado, completamente inofensivo.

Mas - opa! Quando esse novo shell é inicializado e lê o ambiente, ele chega à variável x e, como se parece com uma função, ela é avaliada. A definição da função é inofensivamente carregada - e então nossa carga maliciosa é acionada também. Então, se você executar o código acima em um sistema vulnerável, você receberá “OOPS” de volta para você. Ou, um invasor poderia fazer muito pior do que apenas imprimir coisas.

    
por αғsнιη 28.09.2014 / 08:06
2

Na versão não corrigida de bash , ela armazena definições de função exportadas como variáveis ​​de ambiente.

Armazene uma função x as,

$ x() { bar; }
$ export -f x

E verifique sua definição como

$ env | grep -A1 x
x=() {  bar
}

Portanto, pode-se explorar isso definindo suas próprias variáveis ​​de ambiente e as interpreta como definições de função. Por exemplo, env x='() { :;}' seria tratado como

x() { :;
}

O que o comando para verificar o shellshock faz,

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

De man env ,

  1. env - executa um programa em um ambiente modificado.

  2. : não faz nada, mas sai com o status de saída 0 . veja mais

  3. Quando uma nova instância de bash não corrigida é 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

    vulnerable
    this is a test
  

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 fazer com que a avaliação e a exploração ocorram, a definição da função em si e a variável de ambiente utilizada são arbitrárias. O shell examina as variáveis ​​de ambiente, vê x, que se parece com as restrições que ele conhece sobre a definição de uma função, e avalia a linha, involuntariamente também executando o eco (que pode ser qualquer comando, malicioso ou não) . Veja também este

    
por souravc 28.09.2014 / 08:39