php $ POST动态变量命名安全问题

时间:2012-07-19 05:26:14

标签: php security post

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

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

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

7 个答案:

答案 0 :(得分:4)

是的可能存在安全风险。

假设您在代码中前面定义了一个变量$is_admin,可以为某人提供管理员能力。如果有人通过

发送到该页面
$_POST['is_admin'] = true;

然后$is_admin现在是真的。不好。

使用$_POST有什么问题?

答案 1 :(得分:2)

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

<?php

if (someRandomSessionCheck()) {
    $isAdminUser = true;
}


if ($isAdminUser) {
    // give access to everything
}

?>

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

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

,该怎么办?

答案 2 :(得分: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 :(得分:1)

目前我只能想到的问题是覆盖范围内的现有变量。这可能非常不安全,具体取决于您使用它做什么。考虑变量是您正在执行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发布了我正在谈论的标志变量,所以可能我不需要发布任何示例来强调问题。

答案 4 :(得分:1)

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删除了plenty arguments against its use的事实应该足够证据。

答案 5 :(得分:0)

 <?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";

  ?>

请检查一下。使用循环你要做的事情是一样的。可以帮到你

答案 6 :(得分:0)

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

  

请勿对不受信任的数据使用extract(),例如用户输入(例如$_GET$_FILES等)。如果您这样做,例如,如果您想要运行暂时依赖于 register_globals 的旧代码,请确保使用其中一个非覆盖 extract_type 值,例如{{1并且请注意,您应该以与php.ini中 variables_order 中定义的顺序相同的顺序提取。

这可能导致覆盖必要和敏感变量,包括那些无法真正直接修改的变量,如EXTR_SKIP$_SESSION$_SERVER

$GLOBALS

这与POST /foo.php HTTP/1.1 Content-Type: application/x-www-urlencoded _SESSION[user]=admin 具有相同的效果。