从“php://memory”流中包含

9
我正在为一个浏览器应用程序编写系统,该系统将在数据库中存储一些特定的php脚本,然后在需要时将它们提取出来并执行。起初,我尝试使用exec()和管道将从数据库中获取脚本并打印输出的脚本的输出传递给php。这在一个用例中可以工作,但不是所有情况都适用,并且感觉很脆弱,因此我正在寻找更好的方法。
现在,我正在尝试通过在内存中使用PHP文件流来实现这一目标。例如:
$thing = <<<'TEST'
<?php

$thing = array();

print "Testing code in here.";
var_dump($thing);

?>
TEST;

$filename = "php://memory";

$fp = fopen($filename, "w+b");
fwrite($fp, $thing);
//rewind($fp);

fclose($fp);

include "php://memory";

执行脚本时没有输出任何内容。这种方法是否可行?如果不行,是否有其他方法可以实现?我试图避免编写临时文件并从中读取,因为我相信访问文件系统会减慢速度。是否有一个URL可以提供“包含”,以便它将读取内存流,就像读取文件一样?
我认为eval()不能做到这一点,因为如果我记得正确,它只能处理单行代码。
同时,请不要回答"eval = include = hell"。非管理员用户无法访问存储在数据库中的脚本,我知道这需要在应用程序的生命周期中进行特殊处理。

我的天,我完全错了。Eval可以处理多行代码。我甚至都没有尝试过,哈哈...那么这应该可以解决问题。不过,我仍然对存储在内存中的文件流很好奇,如果有人能回答这个问题,我会非常感激。 - terminal_case
你不想创建文件有特别的原因吗?文件系统是文件的数据库。还有:天哪,不要这样做,那太危险了。即使只有管理员可以写入这些php文件,一旦出现SQL注入漏洞或有人设法获取/猜测/揭示你的MySQL凭据->立即远程代码执行。 - mensi
3个回答

6
你需要使用 stream_get_contentsphp://memory stream 中读取。你不能直接包含它。

6
eval()include实际上是相似的。所以,eval()可以处理多行代码-仅供参考。然而,在这里我更喜欢include,我总觉得它更快。也许我错了,不确定。
然而,我认为你应该调试你的代码,我并没有看到任何理由导致它不能工作。你可能需要rewind指针(你已经注释掉了),但你首先应该检查的是你的PHP配置是否允许包含URLs。我知道这个设置会阻止使用data:// URI,因此你可能启用了它。
另外,你可以尝试使用file_get_contents打开内存并进行转储。这应该给你代码。如果没有,那么你已经犯了一些错误(例如没有倒回或类似的事情)。
编辑:我还没有做到这一步(演示)。
<?php
/**
 * Include from “php://memory” stream
 * @link https://dev59.com/IGLVa4cB1Zd3GeqPtiZr
 */

$thing = <<<TEST
<?php
\$thing = array();
print "Testing code in here.";
var_dump(\$thing);
TEST;

$filename = "php://memory";

$fp = fopen($filename, "w+b");
fwrite($fp, $thing);
rewind($fp);

var_dump(stream_get_contents($fp));

这是我找到的:
  1. 不应关闭“file”。php://memory是一种流,一旦关闭,它将消失。
  2. 您需要访问作为流的$fp,这对于include来说可能不是默认情况。
  3. 然后,您需要创建一个流包装器,将流资源映射到文件名。
  4. 完成后,您可以包含内存流。
  5. 无论如何,您都需要检查PHP设置。有不止一个,请参阅PHP手册。
使用数据URI可能更容易(演示):
<?php
/**
 * Include from “php://memory” stream
 * @link https://dev59.com/IGLVa4cB1Zd3GeqPtiZr
 */

$thing = <<<TEST
<?php
\$thing = array();
print "Testing code in here.";
var_dump(\$thing);
TEST;

include 'data://text/plain;,'. urlencode($thing);

请参考:从PHP流中包含代码


这会产生未定义变量的错误。 为了修复它,请将 var_dump($thing); 更改为 var_dump(\$thing); - Cláudio Silva
@CláudioSilva:已修复。感谢提示。 - hakre

1
如果有从php://memory包含的方法,那么这是一个严重的漏洞。虽然它有许多用途,但eval经常与代码混淆技术一起使用,以隐藏恶意代码。
(每个工具都是一把武器,取决于你如何使用。)
话虽如此,幸运的是,似乎没有明显的方法可以从php://memory中进行包含。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接