一个朋友问我一个编程问题:你有一个路径列表,让路径成为一个多维关联路径数组。样本输入:
$paths = [
"a/a/a",
"a/a/b",
"a/b/a"
];样本输出:
array(1) {
["a"]=>
array(2) {
["a"]=>
array(2) {
["a"]=>
string(4) "file"
["b"]=>
string(4) "file"
}
["b"]=>
array(1) {
["a"]=>
string(4) "file"
}
}
}当然,我可以使用递归或简单的循环和引用,但我想到了一个更懒惰的解决方案,让PHP引擎来完成所有的工作。
foreach($paths as $path) {
$filtered = addslashes($path);
$arrid = "['".str_replace("/", "']['", $filtered)."']";
eval("\$out$arrid = 'file';");
}因此,每个路径a/a/a都被转换为$out['a']['a']['a'] = 'file';,然后回避。因为PHP不需要在使用之前创建数组,所以这个解决方案可以工作。键名位于单引号内,而不是双引号内,因此不能包含局部变量,并且'和其他字符被反斜杠,所以我认为您不能用糟糕的路径名逃离键。在语言文档中,addslashes()的这种用法甚至被用作一个示例:
addslashes()的一个例子是当您将数据输入到PHP计算的字符串中时。
然而,我立即认为这个解决方案是不安全的,因为eval()是邪恶的。我不会在生产中运行这段代码,因为eval()只是不必要的,总是有风险的,一个错误就可能导致RCE,没有它有更好的解决方案,而且它比我编写的递归解决方案慢2倍,我只是想以一种奇怪的方式解决这个挑战,并且知道如果我在代码分析中看到类似的代码,应该做什么。我试着破门而入却没有运气。我知道对加法的多字节和编码攻击,但我觉得它在这里不适用。
那么,你真的能利用这段代码吗?
发布于 2022-08-10 10:34:23
由于您在使用$path函数之后用单引号封装了输入( addslashes() ),所以任何潜在的恶意输入都会被正确地转义。这里使用单引号的上下文非常重要。如果您不使用单引号而是双引号,则漏洞仍然存在。以您的示例中的以下行为例:
$arrid = "['".str_replace("/", "']['", $filtered)."']";
如果这样写的话:
$arrid = '["'.str_replace('/', '"]["', $filtered).'"]';
用户输入将在一个双引号字符串的上下文中,该字符串在PHP中允许变量。
现在,如果您使用复变量,如${phpinfo()},将执行phpinfo()函数。
以完整编辑的脚本为例:
我替换了$paths变量,因此它接受用户输入。使用以下URL可利用此漏洞:http://localhost/eval.php?paths[]=a/b/c&paths[]=c/b/c&paths[]=${phpinfo()}
这将输出phpinfo页面。此示例仅限于允许函数作为输入。为了使它更加灵活,您可以这样做:
http://localhost/?paths[]=a/b/c&paths[]=c/b/c&paths[]=${eval($_GET[1])}=123)&1=echo 5*5; echo "
something else";
path参数包括接收来自另一个$_GET[1]参数的输入的另一个eval。这允许插入多个语句,以便进行更复杂的攻击。
https://security.stackexchange.com/questions/263114
复制相似问题