
Eu tenho um daemon daemon
em execução no Servidor A.
Lá, há um script baseado em argumentos para controlar o daemon daemon_adm.py
(Servidor A). Através deste script posso inserir "mensagens" daemon
vindas da entrada do usuário. Texto livre, como você quiser.
Depois, há uma interface web no Servidor B para daemon_adm.py
PHP usando a classe SSH2 do phpseclib.
Eu sei que é fortemente desencorajado passar a entrada do usuário para a linha de comando, mas bem, deve haver uma maneira de passar o texto do servidor web B para daemon_adm.py
o servidor A.
Como posso passar com segurança um texto como argumento para um utilitário de linha de comando?
Mesmo se eu repetir os argumentos e canalizá-los daemon_adm.py
assim:
<?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 do usuário para base64 (que, até onde eu sei, não usa aspas e espaços em seu conjunto de caracteres) e decodificá-la daemon_adm.py
assim:
<?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, conforme indicado por Barmar, seria daemon_adm.py
aceitar os dados de texto do stdin, e não como um argumento analisável pelo shell.
Responder1
ssh2::exec()
retorna um fluxo, que está conectado a 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 não quiser passar os parâmetros via stdin, você pode usarescapeshellarg()
:
$command = '/path/to/daemon_adm.py ' . escapeshellarg($text);
$ssh->exec($command);
Responder2
Para inserir uma string em um snippet de shell e fazer com que o shell interprete a string literalmente, existem duas abordagens relativamente simples:
- Coloque a string entre aspas simples e substitua cada aspa simples
'
pela string de 4 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 por SSH, lembre-se de que o shell remoto expandirá o comando e, além disso, se você estiver invocando o SSH por meio de um shell local, o shell local também realizará a expansão, portanto, você precisará citar duas vezes.
PHP fornece oescapeshellarg
função para escapar de caracteres especiais do shell. Desde entãoexec
executa a expansão, chame-o duas vezes na string que deseja proteger.
Observe que isso é adequado para cadeias de texto, mas não para cadeias de bytes. A maioria dos shells não permite a passagem de bytes nulos.
Outra abordagem que é menos propensa a erros e permite a passagem de cadeias de bytes arbitrárias, mas requer a alteração do que é executado na outra extremidade, épasse a string na entrada padrão do comando remoto.
Responder3
Você poderia fazer algo como...
$ssh->enablePTY();
$ssh->exec('/path/to/daemon_adm.py');
$ssh->write('...');
echo $ssh->read();