【问题标题】:php $POST dynamic variable names security concernsphp $POST 动态变量名安全问题
【发布时间】:2012-07-19 05:26:14
【问题描述】:

我正在考虑创建一个循环来收集我所有的 $_POST 变量并将它们分配给动态命名的变量。类似这样的东西(未测试)

 for($i; $i <= $_POST[].length; $i++){
  ${$_POST[i]} = $_POST[i]
  }

但我想知道这样的安全性。然后,这将为发送到页面的每一位发布数据在系统中创建一个变量。即使我编写的脚本没有引用它,该变量是否会造成破坏?这是我应该完全避免的事情吗?我有一些页面发送了很多变量,这样的脚本会阻止大量的写入,但它足够安全吗?

【问题讨论】:

  • 查看 extract()。它和你的 sn-p 做的事情是一样的。
  • 您正在尝试复制 PHP 的 register_globals 功能。不要这样做。这将非常不安全。

标签: php security post


【解决方案1】:

是的,存在可能安全风险。

假设您在前面的代码中定义了一个变量$is_admin,该变量赋予某人管理员权限。如果有人在该页面上发布了

$_POST['is_admin'] = true;

那么$is_admin 现在为真。不好。

使用$_POST有什么问题?

【讨论】:

    【解决方案2】:

    是的,可能存在安全问题/问题,例如,可能会覆盖已设置的任何局部变量,如数据库、配置值等。

    所以应该避免这样的事情:

    $yourImportantVar = 'Something relies on this';
    
    //User POSTS yourImportantVar=overwritten
    foreach ($_POST as $key => $value) {
        $$key = $value; 
    }
    echo $yourImportantVar; //overwritten 
    

    但是如果你想实现一个循环来保存一段代码,你可以创建一个允许的数组,你可以循环并从 $_POST 中提取值。

    foreach (array(
        'name',
        'address',
        'somethingelse',
        'ect'
    ) as $key) {
        $$key = isset($_POST[$key]) ? $_POST[$key] : null;
    }
    

    【讨论】:

    • 我认为这是个好主意,并且可以节省代码。尽管可能仍然存在一些安全问题,但一些经过深思熟虑的代码可以限制风险。
    【解决方案3】:

    这对于安全性和可维护性来说是一个非常糟糕的主意。简化示例为什么...

    <?php
    
    if (someRandomSessionCheck()) {
        $isAdminUser = true;
    }
    
    
    if ($isAdminUser) {
        // give access to everything
    }
    
    ?>
    

    某人可以使用变量“isAdminUser=1”在页面上发帖,并且可以访问所有内容。

    这是一个坏主意的另一个原因是您无法从脚本中清楚地看到创建变量的位置。这会降低脚本的可维护性。如果您现在想要运行脚本,但需要从其他地方而不是 POST 获取数据,该怎么办?

    【讨论】:

      【解决方案4】:

      目前我能想到的唯一问题是它会覆盖范围内的现有变量。这可能是非常不安全的,具体取决于您如何处理它。考虑变量是您正在向其发出 HTTP 请求的 URL。或者更糟的是,一些标志变量会访问代码的某些关键部分。

      我将发布一个关于 HTTP 请求的示例:

      <?php
          $url = "http://safe/url/to/POSTto";
          $var = array("url" => "http://www.mysite.com/url"); //assume this is $_POST
          foreach($var as $key => $value){
              ${$key} = $value;
          }
      
          //now upon the HttpRequest, your site can receive the (critical) data which was actually meant for the safe site.
      ?>
      

      编辑:@Galen 已经发布了我正在谈论的标志变量,所以我可能不需要发布任何示例来突出问题。

      【讨论】:

        【解决方案5】:

        PHP 有一个称为register_globals 的特性(使用术语松散)。它已被弃用(PHP 5.3)并被删除(PHP 5.4),但它反映了您正在寻找的功能。它执行的操作与 PHP 函数 extract() 执行的操作相同,后者使用匹配数组值的键名和值在当前范围内设置变量。 这绝对是一个安全风险。考虑对身份验证进行不良检查的示例:

        if($is_logged_in) {
            // Allow execution of destructive actions
        }
        

        如果启用此功能(或您模仿它),恶意用户将能够设置变量 $is_logged_in 并绕过登录屏幕。不用担心节省打字。如果您需要在文件开头复制并粘贴这样的代码块:

        $something = $_POST['something'];
        $another   = $_POST['another'];
        $stuff     = $_POST['stuff'];
        //etc.
        

        它不仅更安全,而且当开始使用未声明的变量时,它不会让开发人员(他们没想到register_globals)感到困惑。此外,PHP 已将其删除并且有 plentyarguments against its use 的事实应该是足够的证据。

        【讨论】:

          【解决方案6】:
           <?php
          
          /* Suppose that $var_array is an array returned from
            wddx_deserialize */
          
           $size = "large";
           $var_array = array("color" => "blue",
                         "size"  => "medium",
                         "shape" => "sphere");
           extract($var_array, EXTR_PREFIX_SAME, "wddx");
          
           echo "$color, $size, $shape, $wddx_size\n";
          
            ?>
          

          请检查这个。您将通过使用循环来做同样的事情。可以帮到你

          【讨论】:

            【解决方案7】:

            您基本上是在实现extract($_POST, EXTR_OVERWRITE),它将覆盖任何已经存在的变量。该手册已经警告您以您的方式使用extract

            不要在不受信任的数据上使用extract(),例如用户输入(即$_GET$_FILES 等)。如果您这样做,例如,如果您想临时运行依赖于 register_globals 的旧代码,请确保使用非覆盖 extract_type 值之一,例如 EXTR_SKIP请注意,您应该按照 php.ini 中 variables_order 中定义的相同顺序进行提取。

            这可能会导致覆盖基本和敏感变量,包括那些无法真正直接修改的变量,例如 $_SESSION$_SERVER$GLOBALS

            POST /foo.php HTTP/1.1
            Content-Type: application/x-www-urlencoded
            
            _SESSION[user]=admin
            

            这与$_SESSION = array('user'=&gt;'admin') 的效果相同。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-03-30
              • 1970-01-01
              • 2012-10-04
              • 1970-01-01
              相关资源
              最近更新 更多