2

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

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

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

4

7 回答 7

4

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

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

$_POST['is_admin'] = true;

那么$is_admin现在是真的。不好。

使用有什么问题$_POST

于 2012-07-19T05:44:07.603 回答
2

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

<?php

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


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

?>

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

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

于 2012-07-19T05:44:35.867 回答
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;
}
于 2012-07-19T05:50:35.290 回答
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 已经发布了我正在谈论的标志变量,所以我可能不需要发布任何示例来突出问题。

于 2012-07-19T05:46:14.900 回答
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 已将其删除并且有很多反对使用论据 这一事实应该是足够的证据。

于 2012-07-19T05:53:29.653 回答
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";

  ?>

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

于 2012-07-19T05:43:11.697 回答
0

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

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

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

POST /foo.php HTTP/1.1
Content-Type: application/x-www-urlencoded

_SESSION[user]=admin

这将具有与 相同的效果$_SESSION = array('user'=>'admin')

于 2012-07-19T07:09:18.610 回答