攻防世界-easyphp 思路分析

打开靶场 是代码审计

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

?> Emmm...

对其进行代码审计

首先 key1 key2 为0  get传参两个参数a和b 

参数a需要满足以下条件

intval() 函数用于获取变量的整数值  传入需要一个整数 其值要大于6000000  且长度小于3

参数b满足以下条件

MD5加密后末尾值为'8b184b'的字符串 这个可以使用脚本实现

a和b参数满足条件后 key1的值置为1 

那么a参数我们就可以使用科学计数法来绕过 这样子 a的值既可以大于6000000 也保证了长度

这里的值有很多 大家可以自己搜索 

我这里使用的值为a=1e7 

b参数的爆破脚本如下

import hashlib

for i in range(100000):
    a = hashlib.md5()
    a.update(str(i).encode())
    q = a.hexdigest()
    if q[-6:] == "8b184b":  #  判断MD5最后6位的值是否位8b184b
        print(i)

跑出结果为53724 所以这里的b的值就为53724 

执行完毕后 可以发现 前面已经绕过了 已经进入c参数的逻辑了  下面来看C参数的逻辑

$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
//传入数组c  不能是数字 大于2022  php弱类型比较  传入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;
        }
        $key2 = 1;

两个数组元素也即是说键值有两个  d在数组c["n"]中搜索"DGGJ",如果匹配成功返回键值  数组中是键值对的形式

foreach()循环遍历数组中的每个元素;$c["n"]获取数组变量中键名为"n"的元素的值   每次循环中,将当前元素的键名赋值给key变量,将当前元素的值赋值给val变量

这是最关键的地方
既要search到 DGGJ    遍历时又不要DGGJ  但array_search()又要查找并且要有结果 这里就需要绕过了
这里用array_search函数的一个漏洞 待匹配的模式串里有0时会与字符串进行比较时,字符串也会转变为0,这样就算不出现DGGJ也可以返回1

绕过is_array和array_search函数

函数的语法给到大家

这里的true参数的意义就是为我们后面绕过做了铺垫


绕array_search函数保证非0下标元素含0就行,字符串转数字都是0


数组的第一个值较为简单 是一个数组即可
数组中的第二个值要满足array_search("DGGJ", $c["n"])返回为真,同时c["n"]中又不能出现"DGGJ"。  
也就是说数组中不能有DGGJ这个字符串但是又要保证array_search函数最后返回的结果为真 因为数组中没有这个字符串 所以返回不了对应的键名 只能返回false 而我们必须让其结果为真 才可以进入下一个逻辑
  下面是这个函数返回值的贴图 助于理解
 
所以此处利用array_search函数在比较两者是否相等时是使用的弱类型比较。又由于"DGGJ"是一个普通的字符串,其在与数字进行比较时会转化为数字0。  从而令c['n']的第二个值为0。


array_search()没有设置strict参数(如果该参数被设置为 TRUE,则函数在数组中搜索数据类型和值都一致的元素),我们就可以用0和DGGJ进行弱比较


在php中,三个等号“===”是全等比较运算符,用于比较两个操作数的值是否相等,同时检测它们的类型是否相同;只有两边的值和数据类型都相等时,运算结果才是TRUE


这里我们需要保证比较的结果为false就不会执行die语句了  如果数组中存在DGGJ进行比较结果就是true了 为true那么就执行die语句了 至此闭环成功

这里给一个弱类型比较的文章

https://www.cnblogs.com/anbus/p/10000571.html

所以最后c的传参为   c={"m":"20222a","n":[[1,2],0]}

[1,2]中的数组数据无所谓 没有也行 

最终的payload如下

?a=1e7&b=53724&c={"m":"20222a","n":[[1,2],0]}

flag拿出

这道题考查的就是代码审计 以及一些函数的理解运用与绕过 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

layz_y

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

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

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

打赏作者

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

抵扣说明:

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

余额充值