【问题标题】:Dynamic Include动态包含
【发布时间】:2010-10-05 17:36:45
【问题描述】:

在不将允许的页面放入数组/使用开关等的情况下,使用 $_GET 包含页面的最安全方法是什么。我有很多页面,所以不,谢谢。

$content = addlashes($_GET['content']); if (file_exists(PAGE_PATH."$content.html")) { 包括(PAGE_PATH。“$content.html”); }

这有多安全?

谢谢。

【问题讨论】:

  • 我很好奇:您能添加更多背景信息吗?你为什么想做这个?为什么你不能根据不同的区域/功能/等来组织你的网页?
  • 赞成,因为大多数答案似乎都没有认识到整个方法有多危险,这令人不安。

标签: php dynamic include


【解决方案1】:

这是非常糟糕的做法。您应该设置一个控制器来处理对需要执行或检索的代码的分派,而不是尝试直接从用户提供的变量中包含它。永远不要在包含文件时信任用户输入。您没有什么可以阻止他们包含您不希望包含的内容。

【讨论】:

  • +1 用于给出我的答案的通用版本,由于某种原因被否决了。 ;-) (file_exists() == TRUE) 表示什么都没有。除非您完全确定您的文件系统不会受到损害。
【解决方案2】:

如果您检查输入的有效模式,您会睡得更安全。例如假设您知道包含的文件永远不会有子目录并且总是字母数字

if (preg_match('/^[a-z0-9]+$/', $_GET['page']))
{
    $file=PAGE_PATH.$_GET['page'].".html";
    if (file_exists($file))
    {
         readfile($file);
    }
}

我用过readfile,好像.html文件都是静态的,没必要用include。

您的方法可能存在的缺陷是您可以设计系统中任何 HTML 文件的路径,并将其作为 PHP 执行。如果你能找到某种方法在文件系统上获取你自己设计的 HTML 文件,你可以通过你的脚本来执行它。

【讨论】:

  • 当然,“在文件系统上获取[攻击者]自己设计的文件”是脚本小子擅长的。 file_exists() 在这里真的没有给 OP 买任何东西,只是一种安全的错觉。
  • 问题是您的方法(Paul Dixon 的)也存在您在 OP 方法中发现的缺陷——除了在您的情况下,执行上下文是最终用户的浏览器。似乎下面关于 XSS 的 uber-downvoted 答案并没有完全超出范围......
  • 确实如此,但至少它将攻击可能性限制在一个目录而不是攻击者选择的一个目录中。
【解决方案3】:

将它与只接受“a-zA-Z-”的正则表达式匹配。

编辑:我不认为阻止特定模式是一个好主意。就像我说的那样,我宁愿做一个只接受我们知道不会导致漏洞利用的字符的正则表达式。

【讨论】:

    【解决方案4】:

    假设“允许”的页面集都存在于PAGE_PATH 下,那么我可能会建议如下内容:

    • 修剪页面名称
    • 拒绝以斜杠开头的页面名称(可能是绝对路径的尝试)
    • 拒绝包含.. 的页面名称(可能是路径遍历的尝试)
    • 明确前缀 PAGE_PATH 并包括(希望)安全路径

    如果您的页面名称都遵循一些一致的规则,例如字母数字字符,那么理论上你可以使用正则表达式来验证,拒绝“坏”的页面名称。

    PHP 网站上有一些more discussion of these issues

    【讨论】:

      【解决方案5】:

      它看起来通常是安全的,因为您在显示之前检查页面是否确实存在。但是,您可能希望创建一个人们不应使用有效 $_SESSION 凭据查看的页面的黑名单。这可以通过数组/开关来完成,或者您可以简单地将所有特殊页面放在某个目录中,然后检查。

      【讨论】:

        【解决方案6】:

        您可以首先扫描包含所有 HTML 模板的目录并将所有模板名称缓存在一个数组中,您可以验证 GET 参数。 但即使你缓存了这个数组,它仍然会产生某种开销。

        【讨论】:

          【解决方案7】:

          不要。你永远不会预料到所有可能的攻击,你会被黑客入侵。

          如果您想让您的代码不使用数组等,请使用包含两列 ID 和路径的数据库。通过数字 ID 请求页面。忽略所有对不是纯数字且不在您的有效 ID 范围内的 ID 的请求。如果您担心 SEO,您可以在链接中的数字 id 之后添加任意页面名称,就像 Stack Overflow 一样。

          数据库不必是重型的。例如,您可以使用SQLite

          【讨论】:

            【解决方案8】:

            最安全的方法是稍微清理一下请求。

            1. 删除任何../
            2. 剥离^\/

            从那里,确保您检查他们请求的文件是否存在并且可以读取。然后,只需 include 即可。

            【讨论】:

              【解决方案9】:

              你应该至少使用类似的东西来防止 XSS 攻击。

              $content = htmlentities($_GET['page'], ENT_QUOTES, 'UTF-8');
              

              addlashes 不会保护您免受 SQL 注入。

              【讨论】:

              • 他没有将页面名称注入到 SQL 语句中,也没有将其发送到 HTML;他包含了一个基于用户输入的文件,这需要不同的处理和逻辑来防止路径遍历攻击。
              • 我知道,但是使用加斜杠来防止 SQL 注入仍然很常见。
              • 是的,但他很明显没有试图使用它来防止 SQL 注入,而且你关于跨站点脚本的评论显然不合时宜。
              猜你喜欢
              • 2011-03-29
              • 2015-11-04
              • 1970-01-01
              • 2012-05-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-07-29
              • 1970-01-01
              相关资源
              最近更新 更多