Unzureichende Beschränkung gerenderter UI-Schichten oder Frames
Beschreibung
Unzureichende Beschränkung gerenderter UI-Schichten oder Frames tritt auf, wenn eine Webanwendung Frame-Objekte oder UI-Schichten, die zu einer anderen Anwendung oder Domain gehören, nicht einschränkt oder falsch einschränkt. Dies ermöglicht "Clickjacking"-Angriffe, bei denen ein Angreifer transparente oder undurchsichtige Frames über legitime UI-Elemente legt und Benutzer dazu verleitet, auf bösartige Inhalte zu klicken, während sie glauben, mit der legitimen Website zu interagieren. Angreifer können dies nutzen, um Anmeldedaten zu stehlen, nicht autorisierte Aktionen durchzuführen oder Benutzer dazu zu bringen, gefährliche Funktionen zu aktivieren.
Risiko
Clickjacking-Angriffe können schwerwiegende Folgen haben, darunter nicht autorisierte Überweisungen, Kompromittierung von Social-Media-Konten, Aktivierung von Webcam/Mikrofon und Malware-Installation durch Drive-by-Downloads. Bemerkenswerte Angriffe zielten auf Facebooks "Gefällt mir"-Button (Likejacking), Twitters "Folgen"-Button und Banking-Anwendungen. Ohne ordnungsgemäße Frame-Einschränkungen kann potenziell jede authentifizierte Aktion, die ein Benutzer durchführen kann, gekapert werden. Moderne Browser haben einige Schutzmaßnahmen implementiert, aber Anwendungen müssen sich dennoch explizit für diese Schutzmaßnahmen entscheiden.
Lösung
Implementieren Sie den X-Frame-Options-Header mit DENY oder SAMEORIGIN. Verwenden Sie die Content-Security-Policy (CSP) frame-ancestors-Direktive für detailliertere Kontrolle. Implementieren Sie Frame-Busting-JavaScript als Verteidigung in der Tiefe (obwohl es umgangen werden kann). Verwenden Sie das SameSite-Cookie-Attribut, um zu verhindern, dass Cookies in gerahmten Kontexten gesendet werden. Implementieren Sie für sensible Operationen zusätzliche Bestätigungsschritte, die nicht durch Clickjacking umgangen werden können (z.B. erneute Authentifizierung, CAPTCHA).
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Nicht autorisierte Aktionen Benutzer führen unwissentlich Aktionen wie Einstellungsänderungen, Käufe oder Berechtigungserteilungen durch. |
| Vertraulichkeit | Bereich: Anmeldedaten-Diebstahl Anmeldeformulare können überlagert werden, um Anmeldedaten zu stehlen. |
| Zugriffskontrolle | Bereich: Berechtigungs-Hijacking Angreifer können Benutzer dazu verleiten, Berechtigungen für Kamera, Mikrofon oder Standort zu erteilen. |
Beispielcode und Lösung
Verwundbarer Code
<!-- VERWUNDBAR: Kein Clickjacking-Schutz -->
<!-- Diese Seite kann in jedem iframe eingebettet werden -->
<!DOCTYPE html>
<html>
<head>
<title>Banking-Überweisung</title>
</head>
<body>
<form action="/transfer" method="POST">
<input type="hidden" name="to" value="angreifer-konto">
<input type="hidden" name="amount" value="10000">
<button type="submit">Hier klicken für einen kostenlosen Preis!</button>
</form>
</body>
</html>
# VERWUNDBAR: Kein X-Frame-Options-Header
from flask import Flask, render_template
@app.route('/settings')
def settings():
# Kein Frame-Schutz - kann eingebettet und per Clickjacking angegriffen werden
return render_template('settings.html')
// VERWUNDBAR: Unwirksames Frame-Busting (kann umgangen werden)
if (top != self) {
top.location = self.location; // Kann durch sandbox-Attribut blockiert werden
}
Sichere Lösung
# SICHER: X-Frame-Options und CSP-Header
from flask import Flask, make_response
@app.after_request
def sicherheits_header_hinzufügen(response):
# Framing komplett verhindern
response.headers['X-Frame-Options'] = 'DENY'
# Oder nur gleiche Herkunft erlauben
# response.headers['X-Frame-Options'] = 'SAMEORIGIN'
# CSP frame-ancestors (flexibler)
response.headers['Content-Security-Policy'] = "frame-ancestors 'none';"
return response
# Für spezifische vertrauenswürdige Domains:
# response.headers['Content-Security-Policy'] = "frame-ancestors 'self' https://trusted.example.com;"
// SICHER: Robustes Frame-Busting mit Sandbox-Erkennung
(function() {
// Prüfen, ob wir in einem Frame sind
if (self !== top) {
// Prüfen, ob wir ausbrechen können
try {
// Versuch, auf Parent zuzugreifen - wirft Fehler bei Cross-Origin
if (top.location.hostname !== self.location.hostname) {
// Wir sind von einer anderen Herkunft gerahmt - umleiten
top.location = self.location;
}
} catch (e) {
// Cross-Origin-Frame erkannt
// Inhalt verstecken und Warnung anzeigen
document.body.innerHTML = '<h1>Dieser Inhalt kann nicht in einem Frame angezeigt werden</h1>';
}
}
})();
// SICHER: Zusätzlicher Schutz für sensible Aktionen
function sensibleAktionAusführen() {
// Erneute Bestätigung erfordern, die nicht durch Clickjacking umgangen werden kann
const bestätigt = prompt('Geben Sie "BESTÄTIGEN" ein, um mit dieser Aktion fortzufahren:');
if (bestätigt !== 'BESTÄTIGEN') {
return false;
}
// Mit Aktion fortfahren
}
<!-- SICHER: Serverseitige Header plus clientseitiger Schutz -->
<!DOCTYPE html>
<html>
<head>
<title>Sichere Seite</title>
<style>
/* Inhalt verstecken bis JS bestätigt, dass wir nicht gerahmt sind */
html { display: none; }
</style>
<script>
if (self === top) {
document.documentElement.style.display = 'block';
} else {
// Gerahmt - Inhalt nicht anzeigen
top.location = self.location;
}
</script>
</head>
<body>
<!-- Inhalt wird nur angezeigt, wenn nicht gerahmt -->
</body>
</html>
// SICHER: Spring Security-Konfiguration
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.frameOptions()
.deny() // X-Frame-Options: DENY
.and()
.contentSecurityPolicy("frame-ancestors 'none';");
}
}
// Oder mit Filter für Nicht-Spring-Anwendungen
@WebFilter("/*")
public class ClickjackingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("X-Frame-Options", "DENY");
response.setHeader("Content-Security-Policy", "frame-ancestors 'none';");
chain.doFilter(req, res);
}
}
Ausgenutzt in der Praxis
Facebook-Likejacking (2010-heute)
Angreifer legen unsichtbare Facebook-"Gefällt mir"-Buttons über verlockende Inhalte und veranlassen Benutzer, unwissentlich Seiten zu liken oder Inhalte zu teilen, die zur Verbreitung von Malware und Betrug verwendet werden.
Twitter-Clickjacking (2009)
Angreifer nutzten Clickjacking, um Twitter-Benutzer dazu zu bringen, Tweets zu posten oder Konten zu folgen, ohne ihr Wissen, wodurch bösartige Links verbreitet wurden.
Adobe Flash Settings Hijacking
Clickjacking-Angriffe zielten auf Adobes Flash-Einstellungsmanager, um Webcam- und Mikrofonzugriff ohne Benutzerkenntnis zu aktivieren.
Tools zum Testen und Ausnutzen
-
Burp Suite Clickbandit - Automatisierter Clickjacking-PoC-Generator.
-
OWASP ZAP - Erkennt fehlende Frame-Schutz-Header.
-
Security Headers - Prüft auf Clickjacking-Schutz-Header.
CVE-Beispiele
-
CVE-2015-1241 - Google Chrome Tap-Jacking-Schwachstelle.
-
CVE-2017-7089 - Safari UI-Spoofing über Clickjacking.
-
CVE-2021-21224 - Chrome Type Confusion ermöglicht Clickjacking.
Referenzen
-
MITRE Corporation. "CWE-1021: Improper Restriction of Rendered UI Layers or Frames." https://cwe.mitre.org/data/definitions/1021.html
-
OWASP. "Clickjacking Defense Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
-
MDN Web Docs. "X-Frame-Options." https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options