首次尝试PHP代码审计,不够完善,敬请指教。
原题如下:
<?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>';
}
?>
解题:
1、相关知识:PHP弱类型、is_numeric()函数等。
2、分析:题中先使用is_numeric()判断time是数字还是数字字符串,然后判断是否在60*60*24*30*2~60*60*24*30*3之间,最后对time参数有一个sleep()延时函数,函数用了一个int类型的强制类型转换。要绕过的是时间大小的限制,因此通过计算得到限制的时间范围最小是5184000秒,转换成16进制就是0x4F1A00,于是传参time=0x4F1A00,通过了四次判断,GET获取值类型为字符串,最后sleep函数中进行类型转换的时候0x4F1A00,遇到字母就停止转换,变成了0,于是不能继续sleep,最后输出结果。
3、问题:is_numeric()中强制类型转换成int,不能正确转换的类型有十六进制型和部分科学计数法型字符串。
4、测试:
<?php
show_source(__FILE__);
$temp = $_POST['temp'];
echo (int)$temp;
?>
当传入参数为 0x6F1A00之类的十六进制型字符串和0e10之类的科学计数法型字符串时,会输出0;当传入参数6e10之类的科学计数法型字符串时,会输出6。
5、Payload:
(1)?time=0x6F1A00--十六进制
(2)?time=0e10--科学计数法
(3)?time=6e10--科学计数法