首页 > 技术文章 > web9

zi-Chuan 2020-03-07 17:51 原文

上源代码

<?php
include "flag.php";
show_source(__FILE__);
$v1=0;$v2=0;
$a=(array)json_decode(@$_GET['dcn']);
if(is_array($a)){
   is_numeric(@$a["d1"])?die("错误"):NULL;
   if(@$a["d1"]){
       ($a["d1"]>2019)?$v1=1:NULL;
   }
   if(is_array(@$a["d2"])){
       if(count($a["d2"])!==5 OR !is_array($a["d2"][0])) die("错误");
       $pos = array_search("dcnctf", $a["a2"]);
       $pos===false?die("错误"):NULL;
       foreach($a["d2"] as $key=>$val){
           $val==="dcnctf"?die("错误"):NULL;
       }
       $v2=1;
   }
}

if($v1 && $v2){
   echo $flag;
}
?> 

添加注释解析

<?php
//这里使用include函数包含‘flag.php'
include "flag.php";

show_source(__FILE__);
//定义v1,v2两个变量 初始值为0
$v1=0;$v2=0;

//定义变量a用来接收GTE【’dcn']的值 并进行Json解码和强转成数组
$a=(array)json_decode(@$_GET['dcn']);
//做一个if判断,变量a是否为数组
if(is_array($a)){
    //如果$a["d1"]是数字 则显示为 错误 否则为 NULL
   is_numeric(@$a["d1"])?die("错误"):NULL;
    
    //如果$a["d1"]存在
   if(@$a["d1"]){
        //如果$a["d1"]大于2019 则$v1=1,否则NULL
       ($a["d1"]>2019)?$v1=1:NULL;
   }

    //如果$a["d2"]存在且为数组
   if(is_array(@$a["d2"])){
        //(如果数组$a["d2"]的总行数不等于5 或者 $a["d2"][0]不是数组  )则输出"错误"并结束
       if(count($a["d2"])!==5 OR !is_array($a["d2"][0])) die("错误");
        //查找$a["d2"]数组中是否存在dcnctf的键名,并赋值给$pos
       $pos = array_search("dcnctf", $a["a2"]);
        //如果pos恒等于假 返回 错误 并结束
       $pos===false?die("错误"):NULL;
        //循环数组$a["d2"] $key 为每次循环数组的键   $val为每次循环数组的值
       foreach($a["d2"] as $key=>$val){
            //如果每次循环数组的的值恒等于"dcnctf"  则输出"错误"并结束程序
           $val==="dcnctf"?die("错误"):NULL;
       }
        //给v2变量赋值
       $v2=1;
   }
}
//如果 变量 v1 v2有值 则输出变量flag
if($v1 && $v2){
   echo $flag;
}
?>         

通过注释了解到,这里要拿到flag就必须使v1 v2成立,所以这里我们分别求值,然后再合在一起。

首先是v1的值

//定义变量a用来接收GTE【’dcn']的值 并进行Json解码和强转成数组
$a=(array)json_decode(@$_GET['dcn']);
//做一个if判断,变量a是否为数组
if(is_array($a)){
    //如果$a["d1"]是数字 则显示为 错误 否则为 NULL
   is_numeric(@$a["d1"])?die("错误"):NULL;
    
    //如果$a["d1"]存在
   if(@$a["d1"]){
        //如果$a["d1"]大于2019 则$v1=1,否则NULL
       ($a["d1"]>2019)?$v1=1:NULL;
   }

传入dcn,经过json构造数组,判断$a['d1']是否为纯数字,首先变量不能为纯数字,其次在数值判断上要大于2019,因此可以利用弱类型进行绕狗,即$a["d1"]=2020a。

然后是v2的值

//如果$a["d2"]存在且为数组
   if(is_array(@$a["d2"])){
        //(如果数组$a["d2"]的总行数不等于5 或者 $a["d2"][0]不是数组  )则输出"错误"并结束
       if(count($a["d2"])!==5 OR !is_array($a["d2"][0])) die("错误");
        //查找$a["d2"]数组中是否存在dcnctf的键名,并赋值给$pos
       $pos = array_search("dcnctf", $a["a2"]);
        //如果pos恒等于假 返回 错误 并结束
       $pos===false?die("错误"):NULL;
        //循环数组$a["d2"] $key 为每次循环数组的键   $val为每次循环数组的值
       foreach($a["d2"] as $key=>$val){
            //如果每次循环数组的的值恒等于"dcnctf"  则输出"错误"并结束程序
           $val==="dcnctf"?die("错误"):NULL;
       }
        //给v2变量赋值
       $v2=1;

这里要求d2变量是一个数组,且元素个数为5个,第一个元素为数组,因此构造 $a["d2"]=[[],1,2,3,4]

获取flag

//如果 变量 v1 v2有值 则输出变量flag
if($v1 && $v2){
   echo $flag;
}

既然上面的已经获取得到v1 v2.所以构造语句:   拿到flag

?dcn={"d1":"2020a","d2":[[],2,3,4,5],"a2":["dcnctf"]}

 

推荐阅读