代码是这样的(加了注释的)
1 | |
2 | $flag = "66666"; |
3 | if(isset($_GET['time'])){ // 如果get请求中存在time参数 |
4 | if(!is_numeric($_GET['time'])){ // 如果非数字 |
5 | echo 'The time must be number.'; |
6 | }else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){ // 如果time小于xx |
7 | echo 'This time is too short.'; |
8 | }else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){ // 如果time大于xx |
9 | echo 'This time is too long.'; |
10 | }else{ // 否则 |
11 | sleep((int)$_GET['time']); // 睡眠time秒 |
12 | echo $flag; // 睡眠结束后输出flag |
13 | } |
14 | } |
在注释中很详细的讲解了
如果想要输出$flag就必须绕过这3个if条件判断才能到else 然后才会输出$flag,那么我们来看看如何才能不达到这几个if条件语句
第一个if条件
1 | if(!is_numeric($_GET['time'])) |
如果$_GET['time']的值不是数字,则会触发这个if条件
第二个if条件
1 | else if($_GET['time'] < 60 * 60 * 24 * 30 * 2) |
如果$_GET['time']的值小于60 * 60 * 24 * 30 * 2,则触发这个if条件,那么我们来看看这个数值有多大

1 | 5184000 |
然后再来看看第三个if条件
1 | else if($_GET['time'] > 60 * 60 * 24 * 30 * 3 |
如果$_GET['time']的值大于60 * 60 * 24 * 30 * 3,则触发这个if条件,那么来看看这个有多大

1 | 7776000 |
那么要逃逸这2个if条件很简单,只要$_GET['time']大于5184000并且小于7776000就可以获取到flag,但是我们看一下else里面的代码
1 | sleep((int)$_GET['time']); // 睡眠time秒 |
2 | echo $flag; // 睡眠结束后输出flag |
那么我们如果把time的值填的符合上面那么大的值,估计我孩子都生出来了。。。,那么该肿么办呢,之前看过一篇文章有讲过,测试代码如下
1 | |
2 | |
3 | $num = $_GET['num']; // 接收get请求中的num参数 |
4 | if ($num > 9999){ // 如果num大于9999 |
5 | echo '$temp > 9999'; // 输出 $temp > 9999 |
6 | } |
7 | echo "<br>"; |
8 | var_dump( (int)$num ); // 打印转换$num的值 |
那么我们来访问以下?num=0x2710

what?为啥会显示大于9999最后又输出结果是0呢?下面来看下讲解
这里的0x2710是10000转换为十六进制后的值

然后我们再来看个小案例
1 | var_dump( (int)('0only_free') ); |

可以看到0only_free在int转换后变成了0 可以理解为int就是取一个有数字、字母的字符串的前面数字。
那么我们可以利用这个办法去绕过上面的2个if判断,直接访问一下
1 | http://you_url.xxx/xxx.php?time=0x4f1a01 |

ok,成功绕过并且输出了flag