攻防世界(CTF)~web-easyphp(江苏工匠杯)
题目介绍

题目(是一段php代码,让我们先来分析一下)
<?php
highlight_file(__FILE__);//高亮显示
$key1 = 0;//定义变量key1并赋值0
$key2 = 0;//定义变量key2并赋值0
$a = $_GET['a'];//变量a通过get传参
$b = $_GET['b'];//变量b通过get传参
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
//如果a不为空且a的整数值大于6000000且a的长度小于3则执行下面的语句
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
//如果b不为空 且 b的后六位数值的md5值为'8b184b'则执行下面的语句
$key1 = 1;
//得到key1 = 1;
}else{
//如果变量b不满足if的条件的话则执行else里面的语句
die("Emmm...再想想");
//输出Emmm
}
}else{
//如果变量a不满足if的条件的话则执行这个else里面的语句
die("Emmm...");
//输出Emmm
}
$c=(array)json_decode(@$_GET['c']);
//接收一个json编码的字符串c转换成php值并放到array数组中
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
//如果c是一个数组且不是数字和数字字符串且$c["m"]大于2022则执行下面的语句
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
//如果c["n"]是数组且c["n"]等于2且c["n"][0]是数组则执行下面的语句
$d = array_search("DGGJ", $c["n"]);
//在数组c["n"]中匹配DGGJ并赋值给d
$d === false?die("no..."):NULL;
//如果d为false则输出no
foreach($c["n"] as $key=>$val){
//对数组c["n"]进行检查
$val==="DGGJ"?die("no......"):NULL;
//如果数组c["n"]是DGGJ则输出no
}
$key2 = 1;
//得到key2
}else{
//如果没有满足上面的条件执行else里面的语句
die("no hack");
//输出no hack
}
}else{
//如果不满足c的条件则出书no
die("no");
}
if($key1 && $key2){
//如果key1和key2都拿到了则执行下面的语句
include "Hgfks.php";
//包含Hgfks.php文件
echo "You're right"."\n";
//输出You're right并换行
echo $flag;
//输出flag
}
?> Emmm...
这题条件设的比较多,我们一点一点来解,从代码的分析来看,如果同时满足了key1和key2那么就可以得到flag,我们要先看一下key1的if条件
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
//如果a不为空且a的整数值大于6000000且a的长度小于3则执行下面的语句
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
//如果b不为空 且 b的后六位数值的md5值为'8b184b'则执行下面的语句
$key1 = 1;
//得到key1 = 1;
$a的整数值要大于6000000,并且长度小于三,这个时候要用科学计数法来绕过a=1e9
1e9 = 110^9 =1000000000
a=1e9
$b的后六位数值的md5值为'8b184b'
$b的值只能用php脚本跑出来了(md5碰撞),b=53724
<?php
for ($i = 1; $i <= 100000; $i++) {
if ('8b184b' === substr(md5($i), -6, 6)) {
echo $i . "<br>" . md5($i);
}
}
输出了Emmm...再想想,说明我们成功拿到了key1,接下来再看看key2怎么拿
$c=(array)json_decode(@$_GET['c']);
//接收一个json编码的字符串c转换成php值并放到array数组中
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
//如果c是一个数组且不是数字和数字字符串且$c["m"]大于2022则执行下面的语句
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
//如果c["n"]是数组且c["n"]等于2且c["n"][0]是数组则执行下面的语句
$d = array_search("DGGJ", $c["n"]);
//在数组c["n"]中匹配DGGJ并赋值给d
$d === false?die("no..."):NULL;
//如果d为false则输出no
foreach($c["n"] as $key=>$val){
//对数组c["n"]进行检查
$val==="DGGJ"?die("no......"):NULL;
//如果数组c["n"]是DGGJ则输出no
}
$key2 = 1;
//得到key2
}else{
//如果没有满足上面的条件执行else里面的语句
die("no hack");
//输出no hack
}
}else{
//如果不满足c的条件则出书no
die("no");
}
作为一个小白的我看着就头疼,但是还要继续搬砖,不能着急,一步一步解析
首先传入的c要是一个JSON格式的字符串,然后解析成数组,不能是数字而且还要大于2022,当字符串与数字相比时会把字符串强制转化为整型即"2024a"会转成2024
重点代码
$c=(array)json_decode(@$_GET['c']);
//接收一个json编码的字符串c转换成php值并放到array数组中
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
//如果c是一个数组且不是数字和数字字符串且$c["m"]大于2022则执行下面的语句
构造pyload
{"m":2024a}
c["n"]是一个数组,长度为2,n的第一个元素也是数组
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
//如果c["n"]是数组且c["n"]等于2且c["n"][0]是数组则执行下面的语句
继续构造pyload
{"m":"2024a","n":[["xxx"]:xxx]}
这里可以看到代码意思是先要求在数组c["n"]中匹配到DGGJ,否则就输出no,然后又要对其进行第二次匹配如果有DGGJ则输出no,不得不吐槽一句(左右为难),这一段代码的重点就在array_search这个函数,该函数进行匹配时如果是字符串与数字,先会把字符串转化为整型再加以比较,而"DGGJ"转化为整型即为0,这样就很好理解了。
$d = array_search("DGGJ", $c["n"]);
//在数组c["n"]中匹配DGGJ并赋值给d
$d === false?die("no..."):NULL;
//如果d为false则输出no
foreach($c["n"] as $key=>$val){
//对数组c["n"]进行检查
$val==="DGGJ"?die("no......"):NULL;
//如果数组c["n"]是DGGJ则输出no
}
$key2 = 1;
//得到key2
构造pyload
{"m":"2024a","n":[[]:0]}
最终pyload
?a=1e9&b=53724&c={"m":"2024a","n":[[],0]}
flag:cyberpeace{a75b45ee38b72326f9e6b2c56ecf6eab}


浙公网安备 33010602011771号