为什么会这样?
这是因为 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 位系统。所以这是你泄露的唯一信息。