【问题标题】:PHP safe $_GET or notPHP 是否安全 $_GET
【发布时间】:2010-08-02 15:01:49
【问题描述】:

我们有网址:

http://site.com/index.php?action=show

$_GET['action']在模板中用于检查?action=的值:

switch ($_GET['action']) {
    case = "show" {
        $match_show = true;
    }
}

在其他地方:

echo $_GET['action'];

使用这种结构绝对安全吗?

如何保证它们的安全?

谢谢。

【问题讨论】:

  • 永远不要直接回显从云端发送的数据。

标签: php get


【解决方案1】:

开关没问题,因为您正在与硬编码值进行比较(但是,它是case "show": btw)。

正如@Bruce 在 cmets 中提到的那样,您还应该添加一个 default: 案例以捕获不在列表中的值或空值:

switch ($_GET['action']) {

    case "show":
        $match_show = true;
        break;

    default: 
        // value is not on the list. React accordingly.
        echo "Unknown value for 'action'". 

}

第二件事有潜在的危险,因为它可以将 HTML 和更重要的 JavaScript 注入到文档正文中。在回显变量之前,您应该在变量上应用 htmlspecialchars()

【讨论】:

  • 没注意到他在用 switch 过滤东西 + 1
  • 我倾向于进一步验证$_GET['action'] 是否符合预期操作列表,如果不是其中之一则失败
  • @Michael 好点。 @Ignatz 一定要在你的 switch 中有一个 default: 案例。
  • 如果'action' 不存在,switch 将抛出错误(如果启用)。根据固定集检查输入是好的,但除了添加 default 案例之外,您还应该检查参数是否已传递。
  • 如果'action' 不存在,$_GET['action'] 也会失败。这可能会显示错误(或停止执行),具体取决于 PHP 的配置方式。
【解决方案2】:

$_GET 超全局默认情况下是不安全的,因为它可能包含特殊或编码字符以及其他不需要的文本序列。

您可以使用内置的 PHP 函数 filter_input 根据几个标准过滤器来清理字符串(请参阅 list of filters 了解可能的情况)。

示例:

if (!($action = filter_input(INPUT_GET, 'action', FILTER_SANITIZE_STRING))) {
    $action = 'some-default'; 
}

优点:

依靠内置的清理过滤,确保:

  • 随着 PHP 的修补提供安全修复程序
  • 一致/标准过滤
  • 可靠的过滤器实现(在性能和安全性方面)
  • 还提供了明确的默认情况

缺点:

  • 语法有点难记
  • 如果您修改超全局$_GET,则不能使用filter_input(无论如何您可能不应该这样做)。

旁注

您还可以使用in_array 检查该字段是否为集合之一,这是一种更动态的方法来检查您是否拥有集合中的一个。

$search = in_array($search, array('show', 'hide')) ? $search : 'some-default';

动态方法允许您安全地执行或查找目标操作,同时将一组潜在选择存储在数据结构中而不是静态代码中。

【讨论】:

    【解决方案3】:

    是的,如前所述,您必须在盲目使用任何$_GET 变量之前验证它的值。但是……

    您还应该在使用它之前检查它是否存在。根据您在服务器上设置 error_reporting() 的方式,如果您尝试使用 $_GET['action'] 并且在 URL 中未指定 ?action=something,那么您将获得 E_NOTICE - Undefined index : action,这会污染您的错误日志或更糟,出现在浏览器中。

    $urlAction = isset($_GET['action']) ? $_GET['action'] : null;
    
    if (isset($urlAction)) {
      // Rest of validation...
    }
    

    【讨论】:

      【解决方案4】:

      有时当我有很多初学者为网站创建插件或模块时,我会使用类似...

      foreach($_GET as $key=>$value) {
        if(functions_exists('clean_get_'.$key)) {
          $_GET[$key]=call_user_func('clean_get_'.$key,$value);
        } else {
          unset($_GET[$key];
        }
      }
      

      ...所有的 get 和 post 值都被“神奇地”清理或删除,所以我不需要担心别人的 sql-injectable 插件。

      或者,如果你是延迟加载的粉丝......

         foreach($_GET as $key=>$value) {
            if(is_file('clean_get_'.$key.'.php')) {
              include_once('clean_get_'.$key.'.php');
              if(functions_exists('clean_get_'.$key)) {
                $_GET[$key]=call_user_func('clean_get_'.$key,$value); 
              } else {
                unset($_GET[$key]);
              }
            } else {
              unset($_GET[$key];
            }
          }
      

      ps。代码是直接写到这里的,很有可能出错!

      【讨论】:

        【解决方案5】:

        PHP $_GET 本身是不安全的,它可以在多个领域被利用,为了获得良好的阅读和示例,我建议您阅读这篇文章

        http://articles.sitepoint.com/article/php-security-blunders

        【讨论】:

        • 废话。 $_GET 并非“本身不安全”。它包含可以被操纵的数据,但只要这些数据没有被愚蠢地使用,那不是安全风险。
        • @Flakron 您发布的链接仍然是一个很好的资源,而且这些错误往往会经常发生。
        • 您应该澄清,不安全的不是 $_GET,而是您不能依赖的 $_GET 中的值是有效的。
        • @Pekka 这有点值得商榷;大多数“PHP 失误”似乎是与 PHP 无关的标准 Web 安全问题
        • @Michael 绝对是。这些错误并非特定于 PHP(尽管其他平台在过滤某些攻击方面做得更好)。但是这篇文章值得每个 PHP 新手阅读。
        【解决方案6】:

        要将空(未设置)值替换为默认值,请尝试以下操作:

         $variable = isset($_GET['get_variable']) ? $_GET['get_variable'] : 'some-default';     
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-04
          • 2012-01-07
          • 1970-01-01
          • 2015-11-15
          相关资源
          最近更新 更多