【问题标题】:PHP Securely transform $_GET / $_POST arrayPHP 安全地转换 $_GET / $_POST 数组
【发布时间】:2012-01-16 14:52:23
【问题描述】:

我正在检查我的脚本是否存在漏洞,并且对我过去的做法感到震惊,这是非常不安全的:

foreach ($_GET as $key => $value){
    $$key = $value;
}

或更短

extract( $_GET );

我用 firebug 更改了一些 POST/GET 变量以匹配我在脚本中使用的名称。 如果名称猜对了,它们可以被覆盖。

所以我想我必须像这样单独命名: $allowed_vars =

$allowed_vars = array("time","hotfile","netload","megaupload","user","pfda","xyz","sara","amount_needed");
    foreach ($_GET as $key => $value)
        {
             if (in_array($key,$allowed_vars))
                {
                    $$key = $value;
                }
        }

这种方式比单独命名它们节省了一些时间。

为此必须使用什么样的自动化?

【问题讨论】:

  • 为什么必须首先将它们分配给单个变量?就不能用$_GET[ 'time' ]之类的吗?
  • 仅供参考,您将 $allowed_vars 放在 foreach 之外,没有理由每次都设置它
  • @Juahana 1. 易于使用,2. 防止逃逸。只是编码风格,这里不是真正的问题
  • @ben 好点。改正了
  • 防止转义?这是什么?

标签: php post get extract


【解决方案1】:

我不使用任何那种自动化。
我认为将请求变量自动分配给全局变量没有意义。
如果是一两个变量,我可以手动处理。
如果还有更多,我宁愿将它们保留为数组成员以方便处理。

然而,我正在使用某种类似于您的白名单方法。 但不是从 POST 数据中创建全局变量,而是将该数据添加到 SQL 查询中。

就像在这个简单的辅助函数中生成 SET 语句:

function dbSet($fields) {
  $set='';
  foreach ($fields as $field) {
    if (isset($_POST[$field])) {
      $set.="`$field`='".mysql_real_escape_string($_POST[$field])."', ";
    }
  }
  return substr($set, 0, -2); 
}

$id     = intval($_POST['id']);
$fields = explode(" ","name surname lastname address zip fax phone");
$query  = "UPDATE $table SET ".dbSet($fields)." stamp=NOW() WHERE id=$id";

【讨论】:

  • 你的最后一个论点是有道理的。我会重新考虑我的编码风格。
  • @Email:这是一个一般的例子,当然,你还是要确保你得到了期望值;就像一个 zip 真的是一个 zip 等等。另外,如果你想使用 null 值,你需要稍微改变一下。
【解决方案2】:

完全不提取它们可以节省更多时间。只需从 $_GET 数组中使用它们。这样做的好处不仅在于避免与脚本变量发生冲突(或更糟),而且还在于您在添加请求参数时不必更新“自动化”。

当我处理来自表单的 POST 数据时,我经常明确地处理每个数据:

$data = array();
$data['field1'] = someSaniFunction($_POST['field1']);
$data['field2'] = someOtherFunction($_POST['field2']);
...

这样我确保每个字段都得到正确处理,并且只触及我期望的字段。

【讨论】:

  • 我猜用 1 个单词重写 automatism 比用 $_POST['something'] 2+ 次写入变量的额外时间节省更多时间
【解决方案3】:

根据我的经验,您不应该使用 $$$_REQUEST 数组中的数据转换为变量,因为它可能会覆盖当前范围内的变量。

相反,您应该考虑使用请求对象或数组来过滤数据并仅访问您需要的命名变量。这样一来,您不必继续扩展允许的变量名称并仍然保持安全性。

例如,ZF 有一个请求对象,他们建议在处理此数据时使用输入过滤器: http://framework.zend.com/manual/en/zend.filter.input.html

【讨论】:

    【解决方案4】:

    您可以以更安全的方式使用提取功能:

    extract($_REQUEST, EXTR_SKIP);
    

    这不会覆盖代码中已经存在的变量。请参阅here 了解您可以使用的其他参数

    【讨论】:

    • 不过还是和register_globals类似的坑——如果你没有为普通用户定义变量$admin,也可以这样创建。
    • @Col.Shrapnel 当然。然后你必须运用常识和一些开发人员技能来避免这种情况.. :)
    • 我宁愿避免 extract() 函数
    • extract 不能解决问题。它还通过在大型数组中放入内存并深入扫描脚本来使用 cpu。不安全
    • 我没有说是更好的选择。我只是指出你可以通过添加一些参数来更安全一点。
    猜你喜欢
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多