与PHP的SSH连接

时间:2012-11-20 11:10:13

标签: php linux ssh

我目前正在开发一个使用PHP对系统进行更改的项目(例如,更改Nginx /重启服务的配置文件)。

PHP脚本在localhost上运行。在我看来,最好的(读取:最安全)方式是使用SSH建立连接。我考虑以下选项之一:

选项1:在php会话中存储用户名/密码并提示输入sudo

将phpseclib与用户名/密码一起使用,将这些值保存在php会话中,并为每个命令提示sudo。

选项2:使用root登录

在登录脚本中使用phpseclib和root用户名和密码。在这种情况下,您不必向用户询问sudo。 (不是真正安全的解决方案)

<?php
include('Net/SSH2.php');

$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('root', 'root-password')) {
    exit('Login Failed');
}
?>

选项3:使用从文件中读取的公钥进行身份验证

使用带有公钥的PHP SSHlib进行身份验证,并将pubkey放在www root之外。

<?php

    $connection = ssh2_connect('shell.example.com', 22, array('hostkey' => 'ssh-rsa'));
    if (ssh2_auth_pubkey_file($connection, 'username', '/home/username/.ssh/id_rsa.pub', '/home/username/.ssh/id_rsa', 'secret')) {
        echo "Public Key Authentication Successful\n";
    } else {
        die('Public Key Authentication Failed');
    }
?>

选项4:?

6 个答案:

答案 0 :(得分:11)

我建议你通过3个简单的步骤来完成这个任务:

<强>首先 创建另一个用户(例如runner)并使您的敏感数据(如用户/通行证,私钥等)仅对此用户可访问。换句话说,拒绝你的php代码可以访问这些数据。

<强>第二 之后创建一个简单的阻塞fifo管道并授予对php用户的写访问权。

过去。 最后编写一个简单的守护进程来读取fifo中的行,并通过ssh命令执行它。使用runner用户运行此守护程序。

要执行命令,只需在文件(fifo管道)中编写命令即可。如果需要,输出可以在另一个管道或一些简单文件中重定向。

使fifo使用这个简单的命令:

mkfifo "FIFONAME"

转轮守护程序将是一个简单的bash脚本,如下所示:

#!/bin/bash
while [ 1 ]
do
    cmd=$(cat FIFONAME | ( read cmd ; echo $cmd ) )
    # Validate the command
    ssh 192.168.0.1 "$cmd"
done

在此之后你可以信任你的代码,如果你的php代码完全被黑了,你的上游服务器还是安全的。在这种情况下,攻击者根本无法访问您的敏感数据。他可以向您的runner守护程序发送命令,但如果您正确验证命令,则不用担心。

: - )

答案 1 :(得分:1)

方法1

我可能会使用suid flag。写一点suid wrapper in C并确保它执行的所有命令都是预定义的,不能由你的php脚本控制。 因此,您创建了包装器并从ARGV获取命令。所以电话看起来像这样:

./wrapper reloadnginx
然后

Wrapper执行/etc/init.d/nginx reload

确保chown包装到root和chmod +s。然后它将以root身份生成命令,但由于您预定了所有命令,因此您的php脚本无法以root身份执行任何其他操作。

方法2

使用sudo并为passwordless execution设置某些命令。这样您就可以获得相同的效果,并且只能以root身份生成某些应用程序。但是,您无法控制参数,因此请确保这些二进制文件中没有权限提升。

你真的不想给PHP脚本提供完全的root访问权限。

答案 2 :(得分:0)

如果您在同一主机上运行,​​我建议您直接编写配置文件并(重新)启动服务或编写包装脚本。

第一个选项显然需要非常高的权限级别,我不建议这样做。但是,它将是最简单的实现。使用ssh的其他命名选项没有多大帮助,因为可能的攻击者仍然可以轻松获得root权限

第二种选择更安全,涉及编写具有高级访问权限的程序,该程序仅接受指定的输入文件,例如从目录。 php脚本仅仅是用户的前端,并且将写入所述输入文件,因此只需要非常低的权限。这样,您就可以将高权限和低权限分开,从而降低风险,因为保护程序要容易得多,可能的攻击者只能通过文本文件间接工作。此选项需要更多工作,但更安全。

答案 3 :(得分:0)

您可以扩展选项3并使用没有任何库的SSH密钥

$command = sprintf('ssh -i%s -o "StrictHostKeyChecking no" %s@%s "%s"',
                $path, $this->getUsername(), $this->getAddress(), $cmd );
return shell_exec( $command );

我在我的项目中使用了很多。您可以查看我创建的SSH adapter

上述问题是您无法做出实时决策(连接到服务器时)。如果您需要实时,请尝试使用名为SSH2的PHP扩展。

PS。我同意你的看法。 SSH接缝是最安全的选择。

答案 4 :(得分:0)

您可以使用setcap来允许Nginx绑定到端口80/443而无需以root身份运行。 Nginx只需要以root身份运行以绑定端口80/443(任何&lt; 1024)。 this answer详细介绍了setcap

但有几个问题。您必须将chown日志文件发送给正确的用户(chown -R nginx:nginx /var/log/nginx),并将pid文件配置为/var/run/pid /path/to/nginx.pid)以外的其他位置。< / p> lawl0r为setuid / sudo提供了一个很好的答案。

作为最后一个重新开始,您可以使用cron作业定期重新加载配置(如果已更改)。

无论哪种方式,当它在同一系统上时都不需要SSH。

答案 5 :(得分:-1)

老兄说完全错了。

您不想更改要创建新文件的任何配置文件,然后将它们包含在默认配置文件中

你有* .conf文件和include指令的apache示例。更改默认配置文件完全是疯了。这就是我的方式。

你不需要ssh或类似的东西。

如果你愿意的话,相信我会更好更安全。