包含“php:// memory”流

时间:2012-03-30 14:24:47

标签: php include memorystream

我正在为一个浏览器应用程序编写一个系统,它将一些特定的PHP脚本存储在一个数据库中,然后将它们拉出来并在需要时执行它们。起初我尝试使用exec()和管道输出一个脚本的输出,该脚本将脚本从数据库中取出并打印出来。这在一个用例中起作用,但不是全部,并且无论如何都感觉很脆弱,所以我正在寻找更好的方法。

我现在正试图通过在内存中使用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”答案。非管理员用户无权编写存储在数据库中的脚本,我知道这需要对我的应用程序的生命周期进行特殊处理。

3 个答案:

答案 0 :(得分:5)

您需要使用stream_get_contents来阅读php://memory stream。您不能直接包含它。

答案 1 :(得分:4)

eval()include实际上非常相似。因此,eval()适用于多行 - 仅供参考。但是,我更喜欢include,我一直认为它更快。也许我错了,不知道。

但是,我认为你应该调试你的代码,我没有看到原因,为什么它不应该工作。您可能需要rewind指针(您已评论过),但您应该直接检查的是that your PHP configuration allows to include URLs。我知道该设置会阻止使用data:// URI,因此您可能已启用此功能。

此外,如果PHP可以使用file_get_contents打开内存并转出,您也可以尝试。这应该给你代码。如果没有,你已经犯了一些错误(例如没有倒带或类似的东西)。

编辑:我没到那么远(demo):

<?php
/**
 * Include from “php://memory” stream
 * @link https://stackoverflow.com/q/9944867/367456
 */

$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. 您不应该关闭“文件”。 php://memory是一个关闭后会消失的流。
  2. 您需要以$fp作为流来访问,这对于开箱即用的include AFAIK来说是不可能的。
  3. 然后,您需要创建一个将流资源映射到文件名的流包装器。
  4. 完成后,您可以添加内存流。
  5. 您需要检查的PHP设置。有不止一个,请参阅PHP手册。
  6. 使用数据URI(demo)可能更容易:

    <?php
    /**
     * Include from “php://memory” stream
     * @link https://stackoverflow.com/q/9944867/367456
     */
    
    $thing = <<<TEST
    <?php
    \$thing = array();
    print "Testing code in here.";
    var_dump(\$thing);
    TEST;
    
    include 'data://text/plain;,'. urlencode($thing);
    

    请参阅:Include code from a PHP stream

答案 2 :(得分:1)

如果有一种方法可以从php://内存中加入,那么这是一个严重的漏洞。虽然它有很多用途,但eval常常使用代码混淆技术来隐藏恶意代码。

(如果你握紧它,每个工具都是武器。)

有了这个说,那里(谢天谢地)似乎没有任何明显的方式来包含从php:// memory