Pular para o conteúdo
Todos os conceitos

Como fechar a injeção de comando

Não chame o shell, passe os argumentos como lista e valide a entrada por lista de permissão.

Não existe um filtro mágico de caracteres; a defesa é parar de montar texto para o shell. Em camadas, da mais importante para a de reforço:

  1. Não chame o shell. Em vez de os.system("ping -c1 " + host), use a chamada que recebe uma lista de argumentos: subprocess.run(["ping", "-c1", host]), sem shell=True. Sem shell, ;, |, $() e ${IFS} são só caracteres do argumento, nunca comandos.
  2. Prefira a biblioteca ao programa externo. Muitas vezes nem precisa chamar um programa: há uma função que faz o mesmo dentro da linguagem.
  3. Ponha -- antes do valor do usuário quando o programa aceita opções, para um valor que começa com - não virar opção (fecha a injeção de argumento).
  4. Valide por lista de permissão. Aceite só o formato esperado (um IP, um nome de domínio, um nome de arquivo de imagem). Uma lista de permissão diz o que PODE; uma lista de bloqueio tenta adivinhar o que não pode, e sempre esquece um caractere.

Ler o patch é ver essas camadas aparecerem: a string virar lista, o shell=True sumir, o -- entrar, a validação no começo. O mesmo em Node: trocar exec("convert " + name) por execFile("convert", ["-resize", "100x100", name]).

entrada do usuario host = 1.2.3.4; id string entregue ao shell o metacaractere vira comando lista de argumentos + validacao o mesmo texto e so um argumento
Dois caminhos: a string entregue ao shell deixa o metacaractere virar comando; a lista de argumentos com validação faz o mesmo texto ser só um argumento.

Aparece nestes desafios