Pasar de forma segura la entrada del usuario al comando

Pasar de forma segura la entrada del usuario al comando

Tengo un demonio daemonejecutándose en el servidor A.

Allí, hay un script basado en argumentos para controlar el demonio daemon_adm.py(Servidor A). A través de este script puedo insertar "mensajes" daemonprovenientes de la entrada del usuario. Texto libre, lo que quieras que sea.

Luego, hay una interfaz web en el Servidor B para daemon_adm.pyPHP que utiliza la clase SSH2 de phpseclib.

Sé que se desaconseja pasar la entrada del usuario a la línea de comando, pero bueno, debe haber una manera de pasar el texto desde el servidor web B al daemon_adm.pyservidor A.

¿Cómo puedo pasar de forma segura un texto como argumento a una utilidad de línea de comando?

Incluso si me hago eco de los argumentos y los canalizo de daemon_adm.pyesta manera:

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

dado que este comando se ejecuta mediante una interfaz ssh con una cadena formateada, se podría inyectar código

<?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"
?>

Mi opción actual en mente es codificar cada entrada del usuario en base64 (que hasta donde yo sé no usa comillas ni espacios en su conjunto de caracteres) y decodificarla de daemon_adm.pyesta manera:

<?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
?>

¿Es esto lo suficientemente seguro o complicado?

-- EDITAR --

Una solución indirecta, según lo indicado por Barmar, sería hacer que daemon_adm.pyse aceptaran los datos de texto de la entrada estándar, y no como un argumento analizable del shell.

Respuesta1

ssh2::exec()devuelve una secuencia, que está conectada a stdin, stdouty stderrdel comando remoto. Entonces puedes hacer:

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

Si no desea pasar los parámetros a través de stdin, puede usarescapeshellarg():

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

Respuesta2

Para insertar una cadena en un fragmento de shell y hacer que el shell interprete la cadena literalmente, existen dos métodos relativamente simples:

  • Rodee la cadena entre comillas simples y reemplace cada comilla simple 'por la cadena de 4 caracteres '\''.
  • Anteponga cada carácter de puntuación ASCII \(también puede anteponer otros caracteres) y reemplace las nuevas líneas con '␤'o "␤"(nueva línea entre comillas simples o dobles).

Al invocar un comando remoto a través de SSH, tenga en cuenta que el shell remoto expandirá el comando y, además, si invoca SSH a través de un shell local, el shell local también realizará la expansión, por lo que deberá citar dos veces.

PHP proporciona laescapeshellargfunción para escapar de los caracteres especiales del shell. Desdeexecrealiza la expansión, llámalo dos veces en la cadena que deseas proteger.

Tenga en cuenta que esto está bien para cadenas de texto, pero no para cadenas de bytes. La mayoría de los shells no dejarán pasar bytes nulos.

Otro enfoque que es menos propenso a errores y permite el paso de cadenas de bytes arbitrarias, pero requiere cambiar lo que se ejecuta en el otro extremo, espasar la cadena en la entrada estándar del comando remoto.

Respuesta3

Podrías hacer algo como...

$ssh->enablePTY();
$ssh->exec('/path/to/daemon_adm.py');
$ssh->write('...');
echo $ssh->read();

información relacionada