【问题标题】:PHP Securely include files + handle invalid parametersPHP 安全地包含文件 + 处理无效参数
【发布时间】:2018-04-28 17:59:55
【问题描述】:

我遇到了一个小问题。如果参数无效,我想安全地包含基于来自子目录 + 句柄的 $_GET 参数的文件。

 <?php
if(isset($_GET['p']) && $_GET['p'] == 'fahrzeuge'){
        include 'includes/cars.php';
    }
  if(isset($_GET['p']) && $_GET['p'] == 'impressum'){
        include 'includes/impressum.php';
    }
    if(isset($_GET['p']) && $_GET['p'] == 'home'){
            include 'includes/home.php';
        }
      if(isset($_GET['p']) && $_GET['p'] == 'anfahrt'){
            include 'includes/anfahrt.php';
        }
        if(isset($_GET['p']) && $_GET['p'] == 'about'){
                include 'includes/about.php';
            }

?>

这是我的代码。对不起,我知道这是解决这个问题的一种菜鸟方式。我该如何改进它?任何建议/帮助将不胜感激

【问题讨论】:

    标签: php security include


    【解决方案1】:

    这是最快和最好的方法,我是短代码的粉丝 并从 (HACKBUGZ PHP) 中找到了这个。

    您有一个包含数组键数组值的数组。

    示例 1

    <?php
    
        $PAGES          = array();
      
        $PAGES = [
           'home'       => 'home.html'
          ,'about'      => 'about.php'
          ,'contact'    => 'somedir/contact.php'
        ];
    
        @include(substr($PAGES[$_GET['p']] ?? ('home'), 0, 255));
    
        exit;
    
    ?> 
    
    1. 您可以有不同的查询名称、文件名、文件类型和目录

    2. 如果文件不存在,@ 会捕获包含错误。

    3. substr($PAGES, 0, 255) 将 uri 削减为 255 个字符(如果你不喜欢这样的话 不做就行了)

    4. ($PAGES[$_GET['p']] ?? ('home')) 检查查询 (array_key) 是否存在于数组中,如果不存在 'home' 将是默认值 p>

    示例 2(无 substr)

    <?php
    
        $PAGES          = array();
      
        $PAGES = [
           'home'       => 'home.html'
          ,'about'      => 'about.php'
          ,'contact'    => 'somedir/contact.php'
        ];
    
        @include($PAGES[$_GET['p']] ?? ('home'));
    
        exit;
    
    ?> 
    
    

    【讨论】:

      【解决方案2】:

      我会使用ternary 来设置一个变量来告诉页面要包含的内容。

      这与Ofir Baruch 的回答非常相似,只是要短得多。

      $pages = array('about','contact','home');
      
      $p = isset($_GET['p']) && in_array($_GET['p'], $pages)? $_GET['p'] : 'home';
      include "includes/{$p}.php";
      

      基本上,您有一系列可能的页面。在三元中,我们检查是否设置了$_GET['p'] (isset()),并检查它包含的值是否在数组中。如果是,我们将$_GET['p'] 用作$p,如果不是,我们将$p 设置为home,这意味着如果$_GET['p'] 未设置或不设置,home 将始终为默认值根据数组的有效页面。

      【讨论】:

        【解决方案3】:

        设置合法页面数组。检查一次是否设置了$_GET['p'],如果设置了,则将其值(在转义后)分配给变量$p

        然后检查请求的页面 ($p) 是否在您的 pages 数组中定义,如果是 - 包括它。

        $pages = array('about','contact','home');
        
        $p = 'home'; //Default page
        if(isset($_GET['p'])) {
          $p = $_GET['p']; //no need to escape as we compare it to predefined values as @Yoshi suggested
        } 
        
        if(in_array($p, $pages)){
          include 'includes/'.$p.'.php';
        } else {
           include 'includes/home.php';
        }
        

        【讨论】:

        • 感谢您的快速回复。如果可行,我将对其进行测试并接受您的问题。或者如果它不能按我想要的方式工作。我会让你知道或问你
        • 当然,没问题。更新我。
        • 真的有必要做htmlspecialchars()并检查一个数组吗?如果$p 包含特殊字符,它就不会加载任何内容,因为该值不会在数组中。如果是页面名称,则必须是文件名,这意味着无论如何都不应该有任何特殊字符,除非我猜可能是一个空格
        • 嘿,它确实有效 + 但如果用户试图修改参数,我也想处理。在这种情况下,页面不包含任何内容并且看起来很糟糕,因此我想包含主页。恐怕这很简单:P
        • 不要转义p,只用它作为数组键,值来包含页面。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-06
        • 2023-02-05
        • 1970-01-01
        • 2018-05-08
        相关资源
        最近更新 更多