1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
show_source(__FILE__);
$flag = "xxxx";
if(isset($_GET['time'])){
if(!is_numeric($_GET['time'])){
echo 'The time must be number.';
}else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){
echo 'This time is too short.';
}else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){
echo 'This time is too long.';
}else{
sleep((int)$_GET['time']);
echo $flag;
}
echo '<hr>';
}

分析该题,传入一个get类型的变量time,然后判断time的大小,如果time的大小位于区间[5184000,7776000]的话就可以得到flag。
但是这时就出现一个问题了:

1
2
3
4
 }else{ 
sleep((int)$_GET['time']);
echo $flag;
}

在得到flag之前,会将time转换为int型,并作为sleep函数的参数,也就是会停顿我们输入的time那么多秒
那么我们要得到flag,岂不是要等待这么久吗,这样等下去,ctf比赛早就结束了。
所以我们想要得到flag,就的想办法绕过

1
sleep((int)$_GET['time']);

那么该怎么绕过呢,这时我们就要从它将time强制转换为int型这里来做手脚了

1.首先,我们要知道,在php中,通过get和post传过来的参数的值都是字符串型的
2.php中,数与数之间可以用不同的进制来进行比较

我们可以做下demo来验证下:
我们知道这里的time要大于5184000且小于7776000。
那么我们就选择一个5184001来做实验吧
先将5184001转换为16进制

然后再来和5184000和7776000进行比较:

1
2
3
4
<?php
echo (5184000 < 0x4f1a01);
echo "<br><br>";
echo (7776000 > 0x4f1a01);

运行结果:

从返回结果来看,十六进制和十进制这些时可以直接比较的。

十进制的数字字符串可以直接强制转换为int型而不会出现错误什么的,那么如果是十六进制的来进行int型的强制转换呢?

1
2
3
4
5
6
7
8
<?php
$time = "5184001";
echo (int)$time;

echo "<br><br>";

$time_hex = "0x4f1a01";
echo (int)$time_hex;

返回结果:

我们可以看到,十进制正常转换,而十六进制在强制转换的时候,当识别到第一个0后后面的就无法识别的,最终转换的结果为0。
那么我们的解题思路就出来了:
利用十六进制可以与十进制进行比较,而在进行int强制转换时的结果为0就可以绕过sleep拿到flag了

最后更新: 2018年03月16日 00:44

原始链接: http://drac0nids.top/2018/03/14/challenge2/

× 请我吃糖~
打赏二维码