【发布时间】:2017-04-28 07:36:01
【问题描述】:
我有这个函数来验证 php 中的命令?
public function validate_command($command) {
if (isset($this->config->settings->guest_commands)) {
$commands = $this->config->settings->guest_commands;
} else {
$commands = array('echo', 'cat', 'ls', 'find', 'cd', 'grep', 'test', 'xargs');
}
$cmd_re = "(" . implode("|", array_diff($commands, array("xargs"))) . ")";
if (in_array("xargs", $commands)) {
$re = "/^\s*($cmd_re|xargs\s*$cmd_re)/";
} else {
$re = "/^\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)) {
$last = array_pop($commands);
$message = "guest user can only execute: " .
implode(", ", $commands) . " and " . $last;
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);
}
它使用以下命令拆分命令:
$separators = "/(&&|\|\||\||;)/";
$parts = preg_split($separators, $command, null, PREG_SPLIT_DELIM_CAPTURE);
如何使它适用于echo "©" 之类的命令?它应该返回相同的命令,但会抛出异常。
我可以在后面使用单个正则表达式吗?它应该是什么样子?它应该适用于这样的情况:
echo "©\"©" && echo "©"
$parts 应该有array('echo "©\"©"', '&&', 'echo "©"')(可以包含 && 或命令周围的空格)
我尝试了$separators = "/(?<*)(&&|\|\||\||;)/";,但出现异常:
preg_split(): Compilation failed: lookbehind assertion is not fixed length at offset 24
遍历字符串是唯一的选择吗?
【问题讨论】:
-
那个 preg_split() 错误是因为这个
[\"'])*部分在后视。后面是zero length assertions。你不能给它们添加量词。 -
您想将
&copy;视为&吗?那就换吧。或者将&copy;&copy;添加到正则表达式模式中。 -
@WiktorStribiżew 想要忽略拆分正则表达式,如果它在单引号或双引号中。
-
所以,匹配它们并跳过 - 在你的正则表达式前面加上
(?:"[^"]*"|'[^']*')(*SKIP)(*F)| -
@WiktorStribiżew 它有效,你可以添加一个答案,但我用过
"/1(?:\"(?:[^\"]|\\\")*\"|'(?:[^']|\\')*')(*SKIP)(*F)|(&&|\|\||\||;)/"
标签: php regex preg-split