easyphp
目录
题目描述
php
时间:2023年9月2日
类型:Web php md5
WP
提取信息
进入环境它直接给了源码:
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
$a = $_GET['a'];
$b = $_GET['b'];
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}
$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");
}
if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}
粗略阅读后,这个页面需要我们get提交3个参数,每个参数都有不同的要求,我们现在来逐个击破。
参数a
参数a.条件
此if的大条件包含了3个小条件,当大条件为 True时,程序将继续运行,否则将立刻终止
$a = $_GET['a'];
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3)
参数a.代码分析
- isset($a) 判断变量a是否存在,存在→True,不存在→False
- intval($a) > 6000000 将变量a转化为int类型后 ,与6000000比较
- strlen($a) <= 3 变量a的长度,小于等于3
参数a.总结
参数a要存在,同时化为整数 类型后要大于 6000000 ,同时长度要 ≤ 3 。前两个条件很好满足,关键在于要在 >6000000同时要满足长度 ≤ 3。此时想到了科学计数法,利用科学计数法缩写绕过。
e.g.: 1e3 = 1000 3.14e5 = 314000
参数a.Payload
a=7e6
参数b
参数b.条件
此if的大条件包含了2个小条件,当大条件为 True时,程序将继续运行,否则将立刻终止
$b = $_GET['b'];
if(isset($b) && '8b184b' === substr(md5($b),-6,6))
参数b.代码分析
- isset($b) 判断变量b是否存在,存在→True,不存在→False
- ‘8b184b’ === substr(md5($b),-6,6) 截取md5加密后的变量b 的后6位,与’8b184b’作比较
**md5() 加密字符串。**md5(要加密的字符串)
e.g.: md5(“admin”) → “21232f297a57a5a743894a0e4a801fc3”**sbustr() 截取字符串。**
substr(截取字符串, 截取位置索引, 截取长度) 当截取位置索引为负数时,指的是从倒数第几个字符开始截取。
e.g.: substr(“abcdefg”, -3 , 2) → “ef”
参数b.总结
由于md5是非对称加密,我们无法反解密文得出原始数据,只能使用大量原始数据去做加密,再拿加密后的密文和目标密文 ‘8b184b’ 做比对。使用php或python编写简易的脚本,对密文进行爆破,得出结果为 “53724”
注意:php的md5()加密的是字符串类型
<?php
for($i=0;$i<100000;$i++){
if(isset($b) && '8b184b' === substr(md5($i),-6,6)){
echo $i; #53724
}
}
?>
参数b.Payload
b=53724
参数c
参数c.条件
除了外面的if,if里面还嵌套了一个if,在最里面还遍历了数组做查找判断。乍一看条件很复杂,但分开拆解一下还是很好理解的。
$c=(array)json_decode(@$_GET['c']);#通过json解码,并转变为数组赋值给变量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;
}
参数c.代码分析
-
c = ( a r r a y ) j s o n d e c o d e ( @ c=(array)json_decode(@ c=(array)jsondecode(@_ GET[‘c’]); is_array($c) 判断变量c是否为数组
-
!is_numeric(@$c[“m”]) 判断数组c中的 ‘m’ 元素的值 是否是数字类型
-
$c[“m”] > 2022) 判断数组c 中的 ‘m’ 元素的值 是否大于2022
-
↓嵌套if↓
-
is_array(@$c[“n”]) 判断数组c中的 ‘n’ 元素的值是否为数组
-
count($c[“n”]) == 2 判断数组c中的 ‘n’ 数组中元素的个数是否为 2 个
-
is_array($c[“n”][0]) 判断数组c中的 ‘n’ 数组中的0号元素 是否为数组
-
↓遍历查找↓
$d = array_search(“DGGJ”, $c[“n”]);
$d === false?die(“no…”):NULL;查找字符串"DGGJ" 是否不在数组c的n元素中
foreach($c[“n”] as $key=>$val){
$val===“DGGJ”?die(“no…”):NULL;}
参数c.总结
总体是3个版块,第1版块是对变量c的要求;第2版块是对c中m元素的要求;第3版块是对c中n元素的要求。
- c必须是一个json结构的数据,且能转变为数组;
只要遵循json结构书写就可以了 变量={“元素1”:元素1的值 , “元素2” , … - c[‘m’]不可以是数字类型,且大于2022;
大于2022很好说,但要求它不可以是数字类型,那我们可以在 数字后加上字母使php将它解析为字符串类型 - c[‘n’]必须是一个数组类型,并包含两个元素,且第一个元素也是一个数组。
- 要让array_search(“DGGJ”,, $c[“n”])的返回值为True,同时 “DGGJ” 不得出现在c[‘n’]中。
这是参数c中的矛盾点 ,也是这道题的考点,array_search()绕过
array_search()函数中使用的比较是 弱等于(==)。弱比较下0与字符串比较结果 为True,也就是说 “DGGJ” == 0 → True。
参数c.Payload
c={"m":"2023a","n":[[],0]}
得到flag
最终payload为:?a=7e6&b=53724&c={"m":"2023a","n":[[],0]}
总结
这道题考察了get传参的格式,json数据的格式。php的数字类型的科学计数写法,字符串与数字的弱比较,md5的爆破,和array_search()绕过,是一道比较不错的综合题目