代码是这样的(加了注释的)
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