PHP GET变量数组注入

15

我最近了解到可以将数组注入到PHP GET变量中以执行代码?

.php?a[]=asd&a[]=asdasd&b[]=$a

这是我收到的示例。我不知道它如何工作,想知道这是否可能?


3
欢迎来到StackOverflow,三星。让我成为第一个奖励你12个声望分数的人;) - Sampson
9个回答

9

PHP会解析查询字符串,并将这些值注入$_GET超全局数组中(如果是使用POST在表单中完成的,则对于$_POST也是如此)。

在您的情况下,$_GET数组将包含以下内容:

array
  'a' => 
    array
      0 => string 'asd' (length=3)
      1 => string 'asdasd' (length=6)
  'b' => 
    array
      0 => string '$a' (length=2)

每个在查询字符串中传递的值都将由PHP放置在$_GET数组中,如果查询字符串中使用了[],则会创建子数组。

但是这不会导致任何形式的“代码执行”:只要您正确处理输入(即不信任输入并对其使用eval或任何类似于此的坏主意),就没有代码注入的风险。


感谢您为提问者Pascal提供了详尽的回答,这为这里创造了更好的环境。 - Sampson
@Jonathan:谢谢:-);只是想帮忙;希望有所帮助^^;我想这是我的一种"回报"方式 - Pascal MARTIN

7

如果您不确定如何保护安全,最起码可以过滤$_GET数组。以下是函数:

function filter_url($url)
{
  if (is_array($url))
  {
    foreach ($url as $key => $value)
    {
      // recurssion
      $url[$key] = filter_url($value);
    }
    return $url;
  }
  else
  {
    // remove everything except for a-zA-Z0-9_.-&=
    $url = preg_replace('/[^a-zA-Z0-9_\.\-&=]/', '', $url);
    return $url;
  }
}

现在您可以像这样过滤$_GET变量:
$_GET = filter_url($_GET);

这将从 $_GET 数组中清除可疑字符,例如 [ ],以达到基本的清理作用。
谢谢。

它非常完美地解决了我的问题...谢谢。 如果你想知道,我在我的网站上使用“mysqli_real_escape”来阻止注入攻击,但同时也阻止了网站的功能...但现在,函数可以正常工作并且注入攻击被阻止了。谢谢。 - Genesis
4
好的,简单的解决方案。正则表达式中有错误,a-Z 应该改为 a-z ,否则 PHP 会报错 :) - Spaceship09
@Spaceship09 很好的发现,但你能告诉我如何添加空格吗? - beic

2
echo $_GET['a'][0]; //prints "asd"
echo $_GET['a'][1]; //prints "asdasd"
echo $_GET['b'][0]; //prints "$a"

2

以上并不严格允许代码执行,但如果现有代码没有考虑到数据可能是数组,则可能会改变其控制流程。

上述方法之所以可行,是因为PHP将以[]结尾的变量解释为数组。因此,如果您提供多个相同名称以[]结尾的GET变量,PHP将创建包含所有值的数组。


2
长话短说:没有代码执行。否则,难道不认为有人已经黑进了Facebook? :)
我认为告诉你这个的人对于一些其他的bug感到困惑,这些bug使用深层的数组嵌套来触发缓冲区溢出/双重释放/某些其他的黑客向量,理论上可以用来执行一些代码。这些都是软件漏洞,正如你每天在许多流行的软件中看到的那样。它们通常很快就会被修补。
您可以在 http://www.suspekt.org/ 找到更多信息。

2

我认为他在谈论当传入一个数组时,某些内容会被不同地评估。

strcasecmp( $_GET['password'], $password ) == 0 ) { echo($secret); } 如果你将一个空数组传入strcasecmp函数中,由于某种原因,它将被评估为true。

例如:index.php?password=[]


+1 这里也有文档记录:https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet#Input_handling - Bill Karwin

1

看起来你误解了一些东西。

上面的例子只是简单地创建了一个数组,如下所示:

Array (
  [a] => Array (
    [0] => asd
    [1] => asdasd
  )
  [b] => Array ( [0] => $a )
)

这是有文档记录的,而且完全按照预期工作。


0

有人骗了你,你不会用那个执行任何东西,你只会发送一个数组而不是一个普通变量。

试试这段代码

<?php
    $x = $_GET['x'];
    var_dump($x);
?>

通过使用 ?x=1 并且 ?x[a]=1&x[b]=2 访问它,这是预期的行为,而不是注入,您无法使用它运行任何代码。


0

你的网址应该是这样的

www.mysite.com/page.php?name=john

但是你想要防止插入类似这样的内容

www.mysite.com/page.php?name[]=john

解决方案:
<?php
 $myname = is_array($_GET['name'])? "invalid" : $_GET['name'] ;
 echo $myname;
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接