Challenge2题目代码

<?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要大于60*60*24**30*2
并且小于60 * 60 * 24 * 30 * 3

5184000<time<7776000

然后sleep函数进行延时。显然,第一个条件是我们自己传入的,问题就出在,sleep延时时间太久,我们不可能等他那么久。只需要绕过sleep就可以得到flag

绕过sleep

is_numeric()支持普通数字型字符串、科学记数法型字符串、部分支持十六进制0x型字符串。而强制类型转换int,不能正确转换的类型有十六进制型字符串、科学计数法型字符串(部分)。

也就是说,当传入?time=7e6,由于int无法转科学计数法,会把它当做7处理,这样首先7e6满足 5184000<time<7776000 ,然后进入sleep延迟,在int不能转换科学计数法的条件下,延迟七秒得到flag。

考点

考察php弱类型与函数is_numeric的特性。
从逻辑上看,本题接收time参数,先使用is_numeric判断time是否为数字,再要求7776000>time>5184000,若这些都满足则sleep((int)time)。可以看到如果满足time大小要求的话则无法等待如此长的sleep时间。
我们知道is_numeric() 函数可以支持识别科学计数法与十六进制,而int不支持。那么根据php弱类型,如果是一个科学计数法形式2e10 在强制int转换后,就变成了2(当成字符串识别,截取第一个字母前的数字)。那么我们就可以构造一个处于规定大小之间的科学计数法就行了,如下
?time=7e6