[xctf] 江苏工匠杯easyphp【web系列】

题外话

这道题emmm怎么说呢我感觉这难度标签不至于1星吧,这等下萌新看了看这不直接劝退?不过话说回来,这道题没绕什么弯子思路比较直,绕waf的手段最好记下来备着以后刷题用。

一、审题

这是来自江苏工匠杯的一道题,我们打开题目康康:

又是直接扔给我们一段代码,那就开始快乐的(bushi)代码审计吧,代码如下:

<?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;
}

二、代码审计

首先老样子找到我们的关键词flag,这里是一段if语句,如果$key1和$key2都为1时即可输出我们的flag,再跟进$key1和$key2这两个变量,发现分别在两个if语句里面,所以我们只要满足这两个大条件和内置的相关的小条件即可获得flag

if($key1 && $key2){
    include "Hgfks.php";
    echo "You're right"."\n";
    echo $flag;
}

首先我们先来看第一个if

$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两个参数,第一个if语句的含义即为将a转化为整型大于6000000,并且a的长度要小于3,这里直接用我们的科学计数法就可直接解决,a=9e9 (9e9=9*10^9),第二句if的含义为将b进行MD5加密并截取加密后字符串的后六位等于"8b184b",这里就是简单的一个哈希碰撞,这里我写了一个懒人简易版的jio本跑就完事了(碰到其他题的哈希碰撞时只需要修改res和flag的截取位置即可)。

import random
import hashlib

res = "8b184b"
while 1:
    temp = random.randint(10**11, 10**12 - 1)
    temp = str(temp)
    MD5 = hashlib.md5()
    MD5.update(temp.encode(encoding='utf-8'))
    flag = MD5.hexdigest()
    if flag[-6:]==res :
        print("碰撞成功:"+flag)
        print("明文为:"+temp)
        break
    else:
        print("碰撞中.....")
    

碰撞完后得到明文:261815215889

 此时$key1已经等于1了,接下来看到第二个大if语句

$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参数,注意此时的c要是json格式的字符串,其中key为m的value不能为数字且要大于数字2022,而当字符串与数字相比时会把字符串强制转化为整型即"123abc"会转成123,"abc"会转成0,这里和弱相等绕过时的一样,所以这里的m应该等于"9999abc",继续往下跟进,key为n的value必须为一个数组且value数量必须为2,且第一个value必须是一个数组,那么c的雏形就是: {"m":"9999abc","n":[["xxx"],xxx]},继续往下看,第一次使用array_search搜索n中是否有"DGGJ",有的话才能进行下一步,第二次使用foreach循环搜索n中的值是否含有"DGGJ",没有的话才能使$key2=1,而这里看上去是矛盾的,其实就是矛盾的哈哈哈,但是这是ctf题所以这俩函数必绕一个,刚好array_search可以绕过,建议题后去看看这个函数,这里直接说结论,也是一样的与弱相等类似即该函数进行匹配时如果是字符串与数字,先会把字符串转化为整型再加以比较,而"DGGJ"转化为整型即为0,所以c传的参数为:{"m":"9999abc","n":[["666"],0]} ,完整的payload为:?a=9e9&b=261815215889&c={"m":"9999abc","n":[["666"],0]}

最终得到了我们的flag。 

总结

这里绕来绕去大部分还是弱相等问题,出现的知识点的要求就是自己编写哈希碰撞脚本的能力,intval的绕过,array_search的绕过还是值得记下来的。

  • 13
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shutTD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值