攻防世界easyphp解题
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
$a = $_GET['a'];
$b = $_GET['b'];
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}
$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}
if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}
?>
请求参数a要求是整型并且大于6000000但是要求位数小于等于3位。 解: 科学计数法 1e9 虽然只有三位但是表示1后面有9个0
请求参数b 解: 直接写一个脚本爆破,从0开始一个一个加看看哪个满足规则即可:
<?php
$b = 0;
for ($b=0;$b<999999999;$b++){
if ('8b184b' === substr(md5($b),-6,6)){
echo "$b";
break;
}
}
?>
请求参数c 服务端接收到以后会进行json解码再转成数组类型。那么我们只需要保证我们传过去的值是json编码格式就好了。
然后就是两层if判断:
第一层是判断变量c是否是一个数组,是否c中的m键的值不是一个数字,是否m键的值大于2022。是否是数组在接收参数的时候就已经被服务端自行强转了不用管,是否不是一个数字还要求大于2022那么就传入m的值等于“2023a”这种值。
因为在PHP中,当一个字符串和一个数字进行比较时,PHP会尝试将这个字符串转换为一个数字。如下图这个例子中,字符串"2023a"会被转换为数字2023,因为在遇到非数字字符"a"时,转换就会停止。
因此,其实这个if真正在比较的是比较2023>2022的结果,所以会输出"yes"。
第二层if判断变量c的n键的值是否是一个数组,并且n键的值元素要有两个,并且n键的值的第一个元素要是一个数组。那就二维数组嘛。
进入第二层if之后,会在变量c的n键中的值搜素是否有DGGJ这个字符串,有的话返回true给变量d,没有的话返回false给变量d,然后判断变量d的值是否全等于false,如果为真就die函数结束掉程序,如果条件为假就返回NULL给变量d。
然后代码再遍历n键的值。如果任何元素的值等于"DGGJ",它将输出"no…"并终止程序。所以我们既要让变量d的判断结果为真,还不能在值中有"DGGJ"这个字符。
在PHP中,当一个字符串和一个数字进行比较时,PHP会尝试将这个字符串转换为一个数字。如果字符串不包含任何数字,那么它将被转换为0。
那么我们就让payload等于c={"m":"12345a","n":[[1,9,1],0]}
n键的第一个值随便写写都可以保证类型是数组就好,第二个值写做0就绕过了第一个die函数,在foreach遍历n键的值的时候也找不到"DGGJ"这个字符串。变量key2也就等于了1。flag也就拿到了
最后的payload是:?a=1e9&b=53724&c={"m":"2023a","n":[[1,9,1],0]}