Neste artigo, aprenderemos como chamar corretamente os comandos do sistema usando o Node.js para evitar vulnerabilidades comuns de injeção de linha de comando.
O método que costumamos usar para chamar comandos é o mais simples child_process.exec. Tem um padrão de uso muito simples; Ele passa em um comando string e repassa um resultado de processamento de erro ou comando para a função de retorno de chamada.
Aqui está um exemplo muito típico dos seus comandos do sistema de chamada através do Child_Process.exec.
A cópia do código é a seguinte:
Child_process.exec ('ls', function (err, dados) {
console.log (dados);
});
No entanto, o que acontece quando você precisa adicionar alguns parâmetros digitados ao usuário ao comando que você chama? A solução óbvia é amarrar a entrada do usuário diretamente com seu comando. No entanto, meus anos de experiência me dizem: quando você envia strings conectados de um sistema para outro, haverá problemas um dia.
A cópia do código é a seguinte:
var path = "entrada do usuário";
Child_process.exec ('ls -l' + caminho, função (err, dados) {
console.log (dados);
});
Por que a string de conexão tem problemas?
Bem, porque no mecanismo Child_Process.exec, a execução de "/bin/sh" será chamada. Não é o programa de destino. O comando enviado é passado para um novo processo "/bin/sh 'para executar o shell. O nome de Child_process.exec é um pouco enganador - este é um intérprete de bash, não um programa. Isso significa que todos os caracteres da concha podem ter consequências devastadoras se os parâmetros inseridos pelo usuário forem executados diretamente.
A cópia do código é a seguinte:
[PID 25170] Execve ("/bin/sh", ["/bin/sh", "-c", "ls -l user input"], [/ * 16 vars */]
Por exemplo, um invasor poderia usar um ponto de vírgula ";" Para encerrar o comando e iniciar uma nova chamada, e eles poderiam usar backticks ou $ () para executar o subcomando. Existem também muitos abusos em potencial.
Então, qual é a maneira correta de chamá -lo?
execfile / Spawn
Spawn e Execfile pegam um parâmetro extra de matriz, que não é um ambiente de shell que pode executar outros comandos e não executará comandos adicionais.
Vamos usar o Execfile e o Spawn para modificar o exemplo anterior para ver como as chamadas do sistema são diferentes e por que não é suscetível à injeção de comando.
Child_process.execfile
A cópia do código é a seguinte:
var Child_Process = requer ('Child_Process');
var path = "."
Child_process.execfile ('/bin/ls', ['-l', caminho], function (err, resultado) {
console.log (resultado)
});
Executando chamadas do sistema
A cópia do código é a seguinte:
[PID 25565] Execve ("/bin/ls", ["/bin/ls", "-l", "."], [/ * 16 vars */]
Child_process.spawn
Exemplos de uso de substituição de spawn são muito semelhantes.
A cópia do código é a seguinte:
var Child_Process = requer ('Child_Process');
var path = "."
var ls = child_process.spawn ('/bin/ls', ['-l', caminho])
ls.stdout.on ('dados', função (dados) {
console.log (data.toString ());
});
Executando chamadas do sistema
A cópia do código é a seguinte:
[PID 26883] Execve ("/bin/ls", ["/bin/ls", "-l", "."], [/ * 16 vars */
Ao usar Spawn ou Execfile, nosso objetivo é executar apenas um comando (parâmetro). Isso significa que o usuário não pode executar o comando injetado porque /bin /ls não sabe como lidar com backticks ou tubo ou;. O que seu /bin /bash explicará são os parâmetros desses comandos. É semelhante ao uso de um parâmetro para passar os parâmetros em uma consulta SQL, se você estiver familiarizado com ela.
Mas também há um aviso: o uso de Spawn ou Execfile nem sempre é seguro. Por exemplo, a execução /bin /encontre e a passagem nos parâmetros de entrada do usuário ainda pode fazer com que o sistema fique preso. O comando Find possui algumas opções que permitem leitura/gravação de arquivos arbitrários.
Então, aqui estão algumas orientações sobre os comandos Node.js em execução do sistema:
Evite usar child_process.exec, especialmente quando você precisar incluir parâmetros inseridos pelo usuário, lembre -se.
Tente evitar deixar os usuários passarem os parâmetros. O uso de seleções é muito melhor do que fazer com que os usuários entrem diretamente.
Se você precisar permitir que o usuário insira os parâmetros, consulte extensivamente os parâmetros do comando, determine quais opções são seguras e crie uma lista de permissões.