打开网站,即可看到网页的php代码,一眼就看出本题为php代码审计的题目
现在逐段来进行分析,可以看到只有当key1和key2都为1时,才会输出flag,于是本题就是要
highlight_file(__FILE__); $key1 = 0; $key2 = 0;//key1和key2的初始值都设为0 $a = $_GET['a']; $b = $_GET['b'];//a和b都通过get方式来传参 if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){ //a的判断:判断是否设置了参数a,并且判断a的值是否大于6000000,a位数小于等于三位,只有三个条件都满足的时候才能执行以下语句 if(isset($b) && '8b184b' === substr(md5($b),-6,6)){ //b的判断:判断参数b是否被设置;并且使用 md5() 函数对 $b 进行加密,并截取加密结果的最后 6 个字符 判断截取得到的加密结果是否等于字符串 '8b184b'; 当两个条件都满足的时候,key1=1; $key1 = 1; }else{ die("Emmm...再想想"); //不满足就输出"Emmm...再想想" } }else{ die("Emmm..."); }
满足题目的a,b,c
a的构造:
要求:a的值大于6000000,a位数小于等于三位
一看就知道要用科学计数法,这里我们构造a=7e6
b的构造:
题目要求:
使用 md5() 函数对 $b 进行加密,并截取加密结果的最后 6 个字符
判断截取得到的加密结果是否等于字符串 '8b184b';
这里要学习一下substr函数的用法(用于截取字符串的某一部分)
substr函数格式 (俗称:字符截取函数)
格式1: substr(string string, int a, int b);
格式2:substr(string string, int a) ;解释:
格式1:
1、string 需要截取的字符串
2、a 截取字符串的开始位置(注:当a等于0或1时,都是从第一位开始截取)
3、b 要截取的字符串的长度格式2:
1、string 需要截取的字符串
2、a 可以理解为从第a个字符开始截取后面所有的字符串。
if(isset($b) && '8b184b' === substr(md5($b),-6,6))
判断参数b是否被设置;并且使用 md5() 函数对 $b 进行加密,并截取加密结果的最后 6 个字符
判断截取得到的加密结果是否等于字符串 '8b184b';要找到满足条件的b,我们需要写一个脚本来爆破,可以参考以下脚本:
import hashlib # 导入Python的hashlib库,它提供了各种哈希函数,如md5,sha1,SHA256等。
for i in range(100000): # 循环从0到99999,总共100000次。
m = hashlib.md5() # 创建一个新的md5哈希对象,每次循环都会创建新的哈希对象。
m.update(str(i).encode()) # 将当前的数字i转化为字符串并编码为字节,然后更新哈希对象m。这一步是计算md5哈希的关键步骤。
h = m.hexdigest() # 从哈希对象m中获取十六进制的哈希值,并赋值给变量h。
if h[-6:] == "8b184b": # 检查h的最后6个字符是否为"8b184b"。如果是,则执行下面的代码。
print(i) # 打印当前的数字i。
break # 结束循环。
然后找个在线网站运行一下,即可爆破出相应的b的值,b=53724;
最后来看看c的构造,c最麻烦
看c的要求:
$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");
}这是一段PHP代码,其主要功能是接收一个来自GET请求的JSON字符串,并对其进行解码,然后进行一系列的检查。以下是对该代码的逐行解析:
$c=(array)json_decode(@$_GET['c']);
这行代码的作用是:
@$_GET['c']
:获取GET请求中键名为'c'的参数值,但在这里使用了@
操作符,意味着如果有错误发生,它不会抛出错误,而是静默失败。json_decode()
:对获取到的JSON字符串进行解码,将其转换为PHP对象或数组。(array)
:将解码后的结果强制转换为数组类型。
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
这行代码的作用是:
is_array($c)
:检查变量$c
是否是一个数组。!is_numeric(@$c["m"])
:检查$c
数组中的键名为"m"的元素是否不是数字。这里再次使用了@
操作符。$c["m"] > 2022
:检查"m"键的值是否大于2022。如果上述所有条件都满足,那么会执行花括号中的代码。
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
这行代码的作用是:
is_array(@$c["n"])
:检查$c
数组中的键名为"n"的元素是否是一个数组。count($c["n"]) == 2
:如果"n"键的值是一个数组,那么检查其元素数量是否为2。is_array($c["n"][0])
:检查"n"键的第一个元素是否也是一个数组。如果上述所有条件都满足,那么会执行花括号中的代码。
$d = array_search("DGGJ", $c["n"]);
这行代码的作用是在"n"键的数组中搜索"DGGJ"这个值,并返回其索引位置。如果找不到,返回false。
$d === false?die("no..."):NULL;
这是一个三元操作符,它检查
$d
是否等于false,也就是在"n"键的数组中是否没有找到"DGGJ"。如果没有找到,则输出"no..."并终止执行。否则,返回null。
6.foreach($c["n"] as $key=>$val){ ... }
这是一个foreach循环,它会遍历"n"键的数组中的每一个元素。如果发现任何一个元素的值等于"DGGJ",则输出"no......"并终止执行。
7.$key2 = 1;
这行代码将变量
$key2
的值设置为1。但在后续的代码中并没有使用到这个变量。
8.}else{ die("no hack"); }
这是上述if条件的else部分,如果上述所有的条件检查都没有通过,那么会执行这里的代码,输出"no hack"并终止执行。
9.}else{ die("no"); }
这是最外层的if条件的else部分,如果最开始对变量
$c
的检查没有通过,那么会执行这里的代码,输出"no"并终止执行。
$c=(array)json_decode(@$_GET['c']);
/*@$_GET['c']:获取GET请求中键名为'c'的参数值,但在这里使用了@操作符,意味着如果有错误发生,它不会抛出错误,而是静默失败。
json_decode():对获取到的JSON字符串进行解码,将其转换为PHP对象或数组。
(array):将解码后的结果强制转换为数组类型。*/
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022)
/*is_array($c):检查变量$c是否是一个数组。
!is_numeric(@$c["m"]):检查$c数组中的键名为"m"的元素是否不是数字。这里再次使用了@操作符。
$c["m"] > 2022:检查"m"键的值是否大于2022。*/
{
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0]))
/*is_array(@$c["n"]):检查$c数组中的键名为"n"的元素是否是一个数组。
count($c["n"]) == 2:如果"n"键的值是一个数组,那么检查其元素数量是否为2。
is_array($c["n"][0]):检查"n"键的第一个元素是否也是一个数组。*/
{
$d = array_search("DGGJ", $c["n"]);//这行代码的作用是在"n"键的数组中搜索"DGGJ"这个值,并返回其索引位置。如果找不到,返回false。
$d === false?die("no..."):NULL;//这是一个三元操作符,它检查$d是否等于false,也就是在"n"键的数组中是否没有找到"DGGJ"。如果没有找到,则输出"no..."并终止执行。否则,返回null。
foreach($c["n"] as $key=>$val)
{
$val==="DGGJ"?die("no......"):NULL;
}//这是一个foreach循环,它会遍历"n"键的数组中的每一个元素。如果发现任何一个元素的值等于"DGGJ",则输出"no......"并终止执行。
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}//这是最外层的if条件的else部分,如果最开始对变量$c的检查没有通过,那么会执行这里的代码,输出"no"并终止执行
m的构造:
不是数字且大于2022,我们随便构造m=2023a即可;
n的构造:
Array_search():查找数组中的元素并返回其下标。
元素n的下标是DGGJ
但是如果n的下标是DGGJ,程序就会终止。。。。。。
那必须是绕过它才行,那该怎么绕啊
这array_search()在查找元素的时候是进行弱类型比较,而在PHP里字符串==0是成立的,即“DGGJ"==0是成立的,因此,要保证在c["n"]中有0,即可绕过array_search的判断。
构造为?a=7e8&b=53724&c={"m":"2023a","n":[[],0]}
flag
You're right cyberpeace{4bc0c536b369be07b6e17d8d6f1b7693}