导言:
本文主要讲述在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位是否等于8b184b
if(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 hashlib
def 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 num
print("未找到匹配的数字")
return None
target_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]}