在php7中使用shell_exec时,如何停止命令注入?

在php7中使用shell_exec时,如何停止命令注入?,php,security,Php,Security,我有一个html表单,要求用户输入一个域名,它被发布到下面的php7.0页面,由一个shell脚本进行处理,然后通过aha将输出传递到一个html页面,然后显示该页面 我遇到的问题是如何防止用户注入命令,如: domain.com | rm*-rf 我认为这可以通过使用safe_模式和限制可以运行命令的目录来实现,但是现在这个功能似乎已经被弃用了 $domain_arg = escapeshellarg( $_POST['domain'] ); $today = date("Y-m-d-H:i:

我有一个html表单,要求用户输入一个域名,它被发布到下面的php7.0页面,由一个shell脚本进行处理,然后通过aha将输出传递到一个html页面,然后显示该页面

我遇到的问题是如何防止用户注入命令,如:

domain.com | rm*-rf

我认为这可以通过使用safe_模式和限制可以运行命令的目录来实现,但是现在这个功能似乎已经被弃用了

$domain_arg = escapeshellarg( $_POST['domain'] );
$today = date("Y-m-d-H:i:s");
$cmd = "/home/ubuntu/dtest/dtest.sh $domain_arg | aha -b -t 'Domain test of $domain_arg' > /var/www/website/results/$domain_arg.$today.html";
$output = shell_exec($cmd);
header("Location: http://the.web.com/results/$result.$today.html");
您应该使用而不是escapeshellarg()

在运行参数之前,对参数使用,结果是一个带引号的字符串,如
'domain.com | rm*'
。您的问题是,您没有将其用作shell参数,而是将其用作shell参数的部分:

aha -b -t 'Domain test of $domain_arg'
这绝对会导致您描述的问题。请尝试以下方法:

<?php
$domain_arg = escapeshellarg($_POST["domain"]);
$log_msg = escapeshellarg("Domain test of $_POST[domain]");
$today = date("Y-m-d-H:i:s");
$log_file = preg_replace(
    "/[^\w:\\/.-]/i",
    "_",
    "/var/www/website/results/$_POST[domain].$today.html"
);

$cmd = "/home/ubuntu/dtest/dtest.sh $domain_arg | aha -b -t $log_msg > $log_file";
$output = shell_exec($cmd);
$result = rawurlencode($output); // just guessing that's where it comes from
$today = rawurlencode($today);
header("Location: http://the.web.com/results/$result.$today.html");

允许将用户输入注入
exec
命令非常危险。在进行此操作之前,最好先进行一些非常好的验证。我相信你可以编写一个验证程序,确保输入是一个有效的域名。使用
escapeshellarg
就是你所需要做的一切,你正在这么做。虽然你应该使用其他东西作为文件名组件。但是如果我放一个domain.com | rm*它会删除文件,所以escapeshellarg不会effective@miken32不同意escapeshellarg是“您所需要做的一切”。应该认真考虑如何避免将用户输入直接粘贴到shell命令中。我可以想象一些限制性很强的preg_match命令可能会起作用,但是验证将取决于正在运行的脚本的性质。不同的脚本存在不同的风险。我必须添加$filename=''。preg_替换(“/[^a-z0-9]/i'、“'、$”POST['domain'])$今天。html';将标题设置为$filename,我必须添加一个。之前的html,但否则这是完美的工作,我不能再删除文件,谢谢!我刚注意到你的编辑,我也会尝试这个版本。这很容易修复。我希望您在将其用于生产之前理解所有这些代码!;)我希望我能理解它,我有一些严肃的阅读要做。所有preg_replace的内容都让我感到困惑。
preg_replace
使用正则表达式将任何不安全的字符替换为下划线。它允许通过word(
\w
)字符(0-9,a-z)、冒号、破折号、斜线和点。其他东西都不见了。这可能有助于解释: