【问题标题】:Security Flaws?安全漏洞?
【发布时间】:2024-11-07 05:45:02
【问题描述】:

使用此代码有什么影响?

<?php
if(file_exists("pages/" . $_GET["page"] . ".php")){
    include("pages/" . $_GET["page"] . ".php");
    } else{
        include("pages/home.php");
        }
?>

我已经做到了,如果没有“.php”扩展名,您将无法加载任何内容,所以我认为它使用起来非常安全。如果你使用:

website.com/index.php?page=../index 

在 url 中它会创建一个无限循环。据我所知,您无法加载外部 URL。

例子:

website.com/index.php?page=anothersite.com/virus

但我不太确定,有什么建议吗?或者这个可以用吗?

【问题讨论】:

  • 您可能应该查看 Apache 的 mod_rewrite(假设您使用的是 Apache)。
  • @Matt Browne,如果他不使用 Apache 怎么办?还有一些其他可用的 Web 服务器比 Apache 好得多。
  • 虽然@RomanNewaza 我正在使用apache
  • @RomanNewaza 这就是我说“假设您使用的是 Apache”的原因——这是我做出的一个初步假设,因为它在 PHP 世界中很常见。

标签: php security


【解决方案1】:

正如zerkms 已经指出的,根据PHP 版本,file_existsinclude 可能not be safe when handling NULL bytes。仅限since PHP version 5.4.3, filesystem functions are said to be NULL byte safe

因此,您应该在使用该值之前对其进行验证,例如,通过使用允许值的白名单:

$allowedPages = array(/* … */);
if (in_array($_GET["page"], $allowedPages)) {
    // allowed
}

您还可以将此白名单扩展到文档根目录下的任何现有文件:

if (strpos($_GET["page"], "\0") !== false) {
    // NULL byte detected
}
$path = realpath("pages/" . $_GET["page"] . ".php");
$base = realpath($_SERVER['DOCUMENT_ROOT']) . "/";
if ($path !== false && substr($path, 0, strlen($base)) === $base) {
    // allowed
}

但是,这仍然可以用来绕过其他访问控制措施,例如基于位置的 HTTP 授权。

【讨论】:

    【解决方案2】:

    ../../ 模式与空字节结合使用会导致路径“逃逸”其外壳。

    "../../../etc/passwd\0.php"
    

    你可以做两件事:

    1. 使用您愿意接受的可能值的白名单。

    2. 先清理路径,例如

      $path = preg_replace('/[^a-z]/', '');
      // now use $path as you would
      

    【讨论】:

      【解决方案3】:

      正如你所指出的那样,这样做会导致无限循环帽子会导致 php 崩溃。

      PHP 崩溃会导致很多不好的事情。例如,您可以上传不会被删除的临时文件。这最终可能导致巨大的泄漏和攻击。

      【讨论】:

        【解决方案4】:

        首先,根据URL参数包含页面是不安全的,很容易被用户弄乱,你最好避免。

        其次,如果要避免包含外部url,可能需要根据http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include配置php.ini

        如果你还没有进入配置 php.ini,你可以先修剪 $_GET['page'] 中的 "http://", "https://" 字符串,这是一个很好的行为,并制作一个 .htaccess 文件将不存在的页面请求重定向到 home.php,您还必须确保 mod_rewrite 在您的服务器上。

        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} -s [OR]
        RewriteCond %{REQUEST_FILENAME} -l [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        
        RewriteRule ^.*$ - [NC,L]
        RewriteRule ^.*$ home.php [NC,L] 
        

        【讨论】:

          【解决方案5】:

          我将导致一个称为本地文件包含的严重漏洞,GET参数没有过滤更好地过滤它正如jack所说的那样,或者只是使用php realpath()函数,这有点简单。

          【讨论】: