前言
主要考察的是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>';
}
首先我们定位到关键变量 $flag
的最终输出位置,然后紧跟变量进行逆向的分析,确认代码逻辑及关键 if
语句条件。
接收外部传递的 $_GET['time']
,经过三次 if
判断才会到达输出 $flag
的代码段,但在输出 $flag
之前存在一个 sleep()
函数。
$_GET['time']
必须是数字$_GET['time']
必须大于 5184000$_GET['time']
必须小于 7776000$_GET['time']
会被转换成 int 类型,并休眠响应秒后,才会打印$flag
这里的关键点有两个:
is_numeric
函数用于检查参数是否是数字(为真的类型有:浮点型、十进制、十六进制、科学计数)(int)
强制转换成 int 类型。这个就比较特殊了,当然类型为字符串时,比如89ee
最终会变成89
,后面的字符串部分则会被丢弃。
所以,这里我们直接提交一个十六进制数绕过 is_numeric
函数,又因为 php 接收 _GET、_POST
等参数默认都是字符串类型,从而又绕过了 (int)
强制类型转换。
最终提交:?time=0x518400
成功拿到 $flag