导言:
本文主要讲述在CTF竞赛中,web类题目easyphp。
靶场链接:攻防世界 (xctf.org.cn)
参考文章原文链接:Web安全攻防世界05 easyphp(江苏工匠杯)_攻防世界 easyphp-CSDN博客
一,观察页面。
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;// 获取GET参数a和b
$a = $_GET['a'];
$b = $_GET['b'];// 判断a是否设置,并且a的值是否大于6000000,长度是否小于等于3
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){// 判断b是否设置,并且b的md5值的后6位是否等于8b184bif(isset($b) && '8b184b' === substr(md5($b),-6,6)){$key1 = 1;}else{die("Emmm...再想想");}}else{die("Emmm...");
}// 获取GET参数c,并转换为数组
$c=(array)json_decode(@$_GET['c']);
// 判断c是否为数组,并且c的m值是否不是数字,并且m值大于2022
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){// 判断c的n值是否为数组,并且n的长度是否为2,并且n的第一个值是否为数组if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){// 在n数组中查找DGGJ,如果找不到则输出no...$d = array_search("DGGJ", $c["n"]);$d === false?die("no..."):NULL;// 遍历n数组,如果数组中存在DGGJ则输出no......foreach($c["n"] as $key=>$val){$val==="DGGJ"?die("no......"):NULL;}$key2 = 1;}else{die("no hack");}
}else{die("no");
}// 如果key1和key2都为1,则包含Hgfks.php文件,并输出You're right和flag
if($key1 && $key2){include "Hgfks.php";echo "You're right"."\n";echo $flag;
}
可以看到,这是一道php代码审计类题目,单纯地在考验php语法,并且每个变量输错了都有不同的提示。
二,解题思路。
根据php代码可知:
1,需要使用get方式传递两个参数,分别为a,b。
2,a的值大于6000000,长度小于等于3。
3,b的md5值的后6位等于8b184b。
4,需要使用get方式传递c数组,并且里面有m和n两个数值。
5,数组c为数组并且c中的m值不是数字或者字符串,并且值大于2022。
6,数组c中,n必须含有DGGJ,但n不能是DGGJ本身。
7, 数组c除了上述要求外,还需要是JSON 编码。
三,开始测试。
1,a。
a的值大于6000000,长度小于等于3。看似不可能,实际上可以使用科学计数法。例如:2e9,等于2000000000。 E表示的是10的次方,E后面的数字表示的是10的几次方,所以2E9等于2*10^9,也就是20亿。
进行测试:
成功。
2,b。
b的md5值的后6位等于8b184b,这里使用一个php文件进行计算:
<?php
for($b=1;$b<=100000;$b++){ if(preg_match('/^8b184b/',substr(md5($b),-6,6))){ echo $b; echo "\n";}
}
?>
计算结果:
得到b的值为:53724。
一般情况下python脚本使用较多,下面是一个python解法:
import hashlibdef find_number(start, end, target_hash):for num in range(start, end + 1):md5_hash = hashlib.md5(str(num).encode()).hexdigest()if md5_hash[-6:] == target_hash: return numprint("未找到匹配的数字")return Nonetarget_hash = '8b184b'
start, end = 0, 10**5
result = find_number(start, end, target_hash)
if result is not None:print(f" {result}")
测试:
通过。
3,c。
根据源码可知,c是含有m和n两个数值。
m的值应为“>2022的数字+字符”,这里使用"3000% ”
至于n,我们直接将其定义为空数值。
因为m和n是c的值,所以应写为:c={"m":"3000 ","n":[[0],0]}
四,构造payload,得到flag。
payload:
http://61.147.171.105:52428/?a=2e9&&b=53724&&c={"m":"3000 ","n":[[0],0]}