在php中安全执行bash脚本

时间:2017-04-22 20:43:02

标签: php bash shell sandbox

我正在使用php中的浏览器shell(它使用build in exec函数或perl或python中的cgi脚本之一),我想允许对guest用户进行有限的shell访问。我有这个功能来清理用户命令:

private function validate_command($command) {
    $commands = array('echo', 'cat', 'ls', 'find', 'cd', 'grep');
    $cmd_re = "(" . implode("|", $commands) . ")";
    $re = "/^\s*($cmd_re|xargs\s*$cmd_re)/";
    $separators = "/(\||&&|\|\||;)/";
    $parts = preg_split($separators, $command, null, PREG_SPLIT_DELIM_CAPTURE);
    $result = array();
    foreach ($parts as $part) {
        if (preg_match($separators, $part)) {
            $result[] = $part;
        } else if (!preg_match($re, trim($part))) {
            $last = array_pop($commands);
            $message = "guest user can only execute: " .
                     implode(", ", $commands) . " and " . $last;
            throw new Exception($message);
        } else {
            // escapeshellcmd is not use here because it escape quotes
            // and * ? so you can't use find . -name "*.js"
            $result[] = preg_replace('/(\\\\|`|\$\()/', "\\\\$1", $part);
        }
    }
    return implode($result);
}

它适用于这样的命令:

find projects/jcubic -name '*.js' | xargs grep jcubic

但不允许执行find / | xargs rmrm *并转义$(`

这个功能安全吗?是否可以利用它来执行不允许的命令?如果不安全我怎样才能安全?这很难吗?

更新 @ jh1711评论之后的更新功能:

private function validate_command($command) {
    $commands = array('echo', 'cat', 'ls', 'find', 'cd', 'grep');
    $cmd_re = "(" . implode("|", $commands) . ")";
    $re = "/^\s*($cmd_re|xargs\s*$cmd_re)/";
    $separators = "/(&&|\|\||\||;)/";
    $parts = preg_split($separators, $command, null, PREG_SPLIT_DELIM_CAPTURE);
    $result = array();
    foreach ($parts as $part) {
        if (!preg_match($re, trim($part)) && !preg_match($separators, $part)) {
            $message = "guest user can only execute: " .
                     implode(", ", $commands) . " and xargs";
            throw new Exception($message);
        } else if (preg_match('/(>|`|\$\()/', $part)) {
            throw new Exception("guest user can't use redirect to write to files" .
                                " or execute subshell");
        } else {
            $result[] = $part;
        }
    }
    return implode($result);
}

还有什么我想念的吗?

0 个答案:

没有答案