Skip to main content

So vermeiden Sie Web-Cache-Poisoning-Angriffe

Artikel von
Headshot of Najia Gul

Najia Gul

feature cache poison

11. September 2023

0 Min. Lesezeit

Web-Cache-Poisoning ist ein Cyberangriff, der bei ahnungslosen Websites erheblichen Schaden anrichtet. Dabei werden Schwachstellen in den Caching-Mechanismen ausgenutzt, die Webserver, Proxys und Content Delivery Networks (CDNs) verwenden. So wird die Integrität von Daten gefährdet. Angreifer können Cache-Poisoning nutzen, um schädliche Payloads auszuliefern, vertrauliche Informationen zu manipulieren oder Nutzer auf betrügerische Websites umzuleiten.

In diesem Artikel beleuchten wir umfassend Web-Cache-Poisoning-Angriffe und ihre Funktionsweise. Außerdem besprechen wir die wirksamsten Gegenmaßnahmen, mit denen Sie Ihre Webanwendungen schützen können.

Web-Caching und seine Bedeutung verstehen

Web-Caching ist ein wichtiger Prozess, um die Leistung einer Website zu verbessern. Dabei werden Webinhalte wie HTML-Dateien, Bilder, Skripte und Stylesheets vorübergehend an sogenannten Caches gespeichert. So lassen sich diese Inhalte bei späteren Nutzeranfragen schneller und einfacher wieder abrufen.

Je nachdem, wo Web-Caches gespeichert werden, unterscheidet man verschiedene Caching-Mechanismen. Dazu gehören:

  • Browser-Caching: Beim Browser-Caching speichern Webbrowser Kopien statischer Ressourcen auf dem Gerät des Nutzers. Besucht dieser eine Website erneut, prüft der Browser seinen Cache auf zuvor heruntergeladene Dateien. Sind diese noch aktuell, ruft der Browser sie ab, statt eine neue Anfrage an den Server zu senden.

  • Server-Caching: Während Browser-Caching auf der Client-Seite stattfindet, speichert Server-Caching Inhalte auf dem Server selbst, damit sie später wiederverwendet werden können. Sendet ein Nutzer eine Anfrage an den Ursprungsserver, speichert der Cache eine Kopie der generierten Antwort. Bei späteren Anfragen nach demselben Inhalt liefert der Cache dann diese Kopie aus, statt den Ursprungsserver zu bemühen.

  • Content-Delivery-Network-(CDN-)Caching: CDNs sind geografisch verteilte Servernetzwerke, die statische Webinhalte zwischenspeichern und ausliefern. Möchte ein Nutzer erneut auf diese Inhalte zugreifen, bearbeitet der Edge-Server, der sich am nächsten zu seinem Standort befindet, die Anfrage. Dadurch muss der Ursprungsserver nicht alle Anfragen bearbeiten.

Caching verringert den Zeit- und Ressourcenaufwand für den Abruf von Webinhalten. Das führt zu kürzeren Ladezeiten und einer besseren Nutzererfahrung. Außerdem wird die Serverlast reduziert, sodass der Server mehr Anfragen bearbeiten kann.

Caching birgt jedoch auch einige potenzielle Risiken, insbesondere wenn es nicht richtig implementiert oder verwaltet wird. Werden zwischengespeicherte Inhalte nicht rechtzeitig aktualisiert, können sie veraltet oder fehlerhaft sein. Das führt zu Inkonsistenzen oder Sicherheitslücken, die Angreifer ausnutzen können.

Auch das Zwischenspeichern vertraulicher Informationen kann Datenschutzrisiken bergen. Enthält der Cache beispielsweise personenbezogene Daten oder Kontoanmeldedaten eines Nutzers, kann unbefugter Zugriff zu Datenschutzverletzungen und Datenlecks führen.

So funktionieren Web-Cache-Poisoning-Angriffe

Beim Web-Cache-Poisoning versuchen Angreifer, die Caching-Infrastruktur dazu zu bringen, manipulierte oder nicht autorisierte Inhalte an Nutzer auszuliefern. Der Angriff läuft in der Regel in vier Schritten ab:

  1. Ein anfälliges Ziel identifizieren: Der Angreifer sucht nach einer Website mit möglichen Schwachstellen in ihren Cache-Mechanismen, etwa aufgrund von Fehlkonfigurationen oder unzureichender Eingabevalidierung.

  2. HTTP-Anfragen manipulieren: Der Angreifer sendet HTTP-Anfragen an die Zielwebsite, die darauf ausgelegt sind, diese Schwachstellen auszunutzen.

  3. Cache-Mechanismen ausnutzen: Der Angreifer wendet verschiedene Techniken an, um eigene schädliche Inhalte einzuschleusen oder bereits im Cache gespeicherte Inhalte zu manipulieren.

  4. Manipulierte Inhalte ausliefern: Nach Abschluss des Angriffs rufen nachfolgende Anfragen an den Cache die vergifteten statt der legitimen Inhalte ab.

Erfolgreiche Web-Cache-Poisoning-Angriffe können vertrauliche oder geheime Informationen offenlegen. Angreifer können die zwischengespeicherten Inhalte anschließend manipulieren, um die Zielwebsite zu verunstalten, Falschinformationen zu verbreiten oder schädliche Links zu verteilen.

Noch schlimmer: Angreifer kombinieren Web-Cache-Poisoning häufig mit anderen Cyberangriffen, um den Schaden zu vergrößern. So vergifteten Angreifer 2018 erfolgreich den Cache der Website von British Airways. Sie schleusten eine schädliche Payload ein, die Nutzer auf eine betrügerische Website umleitete. Dadurch konnten die Angreifer die E-Mail-Adressen und Kreditkarteninformationen von über 40.000 Nutzern im Vereinigten Königreich stehlen.

Häufige Angriffsvektoren für Web-Cache-Poisoning

Um sich vor Cache-Poisoning-Angriffen zu schützen, müssen wir potenzielle Schwachstellen einer Website identifizieren und beheben. Im Folgenden finden Sie einige der häufigsten Angriffsvektoren und erfahren, wie Angreifer sie ausnutzen können:

  • Manipulation von HTTP-Headern: Angreifer ändern häufig HTTP-Header, um ihre schädlichen Inhalte legitimen URLs oder Cache-Schlüsseln zuzuordnen. So können sie beispielsweise den HTTP-Header Cache-Control manipulieren und das Caching-System anweisen, ihre Inhalte zu speichern. Dadurch kann der Angreifer seine schädliche Payload an nachfolgende Nutzer ausliefern, die dieselbe Ressource anfordern – selbst wenn sich der legitime Inhalt inzwischen geändert hat.

  • Manipulation von Query-Strings: Angreifer können ausnutzen, wie Webanwendungen Query-Strings verarbeiten. Dazu manipulieren sie die an die URL angehängten Abfrageparameter, um mehrere Cache-Varianten für dieselbe Ressource zu erzeugen, die möglicherweise eine schädliche Payload enthalten.

  • Manipulation von Cookies: Angreifer können den Cache auch vergiften, indem sie die Werte und Attribute von Cookies ändern. Damit bringen sie das Caching-System dazu, ihre Inhalte im Kontext einer legitimen Nutzersitzung im Cache zu speichern.

Beachten Sie jedoch, dass dies nur einige Beispiele sind. Angreifer suchen ständig nach neuen Techniken und Schwachstellen, um ihre Ziele zu erreichen. Es reicht nicht aus, nur diese häufigen Angriffsvektoren im Blick zu behalten, um Webdaten zu schützen.

Cache-Poisoning-Angriff durch Manipulation von HTTP-Headern

Sehen wir uns ein Beispiel für Web-Cache-Poisoning an, bei dem ein Angreifer eine Schwachstelle einer Website über HTTP-Header ausnutzt. Ein häufiges Ziel ist der Header X-Forwarded-Host (XFH). Dieser De-facto-Standardheader dient dazu, den ursprünglichen Host zu bestimmen, den der Client in der HTTP-/HTTPS-Anfrage an Ihre Anwendung oder API angefordert hat. Der Wert dieses Headers ist in der Regel ein Hostname, der das ursprüngliche Ziel der Client-Anfrage angibt.

Dieser Header soll zwar in Umgebungen mit Reverse-Proxy oder Load Balancer hilfreich sein, kann aber von Angreifern ausgenutzt werden, wenn er nicht ordnungsgemäß validiert wird. Beachten Sie jedoch, dass Angreifer möglicherweise auch viele andere Header für ähnliche Angriffe verwenden können.

Betrachten wir nun unser Beispiel, das eine potenzielle Schwachstelle in JavaScript-Code mit einem Caching-Dienst zeigt. Für diese Demonstration verwenden wir Redis.

const express = require('express');
const app = express();
const redis = require('redis');
const client = redis.createClient();

// Middleware to handle caching
app.use((req, res, next) => {
    const key = req.originalUrl; // use request url as a key

    client.get(key, (err, data) => {
        if (err) throw err;

        if (data !== null) {
            res.send(data);
        } else {
            next();
        }
    });
});

app.get('/user', (req, res, next) => {
    const host = req.headers['x-forwarded-host'] || 'unknown host';
    const response = `Welcome, user ${req.query.userId}! You're accessing from ${host}`;

    // Cache the response using the URL as a key
    client.set(req.originalUrl, response, 'EX', 3600); // Cache for 1 hour

    res.send(response);
    next();
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Die Caching-Middleware verwendet die ursprüngliche URL als Schlüssel, um Antworten in Redis zwischenzuspeichern. originalURL bezeichnet alles, was auf den Hostnamen folgt (zum Beispiel /user?userId=1 in http://example.com/user?userId=1). Ist die mit dieser URL verknüpfte Antwort im Cache vorhanden, wird sie sofort gesendet. Andernfalls wird die Anfrage an den zuständigen Routen-Handler weitergeleitet, der in unserem Fall eine nutzerspezifische Begrüßung generiert und zwischenspeichert.

Diese Implementierung kann jedoch zu Cache-Poisoning-Angriffen führen. Ein Angreifer könnte ausnutzen, dass wir Antworten anhand der URLs zwischenspeichern. Nehmen wir an, der Header X-Forwarded-Host, eine vom Nutzer kontrollierte Eingabe, wird zur Generierung der Antwort verwendet. Der Code zeigt, dass die Begrüßung anhand des Werts von X-Forwarded-Host erstellt wird (zum Beispiel „Willkommen, Nutzer ${req.query.userId}, Sie greifen von ${req.headers['x-forwarded-host']} aus zu!“). Wird dieser Wert nicht ordnungsgemäß validiert, könnte ein Angreifer schädliche Skripte in den Header einfügen, die anschließend im Cache gespeichert und an andere Nutzer ausgeliefert werden.

So könnte der Angriff ablaufen:

  • Der Angreifer sendet eine GET-Anfrage an /user?userId=1 und setzt den Header X-Forwarded-Host auf foo."><script>alert(document.cookie)</script>.

  • Der Server generiert eine Begrüßung, die den Wert des Headers enthält, speichert sie unter dem Schlüssel /user?userId=1 im Cache und sendet sie an den Angreifer zurück.

  • Nun wird bei jeder nachfolgenden Anfrage an /user?userId=1 eine schädliche Begrüßung aus dem Cache ausgeliefert.

Eine Möglichkeit, die Sicherheit des obigen Codes zu erhöhen, besteht darin, die für den Cache-Schlüssel verwendete URL zu bereinigen. So könnten Sie eine einfache Bereinigungsfunktion implementieren, die die escape-Methode aus dem validator-Modul verwendet:

const validator = require('validator');

function sanitize(url) {
    let parsedUrl;

    try {
        parsedUrl = new URL(url);
    } catch (err) {
        throw new Error('Invalid URL');
    }

    parsedUrl.searchParams.forEach((val, param) => {
        // Escaping potentially harmful characters in the query parameters
        parsedUrl.searchParams.set(param, validator.escape(val));
    });

    return parsedUrl.toString();
}

Mit der von uns implementierten Funktion sanitize lassen sich alle Zeichen aus req.originalUrl entfernen, die eine potenzielle Bedrohung darstellen könnten:

const key = sanitize(req.originalUrl);

Außerdem können Sie die Gültigkeit von Nutzereingaben überprüfen, indem Sie in unserem Express-Server eine Middleware-Funktion ausführen. Das folgende Beispiel zeigt einen grundlegenden Ansatz zur Validierung von Headern:

const validator = require('validator');

app.use((req, res, next) => {
    const forwardedHostHeader = req.headers['x-forwarded-host'];
    if (forwardedHostHeader) {
        const isFQDN = validator.isFQDN(forwardedHostHeader);
        if (!isFQDN) {
            // If the header does not represent a fully qualified domain name, the request is rejected
            return res.status(400).send('Invalid X-Forwarded-Host header');
        }
    }

    next();
});

Hier nutzen wir die Funktion isFQDN aus dem validator-Modul, um zu prüfen, ob der Header X-Forwarded-Host einen gültigen Domainnamen enthält. Ist dies nicht der Fall, weist die Middleware-Funktion die Anfrage zurück und sendet den Status 400 Bad Request zurück.

Dieser Validierungsschritt ist unerlässlich, um das Einschleusen schädlicher Skripte über den Header X-Forwarded-Host header zu verhindern. Wie bereits erläutert, könnte ein solches Szenario zu einem Cache-Poisoning-Angriff führen.

Best Practices zur Abwehr von Web-Cache-Poisoning

Eine klare Caching-Richtlinie ist die wirksamste Maßnahme, um Web-Cache-Poisoning zu verhindern. Sie legt eindeutig fest, welche Inhalte wie lange und unter welchen Bedingungen zwischengespeichert werden. Bei der Festlegung einer Caching-Richtlinie müssen wir Faktoren wie den Datentyp, Authentifizierungsanforderungen und dynamische Inhalte berücksichtigen, die nicht zwischengespeichert werden sollten.

Weitere Techniken zum Schutz von Caching-Mechanismen sind:

  • Cache-Schlüssel normalisieren: Durch die Normalisierung von Cache-Schlüsseln lassen sich Abweichungen aufgrund unterschiedlicher Eingabeformate oder Groß- und Kleinschreibung vermeiden.

  • Nutzereingaben validieren: Strenge Verfahren zur Eingabevalidierung und -bereinigung können Injection-Angriffe verhindern, die zu Cache-Poisoning führen können. Dazu gehören das Filtern von Eingaben, die Verwendung von Parameter-Allowlisting und Prüfungen mit regulären Ausdrücken.

  • Cache-Control-Header: Cache-Control-Header helfen dabei, das Caching-Verhalten durchzusetzen und Risiken zu verringern. Header wie „no-store“ und „no-cache“ können beispielsweise verhindern, dass vertrauliche Daten zwischengespeichert werden.

  • Vertrauen Sie keinen Eingaben von Drittanbietern: Seien Sie vorsichtig, wenn Sie auf Eingaben von Drittanbietern wie Header, Cookies oder Query-Strings zurückgreifen. Validieren und bereinigen Sie alle externen Eingaben gründlich, bevor Sie sie für Caching-Vorgänge verwenden. Behandeln Sie alle von Nutzern bereitgestellten Daten als potenziell schädlich und setzen Sie eine strenge Eingabevalidierung und -filterung ein, um zu verhindern, dass Angreifer gezielt manipulierte Inhalte in den Cache einschleusen.

  • Web Application Firewalls (WAFs) einsetzen: Eine leistungsfähige WAF kann Cache-Poisoning-Versuche erkennen und blockieren. WAFs analysieren eingehende Anfragen und erkennen verdächtige Muster, die auf Cache-Poisoning hindeuten. Sie können die WAF so konfigurieren, dass sie entsprechende Anfragen meldet oder blockiert und so eine zusätzliche Schutzebene gegen solche Angriffe bietet.

Web-Cache-Poisoning-Angriffe überwachen und erkennen

Auch mit den richtigen Gegenmaßnahmen kann es weiterhin zu Web-Cache-Poisoning kommen. Deshalb ist es wichtig, den Web-Traffic regelmäßig zu überwachen und Protokolle zu analysieren, um potenzielle Angriffe zu erkennen. Achten Sie auf ungewöhnliche oder verdächtige Aktivitäten, etwa Anomalien bei Anfrage-Mustern, unerwartete Cache-Varianten oder ungewöhnliche Inhalte, die der Cache ausliefert.

Eine weitere Best Practice sind regelmäßige Sicherheits- und Penetrationstests. Mit diesen Prüfungen lassen sich Schwachstellen erkennen, die Cache-Poisoning-Angriffe ermöglichen können. Zu Sicherheitstests gehören Schwachstellenscans und Sicherheitsaudits. Penetrationstests gehen noch einen Schritt weiter und simulieren realistische Angriffsszenarien. Dabei werden die Techniken und die Denkweise eines Angreifers auf bestimmte Schwachstellen angewendet, die bei regulären Sicherheitstests möglicherweise unentdeckt bleiben.

Zahlreiche Tools und Ressourcen helfen dabei, Web-Cache-Poisoning-Angriffe zu erkennen und zu verhindern. Beispielsweise können wir Folgendes einsetzen:

  • Schwachstellenscanner wie Snyk, mit denen wir häufige Cache-Poisoning-Schwachstellen automatisch erkennen können.

  • Tools zur Cache-Diagnose und -Analyse, mit denen sich Cache-Konfigurationen prüfen, das Cache-Verhalten überwachen und Anomalien erkennen lassen.

Von Entwicklern geschätzt. Von der Security vertraut.

Die Developer-first-Tools von Snyk bieten integrierte und automatisierte Security, die Ihren Governance- und Compliance-Anforderungen gerecht wird.

Zusammenfassung

Web-Cache-Poisoning-Angriffe zwingen Caches dazu, veraltete oder manipulierte Inhalte auszuliefern, ohne dass Nutzerinnen und Nutzer davon wissen. Dies kann zu Datenlecks und Verletzungen der Privatsphäre führen und letztlich dem Ruf einer Website schaden.

Am besten schützen wir uns vor diesen Angriffen, indem wir eine starke Caching-Richtlinie festlegen und uns über die neuesten Sicherheitstrends für Webanwendungen informieren. Außerdem müssen wir bewährte Sicherheitspraktiken befolgen, etwa Eingaben korrekt validieren und unsere Cache-Keys normalisieren.

Wenn wir diese sicheren Entwicklungspraktiken befolgen, können wir die Vorteile des Web-Cachings nutzen und zugleich das Risiko eines vergifteten Caches minimieren.