如何安全地使用file_get_contents?

时间:2011-07-16 15:54:07

标签: php security

我正在为我博客的示例代码文件夹创建一个基本的PHP源代码查看器。

<?php

if (isset($_GET['file']))
{
    header('Content-type: text/plain');
    $filename = realpath($_GET['file']);
    if (startsWith($filename, dirname(__FILE__)))
    {
        echo file_get_contents($filename);
    }
}

function startsWith($haystack, $needle)
{
    $length = strlen($needle);
    return (substr($haystack, 0, $length) === $needle);
}

?>

我在这里有足够的东西,它永远不会允许查看此脚本所在目录或该脚本目录的子目录之外的文件吗?我猜测有一个比startsWith更好的解决方案,用于检查路径是否是特定目录的后代?

4 个答案:

答案 0 :(得分:3)

这是安全的,是的。 realpath部分是您必须做的,而您正在这样做。这段代码完成了它应该没问题。

答案 1 :(得分:0)

您可以减少文件名的输入(请参阅finfo)并指定要搜索的目录,如果它每次都是同一目录 - 那么您不需要通过startsWith()进行检查。

如果您只想显示PHP源代码,请尝试在您的网络服务器中启用* .phps文件处理。请参阅:https://serverfault.com/questions/62410/apache-htaccess-phps

答案 2 :(得分:0)

顺便说一句,请考虑使用strncmp而不是自定义的startsWith函数。

答案 3 :(得分:0)

如果我要接近这样的项目,我会:

结合使用您的解决方案&amp; htaccess将原始文件名掩盖为:

http://example.com/viewsource.php?file=./project1/index.php

太明显了,很容易搞乱,使用你可以拥有的htaccess:

http://example.com/source/project1/index.php

也指向

<强> h1ddEnfIlEs / viewSource / index.php文件= $ 1和;夹= $ 16

RewriteRule ^source/([a-z0-9]+)/([a-z0-9]+).php$ h1ddEnfIlEs/viewSourceScript/index.php?file=$2&project=$1

然后使用源查看器h1ddEnfIlEs / viewSourceScript / index.php

<?php 
if(
is_dir('./h1ddEnfIlEs/'.$_GET['project'].'/')===true && 
is_file('./h1ddEnfIlEs/'.$_GET['project'].'/'.basename($_GET['file']))
){
    highlight_file('./h1ddEnfIlEs/'.$_GET['project'].'/'.basename($_GET['file']));
}
?>