Zum Inhalt springen

Clickjacking

CWE-1021OWASP A05:2021Aktualisiert 4. September 20265 Min. Lesezeit

Beim Clickjacking lädt ein Angreifer Ihre Anwendung unsichtbar in einen Frame auf seiner eigenen Seite und legt seine eigenen Schaltflächen darüber. Das Opfer glaubt, auf der Seite des Angreifers zu klicken, betätigt in Wirklichkeit aber eine Schaltfläche in Ihrer Anwendung, in der es noch angemeldet ist. Die Aktion läuft mit allen Rechten dieses Nutzers.

Die meisten Angriffe drehen sich um Eingaben, denen eine Anwendung zu Unrecht vertraut. Clickjacking funktioniert anders: Der Angreifer missbraucht nicht Ihren Code, sondern die Augen Ihres Nutzers. Im Folgenden lesen Sie, wie ein unsichtbarer Frame einen Klick umlenken kann, warum alte JavaScript-Tricks dagegen nicht helfen und mit welchen zwei Headern Sie das Problem in einem Zug schließen.

Was ist Clickjacking?

Clickjacking ist ein Angriff, bei dem jemand Ihre Anwendung in einem Frame auf seiner eigenen Seite lädt, diesen Frame nahezu durchsichtig macht und sein eigenes Layout darüberlegt. Der Nutzer sieht die Seite des Angreifers, seine Mausklicks und Tastenanschläge landen aber in Ihrer Anwendung, in der er nach wie vor angemeldet ist.

Stellen Sie sich eine Glasplatte mit einer aufgezeichneten Schaltfläche vor, die genau über die Taste eines Geldautomaten gelegt wird. Sie sehen “Kontostand abfragen”, Sie drücken auf das, was Sie für diese Taste halten, doch Ihr Finger bedient in Wirklichkeit die darunterliegende Taste “Bargeld auszahlen”. Das Gerät macht nichts falsch: Es registriert einen echten Tastendruck eines echten Kunden. Die Täuschung liegt vollständig in der Schicht dazwischen.

Genau deshalb ist Clickjacking für Nutzer so schwer zu erkennen. Es wird kein Passwort gestohlen, es läuft kein schädliches Skript auf Ihrer Domain, und die Sitzung ist völlig legitim. Der Angreifer steuert lediglich, wo der Klick ankommt.

Wie funktioniert ein Clickjacking-Angriff?

Der Angriff besteht aus zwei Schichten, die exakt übereinander positioniert werden. Unten liegt Ihre Anwendung in einem iframe, so skaliert und verschoben, dass die gewünschte Schaltfläche unter dem Mauszeiger des Opfers liegt. Darüber liegt die Köderseite mit einem attraktiven Anlass, genau dort zu klicken.

Verwundbar:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: no-store

Diese Antwort trifft keinerlei Aussage darüber, wer die Seite einbetten darf. Jede beliebige Website im Internet darf diese Anwendung also in einen Frame setzen, und der Browser spielt bereitwillig mit. Mehr braucht ein Angreifer nicht:

<!-- Auf der Seite des Angreifers -->
<style>
  iframe {
    position: absolute; top: -180px; left: -420px;
    width: 1200px; height: 900px;
    opacity: 0.02;            /* praktisch unsichtbar, aber klickbar */
    border: 0;
  }
  .koeder { position: absolute; top: 320px; left: 300px; z-index: -1; }
</style>

<div class="koeder">
  <h1>Sie haben einen Preis gewonnen</h1>
  <button>Abholen</button>
</div>

<iframe src="https://portal.example/einstellungen/administratoren"></iframe>

Der Frame liegt oben, ist nahezu durchsichtig und fängt dadurch den Klick ab; der Ködertext liegt darunter und ist reine Dekoration. Klickt das Opfer auf “Abholen”, trifft der Mauszeiger in Wirklichkeit die Schaltfläche “Administrator hinzufügen” im eingebetteten Portal. Das Session-Cookie geht automatisch mit, die Anfrage stammt vom Nutzer selbst, und Ihr Server sieht einen völlig normalen Vorgang.

Sicher:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY

Mit frame-ancestors 'none' weigert sich der Browser, die Seite in irgendeinem Frame darzustellen; der leere oder blockierte Frame macht den Angriff nutzlos. Die Zeile X-Frame-Options: DENY sagt dasselbe in der älteren, breiter unterstützten Form und dient als Auffangnetz für veraltete Browser und Webviews. Betten Sie eigene Seiten ein, etwa in einem Portal, verwenden Sie frame-ancestors 'self' beziehungsweise SAMEORIGIN. Muss ein bestimmter Partner einbetten, benennen Sie ihn ausdrücklich mit frame-ancestors https://partner.example und niemals mit einem Platzhalter.

Senden Sie diese Header mit jeder Antwort mit, nicht nur mit der Anmeldeseite. Angreifer wählen gezielt die tiefer liegenden Masken: einen Bestätigungsdialog, eine Seite zur Rechteverwaltung oder einen Zahlungsschritt. Ein einziger Endpunkt ohne Frame-Schutz genügt, um die gesamte Maßnahme zu umgehen.

Welche Auswirkungen hat Clickjacking?

Der Schweregrad hängt vollständig davon ab, was sich mit einem einzigen Klick erreichen lässt. Auf einer reinen Informationsseite ist die Wirkung vernachlässigbar und der Befund bleibt niedrig. Sobald die Anwendung Vorgänge kennt, die sich in einer Bewegung abschließen lassen, verschiebt sich das Bild: ein Konto löschen, eine Zahlung bestätigen, eine Verbindung zu einem externen Dienst genehmigen oder jemandem Administratorrechte erteilen.

Clickjacking wird gefährlicher, je effizienter Ihre Oberfläche gestaltet ist. Gerade die Schaltfläche, die etwas “mit einem Klick” erledigt, ist die Schaltfläche, die ein Angreifer unter den Mauszeiger des Opfers bringen möchte. Eine Variante davon, mitunter Likejacking oder Cursorjacking genannt, nutzt dieselbe Technik, um Ziehbewegungen oder Tastenanschläge abzufangen, womit auch ausgefüllte Formulare in Reichweite geraten.

Eines sollte man sich klarmachen: Das Opfer bemerkt nichts, und Ihre Protokolle ebenso wenig. Im Audit-Trail steht ein gewöhnlicher Nutzer, der eine gewöhnliche Schaltfläche betätigt. Das erschwert die spätere Untersuchung und macht Missbrauch schwer nachweisbar.

Wie spürt man Clickjacking auf?

Die erste Prüfung ist trivial: Eine Seite abrufen und schauen, ob die Antwort eine Content-Security-Policy mit frame-ancestors oder ein X-Frame-Options enthält. Fehlen beide, ist die Seite grundsätzlich einbettbar. Ein Tester bestätigt das anschließend mit einer eigenen HTML-Datei, die die Seite in einem iframe lädt: Erscheint die Anwendung einfach, ist die Schwachstelle nachgewiesen.

Danach beginnt die eigentliche Arbeit, denn die interessanten Fragen sind feiner. Gilt der Header auf allen Routen oder nur auf der Startseite? Wird er auch bei Fehlerseiten und bei Antworten aus einem Cache oder CDN mitgesendet? Steht dort womöglich ein veralteter ALLOW-FROM-Wert, den kein moderner Browser mehr beachtet? Und ist der Schutz versehentlich für eine Subdomain abgeschaltet, die sehr wohl sensible Funktionen anbietet? AssistSec geht bei einem Penetrationstest den vollständigen Routenbaum durch statt einer einzelnen Stichprobe und beurteilt zusätzlich, welche Vorgänge in der Anwendung mit einem Klick unumkehrbar sind, denn das entscheidet, ob der Befund niedrig oder mittelschwer ausfällt.

Wie verhindert man Clickjacking?

  • Senden Sie bei jeder HTTP-Antwort eine Content-Security-Policy mit ausdrücklicher frame-ancestors-Direktive: 'none', wenn Sie nie eingebettet werden, 'self', wenn Sie nur sich selbst einbetten.
  • Ergänzen Sie X-Frame-Options: DENY oder SAMEORIGIN als Auffangnetz für ältere Browser und Webviews.
  • Benennen Sie erlaubte Einbettende stets ausdrücklich und verwenden Sie nie einen Platzhalter in frame-ancestors.
  • Regeln Sie die Header zentral im Webserver, Reverse Proxy oder in der Middleware, damit neue Routen sie automatisch übernehmen.
  • Verlassen Sie sich nicht auf JavaScript-Framebuster; das sandbox-Attribut am iframe schaltet sie mühelos ab.
  • Verlangen Sie bei unumkehrbaren oder sensiblen Vorgängen eine zweite, bewusste Bestätigung, etwa die erneute Eingabe des Passworts.
  • Prüfen Sie, ob auch Fehlerseiten, Weiterleitungen und Antworten aus Ihrem CDN die Header mitsenden.

Quellen

Häufige Fragen

Wird X-Frame-Options neben einer CSP noch benötigt?

Für moderne Browser ist frame-ancestors in der Content Security Policy maßgeblich und setzt sich sogar gegen X-Frame-Options durch, wenn beide vorhanden sind. Dennoch ist es sinnvoll, beide mitzusenden, da ältere Browser und manche eingebetteten Webviews frame-ancestors nicht kennen und auf den älteren Header zurückfallen.

Warum funktionieren JavaScript-Framebuster nicht mehr?

Framebuster, also Skripte, die prüfen, ob die Seite in einem Frame steckt, wurden jahrelang eingesetzt, lassen sich aber mit dem sandbox-Attribut am iframe umgehen, das die Skripte der eingebetteten Seite schlicht abschaltet. Eine Verteidigung, die der Angreifer ausschalten kann, ist keine Verteidigung; zuverlässig wirkt nur ein HTTP-Header.

Ist Clickjacking auch ohne sensible Schaltflächen ernst?

Dann bleibt die Auswirkung begrenzt, weshalb der Befund häufig als niedrig bewertet wird. Der Schweregrad hängt vollständig davon ab, was sich mit einem einzigen Klick erreichen lässt: eine Schaltfläche zum Löschen des Kontos, eine Zahlungsbestätigung oder die Vergabe von Rechten macht dieselbe Schwachstelle mittelschwer bis hoch.

Schützt ein CSRF-Token vor Clickjacking?

Nein. Beim Clickjacking klickt der echte Nutzer in Ihrer echten Seite, das CSRF-Token wird also ordnungsgemäß mitgesendet, denn es handelt sich um Ihr eigenes Formular. CSRF-Token und Frame-Schutz decken unterschiedliche Angriffe ab und ersetzen einander nicht.

Verwandte Artikel

Zum Suchen / drücken · Esc