科学数字的不良转换是一个漏洞吗?

信息安全 Web应用程序 php 渗透测试 脆弱性 打字杂耍
2021-08-24 03:22:35

我注意到在几个渗透测试中 PHP 正在转换值1e91000000000而这个数字的最大接受字符串长度是 3(在数据库存储中和作为maxlengthHTML 表单上的属性)。

然而,当输入1e9(3) 时,PHP 将返回1000000000(10) 作为其输出。这个数字比应用程序预期的要高,并且可以正确处理。因此,我会考虑更好地验证用户输入以防止这种情况发生。

首先,我认为这种行为并不危险,只是不可取,这样假设是否合法?其次,我可以认为这是一个实际的(低严重性)漏洞吗?

此外,输入9e9将产生最大 32 位值2147483647(10) 而不是9000000000(10)。仅此一项(32 位系统或配置)是否被视为系统信息泄漏或危险?

2个回答

为什么会这样?

这是因为 PHP 的类型很松散看看这个例子:

$x = "1e6";
echo strlen($x); // 3
echo $x * 1;     // 1 000 000

在第二行,$x假定是一个字符串,因此显然是三个字符长。在第三行,$x被解释为整数,在这种情况下为 1 000 000。

这是个问题吗?

这肯定会导致错误,每个错误都是潜在的安全漏洞。但就其本身而言,默认情况下它不会使您的应用程序易受攻击。但是让我们试着想象一个会导致问题的场景。

假设一个论坛有用户可以自由加入的编号组,但前 10 个组(0 到 9)是为管理员保留的。的代码joingroup.php如下所示:

$group = $_POST['group'];
if(strlen($group) > 1 || $isadmin) {
    join_group($group, $uid);
}
else {
    // Fail.
}

0.3e1您可以通过发布例如字符串长度为 5 但计算结果为 3 的字符串潜入管理员组,而不是真正成为管理员。我知道,这是一个愚蠢的例子。我要说明的一点是,如果您依赖strlen()(或将输入视为字符串的任何其他方法)来验证数字数据,您可能很容易受到攻击。

只是发布3.0 3也会绕过此检查。有关 PHP 如何将字符串隐式转换为数字的更多信息,请查看手册

我应该如何在 PHP 中处理这个问题?

验证用户输入。当你期望得到一个整数时,检查你是否真的得到了一个整数:

if(!ctype_digit($group)) {
    // Fail.
}

始终将应该是整数的东西视为整数而不是字符串也是一个好主意:

$group = (int) $_POST['group']
if($group > 9 || $isadmin) {
    // ...

这是泄漏系统信息吗?

显然这可以揭示最大整数值。也许有人可以从中推断出您正在使用 PHP,但可能已经有许多其他方法可以做到这一点。最大值取决于平台,因此可用于指纹识别。但实际上 32 位可能用于 32 位系统,而 64 位则用于 64 位系统。所以这是你泄露的唯一信息。

严格来讲?不,它本身并不是一个漏洞。但这确实表明可能存在需要进一步调查的问题。

这是渗透测试的固有问题之一。您会发现这样的模棱两可的东西,并且不知道它是否可以利用。甚至要开始找出这是否是一个漏洞,您需要了解输入限制的作用。

例如,如果该程序旨在将银行转账限制在 1000 美元以下,并且输入字段是金额,并且在任何地方都没有进一步的检查,那么您就发现了一个巨大的漏洞。

另一方面,如果该字段只是电话号码的前 3 位数字,它会创建一个电话号码数据库,供家长输入学校的联系电话,并且验证只是确保用户只输入前 3 位数字,您可能只发现了一个极端情况,一个非常书呆子的父母可以搞砸他/她自己的电话号码在数据库中的条目。