Injeção de comandos: como funciona, quais são os riscos e como evitá-la
25 de novembro de 2020
0 minutos de leituraAtaques de injeção de comandos — também conhecidos como ataques de injeção de comandos do sistema operacional — exploram uma falha de programação para executar comandos no sistema sem validar, escapar ou sanitizar corretamente as entradas, o que pode permitir que um invasor execute comandos arbitrários.
Quais são os riscos da injeção de comandos?
Dependendo da configuração do aplicativo e do processo que o executa, uma vulnerabilidade de injeção de comandos pode elevar os privilégios do processo ou abrir um shell reverso remoto, permitindo que um agente malicioso interaja com o sistema sem restrições.
Como funcionam os ataques de injeção de comandos?
Para entender as falhas de programação relacionadas a ataques de injeção de comandos do sistema operacional, vamos explorar algumas vulnerabilidades desse tipo encontradas em aplicativos baseados em Node.js.
systeminformation é uma biblioteca de informações do sistema operacional (SO) com mais de 500 mil downloads por semana, manutenção regular (commits) e uma comunidade ativa, como podemos ver na página de integridade de dependências do Snyk Advisor:

No entanto, todas as versões do systeminformation anteriores à versão 4.27.11 são vulneráveis à injeção de comandos do sistema operacional, devido a vários métodos vulneráveis expostos aos usuários pela biblioteca.
Vamos analisar o código da função vulnerável inetChecksite(). Você consegue identificar a vulnerabilidade de segurança neste exemplo de injeção de comandos?
Posso tirar várias conclusões deste trecho de código:
Um parâmetro de
urlestá sendo sanitizado. Será que consigo contornar as funções de sanitização com algo que o autor não levou em conta?Está sendo usada uma API insegura para iniciar processos do sistema operacional:
exec(), que concatena os comandos e seus argumentos em um único comando de shell para execução. Esse também é o motivo pelo qual o autor precisou recorrer à própria sanitização dos argumentos da linha de comando.
A variável urlSanitized é concatenada aos argumentos fornecidos à CLI.
É nesse último ponto, sobre urlSanitized, que está a vulnerabilidade de segurança. O comando em si, referenciado pela variável cmd, é o utilitário de rede curl. E se pudéssemos simplesmente passar um argumento de comando ao curl como URL?
É possível tentar uma injeção de comandos com a seguinte prova de conceito, fornecendo a URL à função vulnerável, como mostrado no primeiro argumento passado para a função inetChecksite(). Veja este exemplo de injeção de comandos:
No entanto, isso não funciona neste caso porque esse pacote npm sanitiza entradas perigosas do usuário, como o ponto e vírgula (;).
No entanto, os argumentos de linha de comando normalmente não precisam de caracteres especiais. Poderíamos fornecer como entrada do usuário uma URL como https://snyk.io -o hihi, que inclui um espaço e concatena o argumento posicional -o do curl, gravando o resultado do site em um arquivo que controlamos.
Veja outro exemplo de injeção de comandos que mostra como essa exploração pode ocorrer — e de fato funciona como esperado — em uma versão vulnerável do systeminformation@4.27.10:
Este commit aprimorou a sanitização com o objetivo de limitar ainda mais vulnerabilidades desse tipo de injeção de comandos:

Guia rápido de injeção de comandos
Podemos aprender muito com outros exemplos de injeção de comandos, nos quais identificamos vulnerabilidades de segurança em pacotes de código aberto e como elas foram mitigadas, como nestas vulnerabilidades: aqui e aqui.
Para evitar ataques de injeção de comandos, considere as seguintes práticas:
Não permita que entradas do usuário sejam usadas nos comandos executados pelo seu aplicativo.
Use apenas APIs seguras para executar comandos, como execFile(). Diferentemente de outras APIs, ela aceita o comando como primeiro parâmetro e um array de argumentos de linha de comando como segundo parâmetro da função. Assim, o comando precisa ser um programa válido e fica separado de entradas potencialmente perigosas.
Ao usar
execFile(), garanta que o usuário não tenha controle sobre o nome do programa. Além disso, mapeie as entradas do usuário para argumentos de comando, em vez de passá-las diretamente para a execução do programa.Como precaução adicional, valide se as entradas do usuário correspondem ao formato esperado. Por exemplo, se um parâmetro de função espera uma URL, valide se a entrada recebida é uma URL válida. Isso teria evitado a vulnerabilidade de injeção de comandos mencionada acima no pacote npm systeminformation.
Ataques de injeção de comandos no OWASP Top 10
Para mostrar como os ataques de injeção de comandos do sistema operacional são comuns, consultei todas as vulnerabilidades de segurança conhecidas publicamente que a equipe de segurança do Snyk publicou em outubro de 2020 e filtrei pelo ecossistema JavaScript no npm. Como você pode ver, só na última semana de outubro foram identificadas várias vulnerabilidades de segurança de Command injection em pacotes npm.

Em resumo, as vulnerabilidades de injeção de comandos são mais comuns do que você imagina. Não é à toa que esses ataques aparecem com destaque entre os 10 principais riscos de segurança para aplicações web da OWASP: são comuns e assumem muitas formas, como os ataques de injeção de SQL.Recomendo conectar seus repositórios Git ao Snyk para testar e corrigir vulnerabilidades de injeção de comandos. Quem sabe o Snyk também encontra outras? O Snyk é gratuito e leva pouco tempo para configurar o monitoramento dos seus projetos!
Comece a participar de desafios de Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo sob demanda ao nosso workshop virtual introdutório.


