微信营销手机网站模板,软件培训班,凡科网站建设套餐报价,国外做问卷调查的网站进入题目页面如下 是一段PHP代码进行代码审计
?php
// 高亮显示PHP文件源代码
highlight_file(__FILE__);// 初始化变量$key1和$key2为0
$key1 0;
$key2 0;// 从GET请求中获取参数a的值#xff0c;并赋值给变量$a
$a $_GET[a];
// 从GET请求中获取参数b的值#xff…进入题目页面如下 是一段PHP代码进行代码审计
?php
// 高亮显示PHP文件源代码
highlight_file(__FILE__);// 初始化变量$key1和$key2为0
$key1 0;
$key2 0;// 从GET请求中获取参数a的值并赋值给变量$a
$a $_GET[a];
// 从GET请求中获取参数b的值并赋值给变量$b
$b $_GET[b];
// 检查是否在GET请求中存在并且将$a转换为整数后大于6000000同时$a的字符串长度小于等于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$key1 1;}else{// 如果$b不满足条件输出提示信息并终止脚本执行die(Emmm...再想想);}
}else{// 如果$a不满足条件输出提示信息并终止脚本执行die(Emmm...);
}// 从GET请求中获取参数c的值使用json_decode函数将其解码为数组并将结果强制转换为数组类型赋值给变量$c
$c(array)json_decode($_GET[c]);// 检查$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$d array_search(DGGJ, $c[n]);// 如果没有找到值为DGGJ的元素输出提示信息并终止脚本执行$d false?die(no...):NULL;// 遍历$c[n]数组检查是否有元素的值直接等于DGGJforeach($c[n] as $key$val){// 如果有元素的值等于DGGJ输出提示信息并终止脚本执行$valDGGJ?die(no......):NULL;}// 如果上述条件都满足将$key2的值设置为1$key2 1;}else{// 如果$c[n]不满足条件输出提示信息并终止脚本执行die(no hack);}
}else{// 如果$c不满足条件输出提示信息并终止脚本执行die(no);
}// 检查$key1和$key2的值是否都为1如果都为1则表示所有条件都满足
if($key1 $key2){// 包含名为Hgfks.php的文件include Hgfks.php;// 输出成功提示echo Youre right.\n;// 输出$flag变量的值echo $flag;
}?
重点看以下几行代码
// 检查是否在GET请求中存在并且将$a转换为整数后大于6000000同时$a的字符串长度小于等于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$key1 1;// 检查$key1和$key2的值是否都为1如果都为1则表示所有条件都满足
if($key1 $key2){// 包含名为Hgfks.php的文件include Hgfks.php;// 输出成功提示echo Youre right.\n;// 输出$flag变量的值echo $flag;
可以知道当$key1和$key2值都为真时输出flag
先构造$key1,通过GET传参a、b的值 $a需满足字符串长度小于等于3且值要大于6000000 常规的十进制数字表示中要同时满足字符串长度小于等于 3 且值大于 6000000 是不可能的。但在 PHP 中存在特殊的类型转换规则我们可以借助科学计数法来绕过这个限制
在 PHP 里当使用 intval() 函数转换字符串时科学计数法表示的字符串会被正确转换为对应的整数。比如字符串 6e6 代表 也就是 6000000。
需要大于6000000则可以令$a的值为“7e6”、“8e6”、“9e6”等 $b的MD5哈希值的最后6位等于8b184b 用python写一个脚本爆破出$b的值脚本如下
import hashlib
# 目标 MD5 哈希值的最后 6 位
target_suffix 8b184b
# 从一个简单的字符集开始生成字符串进行尝试
charset abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
length 1
while True:from itertools import product# 生成所有可能的长度为 length 的字符串组合for combination in product(charset, repeatlength):s .join(combination)# 计算字符串的 MD5 哈希值md5_hash hashlib.md5(s.encode()).hexdigest()# 检查哈希值的最后 6 位是否等于目标后缀if md5_hash[-6:] target_suffix:print(f找到符合条件的字符串: {s})print(f其 MD5 哈希值为: {md5_hash})breakelse:# 如果当前长度的所有组合都没有找到符合条件的字符串增加长度继续尝试length 1continuebreak
可以用pycharm来执行结果如下 得到$b的值为bDIOS
将a、b的值通过get传参并查看输出
构造的payload为 ?a9e6bbDIOS 看到输出的结果改变$key1以及构造成功下面构造$key2
重点看以下几行代码
// 从GET请求中获取参数c的值使用json_decode函数将其解码为数组并将结果强制转换为数组类型赋值给变量$c
$c(array)json_decode($_GET[c]);// 检查$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$d array_search(DGGJ, $c[n]);// 如果没有找到值为DGGJ的元素输出提示信息并终止脚本执行$d false?die(no...):NULL;// 遍历$c[n]数组检查是否有元素的值直接等于DGGJforeach($c[n] as $key$val){// 如果有元素的值等于DGGJ输出提示信息并终止脚本执行$valDGGJ?die(no......):NULL;}// 如果上述条件都满足将$key2的值设置为1$key2 1;
需要通过上传json形式的c来实现
外层条件
if(is_array($c) !is_numeric($c[m]) $c[m] 2022)is_array($c):$c必须是一个数组。通过 json_decode 解析 $_GET[c] 得到的结果要能被强制转换为数组 !is_numeric($c[m]):$c 数组中的键 m 对应的值不能是一个数字。这里使用 符号来抑制可能出现的未定义索引警告 $c[m] 2022:虽然 $c[m] 不是数字但在进行比较时PHP 会尝试将其转换为数字进行比较。可以利用 PHP 的类型转换规则使用以数字开头的字符串来满足这个条件。 由于is_numberic会将数字和数字字符串判定为真但前导数字字符串不会以及是弱类型比较且是将c[m]的值与数字进行比较我们可以直接用前导字符串来作为比较数字与2022进行比较。所以令c[m]2025a
键n值要满足:有且仅有两个元素的数组第一个值为数组第二个值要满足array_search(DGGJ, $c[n])返回为真同时c[n]中又不能出现DGGJ。
可以利用array_search函数在比较两者是否相等时是使用的弱类型比较。由于DGGJ是既非数字字符串又非先导数字字符串的字符串其在与数字进行比较时会转化为数字0。从而令c[n]的第二个值为0。一点思考此处若不是DGGJ而是其他字符串时我们应该视情况而定选择合适的数字所以令c[n](array(1,2),0)
内层条件
if(is_array($c[n]) count($c[n]) 2 is_array($c[n][0]))is_array($c[n])$c 数组中的键 n 对应的值必须是一个数组 count($c[n]) 2这个数组的元素个数必须为 2 is_array($c[n][0])数组 $c[n] 的第一个元素也必须是一个数组
所以最后构造的$c的payload为c{m:2025a,n:[[1,2],0]}
最后传参a、b、c构造payload ?a8e6bbDIOSc{m:2025a,n:[[1,2],0]} 最终得到flag