Clickjacking ist seit 2008 dokumentiert und gehört zu den ältesten noch aktiven Web-Angriffs-Klassen. Das Prinzip ist einfach: ein:e Angreifer:in lädt deine Webseite in einem transparenten iframe auf ihrer eigenen Seite, überlagert sie mit eigenen Elementen — und ein Klick, den die Nutzer:in für ihre eigene Aktion hält, löst tatsächlich eine Aktion auf deiner Seite aus. Dieser Artikel zeigt die Varianten, die realen Vorfälle und die zwei Header-Mechanismen, die das Problem strukturell lösen.
Wie Clickjacking technisch funktioniert
Der klassische Aufbau:
- Angreifer:in baut eine eigene Seite (
evil.example) mit harmlosem Inhalt — z. B. einem Spiel oder einem Gewinnspiel. - In diese Seite wird die echte Ziel-Seite (z. B. das Banking-Portal
bank.example) als iframe geladen. - Mit CSS wird der iframe transparent gemacht (
opacity: 0) oder mit eigenen Elementen überlagert, sodass die echte Seite unsichtbar ist, aber klickbar bleibt. - Die Position des iframes wird so gewählt, dass kritische Buttons der Ziel-Seite direkt unter den sichtbaren Buttons der Angreifer-Seite liegen.
- Wer auf den sichtbaren Button klickt, klickt tatsächlich in die unsichtbare iframe-Schicht — und löst die Aktion auf der echten Seite aus.
Voraussetzung: Die Nutzer:in ist auf der Ziel-Seite bereits eingeloggt — sonst hätte der Klick keinen Effekt. Genau das macht Clickjacking gefährlich: es funktioniert genau in den Szenarien, in denen User-Aktionen Wirkung haben.
Beispiel-Demonstration (vereinfacht):
<!-- Angreifer-Seite -->
<html>
<head><style>
.lure-button { position: absolute; top: 200px; left: 100px; }
iframe { position: absolute; top: 0; left: 0; opacity: 0; width: 100%; height: 100%; }
</style></head>
<body>
<h1>Klicke hier, um zu gewinnen!</h1>
<button class="lure-button">JETZT GEWINNEN</button>
<iframe src="https://bank.example/transfer?to=attacker&amount=1000&confirm=yes"></iframe>
</body>
</html>Der „GEWINNEN"-Button überlagert exakt den „Bestätigen"-Button im iframe der Bank-Seite. Klick → Überweisung läuft.
(Hinweis: heute scheitert dieser Angriff bei jeder seriösen Bank an X-Frame-Options oder frame-ancestors. Aber bei kleineren Web-Apps, die diese Header nicht setzen, ist es weiter möglich.)
Die Varianten
Clickjacking ist eine Familie verwandter Angriffe — gemeinsamer Begriff oft UI-Redress.
- Klassisches Clickjacking — wie oben, mit überlagertem Klick auf Buttons.
- Likejacking — verbreitet 2010–2014, Nutzer:innen klicken Facebook-„Like"-Buttons unsichtbar, ohne es zu wollen. Viele Like-Spam-Kampagnen waren so aufgebaut.
- Cursorjacking — Cursor wird visuell verschoben, sodass Klicks woanders landen als die Nutzer:in glaubt.
- Filejacking / Drag-and-Drop-Hijacking — Nutzer:in zieht eine Datei aus ihrem Dateimanager in den sichtbaren Bereich; in Wahrheit landet die Datei in einem Upload-Feld des iframes.
- Keystroke-Hijacking / Strokejacking — Tasten-Eingaben werden in unsichtbare iframes umgeleitet.
- Tap-Jacking auf Mobile — Touch-Events statt Klicks; auf Mobile-Browsern besonders effektiv.
- Cookie-Jacking — eine sehr alte Variante, die ausnutzt, dass Drag-and-Drop in manchen Browsern Cookie-Inhalte transportierbar machen konnte.
Alle haben den gleichen Kern: die Nutzer:in tut etwas anderes als sie glaubt. Der Angriffsweg ist sozial-psychologisch (Visual-Deception), die technische Mechanik ist Browser-Eigenschaft.
Reale Vorfälle
Facebook Likejacking (2010–2014). Massen-Welle: gefälschte „Wow, das musst du sehen"-Posts mit Bild-Link. Klick führte auf eine Seite mit unsichtbarem Facebook-Like-Button. Eine Klick auf irgendwo auf der Seite war ein „Like" — der Post wurde im Profil des/der Nutzer:in geteilt, Welle pflanzte sich fort.
Twitter Worm (2010). Tweet mit unsichtbarem „Retweet"-Button — wer den scheinbar harmlosen Link klickte, retweetete den Wurm-Tweet selbst.
Adobe Flash Webcam-Aktivierung (2008). Sehr früher Vorfall: Flash-Plugin-Einstellungs-Dialog (für Webcam-Zustimmung) wurde in unsichtbaren iframes geladen. Klick auf einer Spiele-Seite aktivierte Webcam.
LinkedIn Email-Erfassung (2013–2014). „CSV importieren"-Funktion mit ungeschütztem iframe — Drag-and-Drop-Hijacking-Variante.
Bug Bounties bis heute. Auch 2024/25 finden Bug-Bounty-Forschende regelmäßig Clickjacking-Funde — meist bei kleineren Apps, gelegentlich auch bei großen, wenn ein neuer Endpunkt vergessen wurde. Der Schaden reicht von Konto-Aktionen (Profil-Änderungen, Friend-Adds) bis zu finanziellen Aktionen (Geldtransfer, Kauf-Bestätigungen).
Schutz 1 — X-Frame-Options
Der klassische Schutz, eingeführt von Microsoft 2009 (IE8), seit Jahren von allen großen Browsern unterstützt.
Drei Werte:
DENY— die Seite darf in keinem iframe geladen werden, egal woher.SAMEORIGIN— die Seite darf nur in iframes der eigenen Origin geladen werden.ALLOW-FROM <uri>— die Seite darf in iframes der angegebenen Origin geladen werden. Veraltet, nicht mehr in modernen Browsern unterstützt — durch CSPframe-ancestorsersetzt.
Setting in Nginx:
add_header X-Frame-Options "SAMEORIGIN" always;Setting in Express:
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
next();
});Setting in Spring (Java):
http.headers(headers -> headers
.frameOptions(frame -> frame.sameOrigin())
);X-Frame-Options ist breit unterstützt (alle Browser seit ca. 2010), funktioniert zuverlässig. Aber:
ALLOW-FROMfür mehrere Domains funktioniert nicht — nur eine Origin pro Header möglich, und das ist veraltet.- Granularität fehlt — entweder alles oder bestimmte Origin. Komplexere Embed-Szenarien sind nicht abbildbar.
Schutz 2 — CSP frame-ancestors
Die moderne Alternative ist die frame-ancestors-Direktive in der Content Security Policy. Sie bietet mehr Flexibilität und ersetzt X-Frame-Options für moderne Browser.
Beispiel-CSP-Header:
Content-Security-Policy: frame-ancestors 'self';
# oder
Content-Security-Policy: frame-ancestors 'none';
# oder mit erlaubten externen Domains
Content-Security-Policy: frame-ancestors 'self' https://partner.example;
# mit Wildcard
Content-Security-Policy: frame-ancestors 'self' *.partner.example;Werte:
'none'— Seite darf in keinen iframe geladen werden.'self'— nur eigene Origin.- Eine oder mehrere Domain-Ausdrücke — bestimmte Origins erlaubt.
Vorteile gegenüber X-Frame-Options:
- Mehrere erlaubte Origins in einem Header.
- Wildcards unterstützt (vorsichtig nutzen).
- Konsistent mit dem Rest der CSP (siehe content-security-policy — Kap 11).
- Zukunftsfähig —
X-Frame-Optionswird langsam zur Legacy.
Praxis-Empfehlung: Beide Header setzen — X-Frame-Options für ältere Browser (auch wenn das immer weniger nötig ist), frame-ancestors für moderne. Wenn beide gesetzt sind und sich widersprechen, gewinnt in modernen Browsern frame-ancestors.
Setting in Nginx:
add_header Content-Security-Policy "frame-ancestors 'self'; default-src 'self'; ..." always;
add_header X-Frame-Options "SAMEORIGIN" always;SameSite-Cookies als Sekundär-Schutz
SameSite-Cookies sind primär eine CSRF-Verteidigung — aber sie wirken auch sekundär gegen Clickjacking-Konsequenzen.
Wenn ein Cookie als SameSite=Lax oder SameSite=Strict markiert ist, wird es bei Cross-Site-Requests in iframes nicht mitgesendet. Selbst wenn ein:e Angreifer:in deine Seite in ein iframe einbettet — der iframe hat keine Session, weil die Cookies fehlen.
Das ist keine vollständige Lösung:
- Wenn der iframe als
SameSite=None(mitSecure) markiert ist, läuft das Cookie weiter mit. - Wenn Aktionen über GET (statt POST) möglich sind, kann
Laxumgangen werden (Browser sendet Cookies bei Top-Level-GET). - Manche Anwendungs-Flows brauchen Cross-Site-Cookies legitim.
Aber: in Kombination mit frame-ancestors ist SameSite=Lax (Browser-Default seit 2020) ein zusätzlicher Schutz-Layer.
JavaScript-basierte Frame-Buster (alte Variante, nicht empfohlen)
Vor dem Aufkommen von X-Frame-Options nutzten Web-Apps JavaScript-Tricks, um aus iframes herauszuspringen:
// Klassischer Frame-Buster (deprecated)
if (top !== self) {
top.location = self.location;
}Diese Ansätze waren über Jahre vielfach umgehbar:
sandbox-Attribut auf iframes deaktiviert das Top-Frame-Schreiben.onbeforeunload-Handler kann Navigations-Versuche abfangen.- Verschachtelte iframes machen die Top-Window-Detection schwer.
Heute ist die einzige zuverlässige Verteidigung HTTP-Header-basiert — X-Frame-Options oder frame-ancestors. Frame-Buster im Code sind nicht mehr empfehlenswert und sollten durch Header ersetzt werden.
Wann darf eine Seite eingebettet sein?
Es gibt legitime Embed-Szenarien:
- YouTube-Videos, die du in deine Seite einbettest — YouTube setzt für die Embed-Variante (
youtube.com/embed/...)X-Frame-Options: ALLOWALL. - Zahlungs-Widgets (Stripe Checkout, PayPal-Buttons) — Anbieter setzen Whitelists.
- Karten-Embeds (Google Maps, OpenStreetMap).
- Marketing-Widgets (Trustpilot, Bewertungs-Plattformen).
- OAuth-Login-Popups — heute primär als Top-Level-Redirects, nicht iframes.
Wann nicht einbettbar:
- Sensible Aktionen — Banking, E-Mail, Cloud-Datei-Verwaltung. Alles, wo ein:e angemeldete:r Nutzer:in eine impactvolle Aktion auslösen könnte.
- Login-Seiten — sollten nie in iframes laden. Stoppt nicht nur Clickjacking, sondern auch transparente Phishing-Overlays.
- Account-Einstellungen, Zahlungs-Methoden.
Default-Empfehlung: Auf einer normalen Web-App ohne spezifischen Embed-Bedarf gehört frame-ancestors 'self' oder frame-ancestors 'none' global gesetzt — dann erst pro-Seite oder pro-Pfad lockern, wo es nötig ist.
Testen
Sehr einfach zu testen, ob deine Seite verwundbar ist:
Manueller Test: Erstelle eine HTML-Datei mit:
<html><body>
<h1>Test</h1>
<iframe src="https://deine-seite.example" width="800" height="600"></iframe>
</body></html>Öffne die Datei lokal im Browser. Wenn deine Seite im iframe sichtbar wird, ist sie verwundbar. Wenn statt dessen eine Fehlermeldung kommt (refused to display ... in a frame because it set "X-Frame-Options" to ...), ist sie geschützt.
Automatisiert:
- securityheaders.com prüft Header inklusive
X-Frame-Optionsundframe-ancestors. - OWASP ZAP hat einen passiven Scanner für fehlende Frame-Schutz-Header.
- Lighthouse-Audit zeigt Hinweise.
Interessantes
Clickjacking war 2008 ein Sensations-Thema
Robert Hansen (RSnake) und Jeremiah Grossman haben den Begriff 2008 geprägt und Adobe-Flash-Webcam-Aktivierung als Demonstration vorgeführt. Eine geplante DEF-CON-Präsentation wurde damals auf Adobes Bitte zurückgehalten — das Thema kam erst nach koordinierter Disclosure heraus.
X-Frame-Options ist offiziell deprecated
Im W3C-Standard ist X-Frame-Options seit Jahren als „obsolete" markiert — frame-ancestors ist die zukünftige Standardlösung. In der Praxis senden viele Sites beide Header, weil ältere Browser-Versionen frame-ancestors nicht kennen. Stand 2026 sind diese Browser sehr selten.
Mobile Tap-Jacking ist weniger erforscht
Auf Smartphones lassen sich Touch-Events ähnlich umleiten — die Forschung dazu ist weniger weit als bei Desktop-Clickjacking. Apple und Google haben WebView-Härtungen, die das meiste verhindern, aber Custom-WebViews in Apps haben gelegentlich Lücken.
OAuth-Flows niemals in iframes
Eine wichtige Konsequenz: OAuth-2.0-Authorization-Endpunkte dürfen nicht in iframes laden. Genau deshalb wird der „Implicit Flow" als unsicher eingestuft — er ermöglicht Embedding-Szenarien. Moderne OAuth 2.1 verlangt Authorization-Code-Flow mit PKCE in Top-Level-Redirects.
frame-ancestors überschreibt X-Frame-Options
Wenn beide Header gesetzt sind und sich widersprechen, gewinnt in modernen Browsern frame-ancestors aus der CSP. Falls deine Site beide setzt, sollten sie konsistent sein — sonst gibt es überraschende Browser-Unterschiede.
Manche WAFs setzen Header automatisch
Cloudflare, AWS CloudFront, Fastly bieten Optionen, fehlende Sicherheits-Header automatisch zu setzen. Praktisch, wenn der Origin-Server sie nicht selbst setzt — aber gefährlich, wenn man darauf vertraut, ohne es zu prüfen.
Bug-Bounty-Reports für Clickjacking sind oft niedrig bewertet
Im Bug-Bounty-Bereich werden reine Clickjacking-Funde meist als Low-Severity bewertet, weil sie Nutzer-Interaktion verlangen und meist nur einzelne Aktionen ermöglichen. Höhere Bewertung gibt es, wenn der Angriff schwere Konsequenzen hat (Konto-Übernahme, finanzielle Aktion) oder mit anderen Schwachstellen verkettet wird.
Weiterführende Ressourcen
Externe Quellen
- OWASP Clickjacking Defense Cheat Sheet
- MDN — X-Frame-Options
- MDN — CSP frame-ancestors
- PortSwigger Web Security Academy — Clickjacking
- securityheaders.com — Header-Test
- W3C — CSP Level 3 Spezifikation
- Context IS — Clickjacking-Historie
Verwandte Artikel
- OWASP Top 10 Übersicht
- Request Smuggling und Host-Header-Injection
- Prototype Pollution
- CSRF und SameSite (Kap 12)
- SameSite-Cookies (Kap 12)
- Click- und Tap-Jacking (Vertiefung CSRF-Kap) (Kap 12)
- Content Security Policy (Kap 11)
- Secure Headers Übersicht (Kap 16)