【Code-Audit-Challenges】Challenge 2:php弱类型、is_numeric()、强制类型转换

0x01 题目

<?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>'; 
}
?>

0x02 解题

首先分析代码,这里GET得到time参数,进行is_numeric()判断,如果是数字,则进行大小判断,要求time参数在5184000(包括)~7776000(包括)之间,如果成立,则等待time秒,最后得到flag。

首先,这题肯定不是老老实实的输入符合条件的time数值,因为就算输对了这个等待时间也忒长了。。。那么注意到这里有个比较关键的函数是is_numeric()和后面的int强制类型转换了。
is_numeric()函数查阅php手册知道它接受一个数字或者数字型字符串,而从GET获取的参数是字符串,那么后面的强制类型转换就是字符串转换为int类型的数字。
查阅资料得到:is_numeric()支持普通数字型字符串、科学记数法型字符串、部分支持十六进制0x型字符串。而强制类型转换int,不能正确转换的类型有十六进制型字符串、科学计数法型字符串(部分)。
因此可以输入十六进制和科学计数法来进行绕过。本地测试一下:

<?php 
show_source(__FILE__); 

if(is_numeric($_GET['time'])){ 
    $hhh = (int)$_GET['time']; 
    echo $hhh; 
}else{ 
    echo "input a number"; 
} 

?>

经测试发现当我们输入十六进制和0e开头的科学计数法的时候都输出了0,所以应该是当字符串转换到int类型的时候,会从第一个非数字的地方进行截取,只用数字部分,所以答案就是

?time=0x4f1a00
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容