【问题标题】:Properly escaping SSH command in PHP在 PHP 中正确转义 SSH 命令
【发布时间】:2012-12-03 01:15:56
【问题描述】:

我有一个 SSH 命令,我想用 PHP 中的 libssh2 执行:

sh -c '
  rm -f /tmp/command.log
  sleep 3 &
  screen -p 0 -X stuff "\
script -a -c \"ls -l\" /tmp/command.log; kill -USR1 $!
"
  wait
  cat /tmp/command.log
'

我似乎无法正确地转义它,所以 SSH 完全按照上面的方式接收它。我需要将它用双引号括起来,这样我也可以在其中获取 PHP 变量(ls -l 将变为 $command)。

我试过了:

"sh -c '
  rm -f /tmp/command.log
  sleep 3 &
  screen -p 0 -X stuff \"\
script -a -c \\"ls -l\\" /tmp/command.log; kill -USR1 $!
\"
  wait
  cat /tmp/command.log
'"

还有:

"sh -c '
  rm -f /tmp/command.log
  sleep 3 &
  screen -p 0 -X stuff \"\
script -a -c \\\"ls -l\\\" /tmp/command.log; kill -USR1 $!
\"
  wait
  cat /tmp/command.log
'"

第一个返回 PHP 错误,第二个不运行命令。

整个函数(在摩根王尔德建议的编辑之后):

    function runShellCommand($command, $host, $user, $pass, $port){
        if (!function_exists("ssh2_connect")) die("Fail: function ssh2_connect doesn't exist");
        if(!($con = ssh2_connect($host, $port))){
            return "Unable to establish connection. Is your server offline?";
        } else {
            if(!ssh2_auth_password($con, $user, $pass)) {
                return "Failed to authenticate. Please ensure your server's password matches our records.";
            } else {
                $run = <<<HEREDOC
sh -c '
rm -f /tmp/command.log
sleep 3 &
screen -p 0 -X stuff "\
script -a -c \"touch /root/test234\" /tmp/command.log; kill -USR1 $!
"
wait
cat /tmp/command.log
'
HEREDOC;
                if (!($stream = ssh2_exec($con,  $run ))) {
                    return "Could not run command.";
                } else {
                    stream_set_blocking($stream, true);
                    $data = "";
                    while ($buf = fread($stream,4096)) {
                        $data .= $buf;
                    }
                    fclose($stream);
                    if(empty($data)){
                        return "sh-4.1# $command\n\n";
                    } else {
                        return "sh-4.1# $command\n$data\n";
                    }
                }
            }
        }
    }

【问题讨论】:

    标签: php shell ssh escaping libssh2


    【解决方案1】:

    使用HEREDOC 字符串引用怎么样?我没有尝试过,但它适用于其他用例。

    $command = <<<HEREDOC
    sh -c '
    rm -f /tmp/command.log
    sleep 3 &
    screen -p 0 -X stuff "\
    script -a -c \"ls -l\" /tmp/command.log; kill -USR1 $!
    "
    wait
    cat /tmp/command.log
    '
    HEREDOC;
    

    更多信息在这里 - http://php.net/manual/en/language.types.string.php

    【讨论】:

    • 奇怪,它仍然没有正确运行命令。我将发布整个功能。
    • @JamesHadley 首先确保您提供的ssh2_exec 方法的语句序列是有效且有意义的。我无法澄清,因为我没有这方面的专业知识,所以我的回答完全基于正确转义 ssh 命令的需要。我认为,如果您不完全了解命令是否格式正确,您可能需要创建一个新问题。我说的对吗?
    • 命令格式正确——它在终端上运行得很好。诚然,标题有点狭窄,因为我认为问题只是与转义有关,尽管这里似乎还有一个问题。我想知道 libssh2 是否完全不支持多行命令?
    • @JamesHadley 一定要看看这条评论php.net/manual/en/function.ssh2-exec.php#59324
    • 也试过这个功能,我认为结论是 libssh2 不喜欢多行命令。感谢您的帮助。
    【解决方案2】:

    试试phpseclib, a pure PHP SSH implementation。例如。

    <?php
    include('Net/SSH2.php');
    
    $ssh = new Net_SSH2('www.domain.tld');
    if (!$ssh->login('username', 'password')) {
        exit('Login Failed');
    }
    
    echo $ssh->read('username@username:~$');
    $ssh->write("rm -f /tmp/command.log\n");
    echo $ssh->read('username@username:~$');
    $ssh->write("sleep 3 &\n");
    echo $ssh->read('username@username:~$');
    $ssh->write("screen -p 0 -X stuff \"\
    script -a -c \\\"ls -l\\\" /tmp/command.log; kill -USR1 $!
    \"");
    ...
    ?>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-19
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 2013-07-08
      相关资源
      最近更新 更多