Passando com segurança a entrada do usuário para o comando

1

Eu tenho um daemon daemon em execução no servidor A.

Lá, há um script baseado em argumento para controlar o daemon daemon_adm.py (Servidor A). Através deste script eu posso inserir "mensagens" para daemon vindo da entrada do usuário. Texto livre, o que você quiser.

Em seguida, há uma interface da Web no Servidor B para daemon_adm.py no PHP usando a classe SSH2 do phpseclib.

Eu sei que é strongmente desencorajado passar a entrada do usuário para a linha de comando, mas bem, deve haver uma maneira de passar o texto do servidor B para daemon_adm.py no Servidor A.

Como posso passar com segurança um texto como argumento para um utilitário de linha de comando?

Mesmo se eu fizer eco dos argumentos e enviá-los para daemon_adm.py desta forma:

<?php 
$command = '/path/to/daemon_adm.py "'.$text.'"';
ssh->exec($command);
// or whatever other library or programming language
?>

como este comando é executado por uma interface ssh com uma string formatada, o código pode ser injetado

<?php 
$text = 'safetext"; echo "hazard"';
$command = '/path/to/daemon_adm.py "'.$text.'"';
ssh->exec($command);
// command sent: /path/to/daemon_adm.py "safetext"; echo "hazard"
?>

Minha opção atual em mente é codificar cada entrada de usuário para base64 (que, até onde eu sei, não usa aspas e espaços em seu conjunto de caracteres) e decodificá-lo dentro de daemon_adm.py da seguinte forma:

<?php 
$text = 'safetext"; echo "hazard"';

// Enconding it to base64

$command = '/path/to/daemon_adm.py '.$encoded_text;
ssh->exec($command);

// command sent: /path/to/daemon_adm.py c2FmZXRleHQiOyBlY2hvICJoYXphcmQi
?>

Isso é seguro o suficiente ou complicado?

- EDITAR

Uma solução indireta, como indicado pelo Barmar, seria fazer daemon_adm.py aceitar os dados de texto do stdin, e não como um argumento analisável do shell.

    
por Sdlion 08.10.2014 / 21:08

3 respostas

1

Para inserir uma string em um snippet de shell e organizar o shell para interpretar a string literalmente, há duas abordagens relativamente simples:

  • Coloque a string entre aspas simples e substitua cada cota única ' pela string de quatro caracteres '\'' .
  • Prefixe cada caractere de pontuação ASCII com \ (você também pode prefixar outros caracteres) e substitua as novas linhas por '␤' ou "␤" (nova linha entre aspas simples ou duplas).

Ao invocar um comando remoto sobre SSH, lembre-se de que o shell remoto expandirá o comando e, além disso, se você estiver chamando o SSH por meio de um shell local, o shell local também executará a expansão. citar duas vezes.

O PHP fornece a função escapeshellarg para escapar de caracteres especiais do shell. O Snce exec executa a expansão, chame-o duas vezes na string que deseja proteger.

Observe que isso é bom para strings de texto, mas não para strings de bytes. A maioria das shells não permite a passagem de bytes nulos.

Outra abordagem que é menos propensa a erros e permite que sequências de bytes arbitrárias passem, mas requer a alteração do que é executado na outra extremidade, é passar a string na entrada padrão do comando remoto .

    
por 09.10.2014 / 01:57
2

ssh2::exec() retorna um fluxo, que está conectado aos stdin , stdout e stderr do comando remoto. Então você pode fazer:

$command = '/path/to/daemon_adm.py';
$stream = $ssh->exec($command);
fwrite($stream, "$text\n");

Se você não quiser passar os parâmetros via stdin, você pode usar escapeshellarg() :

$command = '/path/to/daemon_adm.py ' . escapeshellarg($text);
$ssh->exec($command);
    
por 08.10.2014 / 21:39
0

Você poderia fazer algo como ...

$ssh->enablePTY();
$ssh->exec('/path/to/daemon_adm.py');
$ssh->write('...');
echo $ssh->read();
    
por 09.10.2014 / 18:06