数组注入是一个漏洞吗?它的正确术语是什么?

信息安全 Web应用程序 php 渗透测试 脆弱性 术语
2021-09-03 04:30:13

当我进行渗透测试时,当我使用 HTTP GET 参数注入单维或多维数组时,有时会注意到 PHP 脚本的不良行为。

可能的可用性风险

这可能会导致可用性风险,特别是在 PHP 脚本递归循环通过(深)多维数组并且执行时间没有限制或有很高限制时的多维数组注入的情况下。因为这会导致资源耗尽。实际上,当整个$_GET数组循环通过以应用某种过滤或验证时,可能就是这种情况


有关此行为的问题

  1. 这种脆弱性的恰当术语是什么?“阵列注入”?
  2. 这属于哪个漏洞类别(例如在 OWASP 前 10 名或 CWE 列表中)?
  3. 除了可用性风险之外,这是否被视为漏洞?
  4. 什么是可以利用它的好场景?

行为示例

输入:(期望字符串作为参数)

/search.php?query=test

结果:(在 PHP 中$_GET

[query] => test

输入:(注入数组)

/search.php?query[]=test

结果:(在 PHP 中$_GET

[query] => Array
(
    [0] => test
)

输入:(注入的多维数组)

/search.php?query[][][][]=test

结果:(在 PHP 中$_GET

[query] => Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => Array
                        (
                            [0] => test
                        )
                )
        )
)
4个回答

我认为HTTP 参数污染这个词是最合适的。这种污染通常在同一个请求中多次提交相同的参数,但值不同。这会导致参数被视为一个值数组,其中参数名称作为数组名称,如本文所述与单个值相比,Web 服务器和编程语言处理这些数组的方式是这个 bug 类所利用的。

fault injection您的示例同样会导致具有相同名称的数组,尽管通过不同的方法来重复参数,但与其他术语(如or )相比,它似乎更合适type confusion

虽然这种类型的污染通常会利用未定义的行为,但您提供的示例不会。它们会导致处理数组的定义行为。这可能仍会触发可用于更改应用程序流程的异常,例如在授权检查更改会话之前出错,从而导致权限提升。

这种脆弱性的恰当术语是什么?“阵列注入”?

这属于哪个漏洞类别(例如在 OWASP Top > 10 或 CWE 列表中)?

这被称为“参数篡改”,PHP 开发人员、OWASP 都这么称呼它,并且属于不同的 CWE 编号,其父级为CWE-371,例如,当参数涉及注入 SQL 语句时,它就变成了 SQL 注入。您所做的只是操纵(篡改)输入以产生不利影响。

除了可用性风险之外,这是否被视为漏洞?

漏洞可能是服务器无法清理输入

什么是可以利用它的好场景?

这取决于应用程序本身。您将不得不继续操纵输入,以了解在不同情况下可能/将会发生什么。例如,您是否尝试过插入嵌套在篡改中的命令?例如:

/search.php?query[() { example;};echo \"Content-type: text/plain\"; echo; echo; /bin/cat /etc/shadow"]=test

如果不了解底层应用程序,就很难确定什么是易受攻击的。输入未经验证的事实,您应该能够测试要注入的各种东西,以尝试让服务器响应您的篡改数据。您可以插入大量数据以查看是否可以触发堆栈/缓冲区/堆溢出。您可以尝试一些事情,但再次尝试,在不知道初始应用程序的功能的情况下,这变成了一个猜谜游戏

能够以$_GET这种方式使用数组本身并不是一个安全漏洞。DoS 向量对我来说似乎可以忽略不计,尽管这可能确实被使用它的代码放大了。

但是,您提供的示例忽略了此功能最重要的部分(从攻击者的角度来看):不仅可以通过这种方式传递常规数组GETPOST参数,还可以传递关联数组事实上,PHP 并没有区分这两者:

PHP 数组可以同时包含整数和字符串键,因为 PHP 不区分索引数组和关联数组。- PHP:数组 - 手册

这意味着如果客户端提供POST如下参数:

<input type="text" name="pass[pass1]" value="Password 1">
<input type="text" name="pass[pass2]" value="Password 2">

$_POST/$_GET看起来像这样:

$_POST = array(
    ...
    'pass' => array(
        'pass1' => 'Password 1',
        'pass2' => 'Password 2', 
    ),
    ...
);

但是如果服务器期望它是一个普通数组而不是一个关联数组,它可能会导致一个安全漏洞:

//Simplified example, bug is possible with parameterized queries as well
//Expects ?pass[]=password1&pass[]=password2
$query = 'INSERT INTO users (index, password) ';
$parts = array();

foreach($_GET['user'] AS $index=>$value){
  parts[]=" VALUES ({$index}, ".$pdo->real_escape_string($value).')';
}

$query .= implode(", ", $parts);
$pdo->exec($query);//

$query 有预期的输入:

INSERT INTO USERS (index, password) VALUES(0, 'password1'), VALUES(1, 'password2')

$query?pass[0,'');DROP DATABASE DATABASE();--]=foo

INSERT INTO USERS (index, password) VALUES(0,'');DROP DATABASE DATABASE();--, 'foo')

繁荣。

事实上,这与导致名为“Drupalgeddon”的安全漏洞的错误完全相同——它获得该名称是有充分理由的。

此 API 中的漏洞允许攻击者发送特制请求,从而导致任意 SQL 执行。根据请求的内容,这可能导致权限提升、任意 PHP 执行或其他攻击。- SA-CORE-2014-005 - Drupal 核心 - SQL 注入

在宣布 SA-CORE-2014-005 - Drupal 核心 - SQL 注入后的几个小时内,自动攻击开始破坏未修补或更新到 Drupal 7.32 的 Drupal 7 网站。您应该假设每个 Drupal 7 网站都已被入侵,除非在 UTC 时间 10 月 15 日晚上 11 点之前(即公告后 7 小时)更新或修补。Drupal 核心 - 高度关键 - 公共服务公告 - PSA-2014-003

这也是最有可能导致巴拿马文件泄露的漏洞(可能应该安装了那些安全更新......)。

Drupal 漏洞已通过更新代码以将接收到的数组传递给 来修复array_values(),它返回一个索引数组,其中仅包含它接收到的数组的,从而摆脱了任何恶意密钥。

示例代码可以以相同的方式修复:

前:

foreach($_GET['user'] AS $index=>$value){

后:

foreach(array_values($_GET['user']) AS $index=>$value){

有关 Drupalgeddon 的更多信息,包括一个有效的漏洞利用:Drupal 7: Drupalgeddon Exploit

请注意,无论您使用的是$_GET还是,这些东西的工作方式都是一样的$_POST我不确定$_REQUEST$_COOKIE

存在其他可能的攻击,例如 with MongoDB

如果您将 $_GET(或 $_POST)参数传递给查询,请确保首先将它们转换为字符串。用户可以在 GET 和 POST 请求中插入关联数组,这可能会变成不需要的 $-查询。

一个相当无害的示例:假设您正在使用请求http://www.example.com?username=bob查找用户的信息您的应用程序执行查询 $collection->find(array("username" => $_GET['username']))。

有人可以通过获取 http://www.example.com?username[ $ne]=foo 来颠覆这一点,PHP 会神奇地变成一个关联数组,将您的查询变成 $collection->find(array("username" = > array('$ne' => "foo"))),它将返回所有未命名为“foo”的用户(可能是所有用户)。

http://php.net/manual/en/mongo.security.php