„Entführen“ von Mausklicks auf eine andere Seite
Der Angreifer bindet die Seite in ein absolut positioniertes Iframe ein:
iframe {
width: 850px;
height: 370px;
position: absolute;
top: -198px;
left: -424px;
/* Nur zur Demonstration auf 50% gesetzt. */
filter: alpha(opacity=50);
opacity: 0.5;
}
Die selbe Seite. Transparenz des Iframes auf 0 gesetzt.
Auch mehrstufige Prozesse (z.B. Bestätigunsdialoge)
können so abgefangen werden.
Nur in Firefox 18+/IE9+, wird künftig anders gelöst
.htaccess
oder Server-Konfiguration
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>
web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN"/>
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Ungewolltes Ausführen von fremden JavaScript-Code
<script>alert(1)</script>
Wenn es gelingt, diesen Beispielcode auszuführen, kann
jeder beliebige JavaScript-Code ausgeführt werden
Reflected XSS-Attacken kommen meist von anderen Seiten:
http://example.com/search.php?q=<script>alert(1)</script>
Beispiel für eine DOM XSS-Attacke
Der Text des Suchfelds wird in der Seite ausgegeben. Auch <script>alert(1)</script>
Stored XSS-Attacken werden auf dem Server gespeichert
und an jeden Besucher ausgeliefert.
(Quelle: HTML5 Security Cheatsheet)
<frameset onload=alert(1)>
<body oninput=alert(1)><input autofocus>
<video poster=javascript:alert(1)//></video>
<!--<img src="--><img src=x onerror=alert(1)//">
<img[a][b]src=x[d]onerror[c]=[e]"alert(1)">
/Everybody stand back/
/<[^>]*>?/g
filtert alle HTML-Tags aus.
a < b
Diese Lösung kann sehr hilfreich sein, ist aber nicht 100%ig perfekt.
Leider keine gute Idee:
<scr<script>ipt>alert(1) </sc<script>ri<script>pt>
As seen many times on StackOverflow™
// never, never, NEVER use this!
function stripHtmlWithXss(html) {
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText;
}
// never, never, NEVER use this! (part 2)
function jQueryStripHtmlWithXss(html) {
return $('<div/>').html(html).text();
}
// … or jQuery's own parsing function
$.parseHTML();
// Small change, but a safer solution
function stripHtmlSafe(html) {
var tmp = document.implementation.createHTMLDocument();
tmp.body.innerHTML = html;
return tmp.body.textContent || tmp.body.innerText;
}
$.parseHTML()
künftig mit document.implementation.createHTMLDocument()
Ergebnis: XSS-Code wird nicht mehr direkt getriggert …
X-XSS-Protection: 1; mode=block
Man sollte sich aber keinesfalls ausschließlich darauf verlassen
Ausführen von ungewünschten Scripten verhindern
Einschränkung der zu ladenden Ressourcen
index.html
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery.js"></script>
<script src="http://evil.com/evil.js"></script>
</head>
<body>
…
</body>
</html>
.htaccess
<IfModule mod_headers.c>
Header always set Content-Security-Policy: ↩
"script-src 'self' http://code.jquery.com"
</IfModule>
Laden des Codes von evil.com wird unterbunden:
Ab CSP Version 1.1:
frame-ancestors: Welche Domains dürfen die Seite per iframe einbetten?
Oder Angaben nach Schema (data:, https:), Hostname (example.com),
URI (https://example.com:443) oder Wildcard (*://*.example.com:*)
Vorsicht: 'unsafe-inline' / 'unsafe-eval'
führen alle
Inline-Scripte aus, auch mögliche XSS-Vektoren.
Das volle Programm: jQuery-CDN, Google Webfonts, Tumblr-Bilder, Youtube-Videos
<IfModule mod_headers.c>
Header always set Content-Security-Policy: ↩
"script-src 'self' code.jquery.com; ↩
style-src 'self' http://fonts.googleapis.com; ↩
font-src http://themes.googleusercontent.com; ↩
img-src 'self' data: https://*.media.tumblr.com; ↩
frame-src www.youtube.com; ↩
object-src 'none'"
</IfModule>
Es gibt keine 100%ige Sicherheit. Bleibt auf der Hut!
Frederic Hemberger (@fhemberger)