1.信息收集:是PHP 代码审计;
2.代码审计:
<?php
highlight_file(__FILE__);//对文件源代码高亮显示;
$key1 = 0;
$key2 = 0;
$a = $_GET['a'];
$b = $_GET['b'];
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
//isset($a):检查是否已经被定义并且不为NULL,如果已经定义且不为null返回为true;否则false;
/*intval($a):变量或表达式转换为整数;如果传递给intval()函数的变量或表达式不是数字或不是可以转换为数字的字符串,
则函数返回0;如果要转换的值是浮点数,则会将其向下舍入到最接近的整数;*/
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
//md5($b):对$b进行MD5哈希处理;
/*MD5算法将输入数据转换为固定长度的128位哈希值,然后以十六进制表示形式呈现,
每个十六进制数表示4位。因此,最终的MD5哈希值是由32个十六进制字符组成的。*/
//substr(string $string, int $start, int|null $length = null): string|false:从字符串中提取子字符串。
//提取子字符串的字符串,起始位置,长度(可选)
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}
$c=(array)json_decode(@$_GET['c']);
/*@$_GET['c']:GET请求中的参数获取语法。$_GET是一个包含通过GET请求传递的参数的PHP超全局变量。
@符号用于抑制可能的错误消息,以防止在参数不存在时出现警告或错误。
json_decode():用于将JSON格式的字符串转换为PHP对象或数组。在这里,被用于解析GET请求中的参数"c"的值。
(array):这是一个类型转换操作符,将json_decode()函数的返回值转换为数组类型。*/
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
//@$c["m"]:这是一个数组访问语法,用于获取变量$c中键为"m"的值。
//is_numeric()判断一个变量是否数字或数字字符串;
//is_array()判断是否为数组;
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
//$c["n"][0])获取数组变量中键为"n"的值,并获取索引为0的元素;
//count($c["n"])数组变量中获取"n"的值后对其计元素的数量
$d = array_search("DGGJ", $c["n"]);
//在数组$c["n"]中搜索值为"DGGJ"的元素,并返回该元素的索引值。
$d === false?die("no..."):NULL;
//判断是否为false,如果是返回"no..."并终止脚本的运行;如果是true,返回:NULL;空值,什么也不做;
foreach($c["n"] as $key=>$val){
//foreach()循环遍历数组中的每个元素;$c["n"]获取数组变量中键名为"n"的元素的值
//每次循环中,将当前元素的键名赋值给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;
}
?> Emmm...
代码审计后:
1.条件:
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
$a的值可以是:1e9; 字符串的长度小于等于3,大于6e6;如6e7;1e8;
2.
条件:
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
怎么找到变量b的值? MD5是一种不可逆的哈希算法,无法通过MD5哈希值反推出原始值;也就是说只能一个一个去试,用python写个脚本;我就试用数字;
得到变量b=53724
3.条件:
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
可以是:"m":"2023a" ;
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;
}
分析:当用array_search()如果键n中含:“DGGJ”,返回值NULL;
当用foreach(),键n含“DGGJ”时,返回“no...”终止; 两个矛盾?怎么办?
这两个中foreach循环中真正 $val==="DGGJ"是否相等来比较; 这又不能有“DGGJ” 也就是说数组中没有“DGGJ”;
而array_search()也是一种比较,字符串和数组中的值比较,如果数组中的值是整数,那字符串自动转换成0;
"n":[[],0]; "n":[[123],0] 都可以;数组第二个元素必须是0;’