„Kidnapping“ of mouse clicks to perform actions on another page
The attacker embeds the target website into an absolute positioned iframe:
iframe {
width: 850px;
height: 370px;
position: absolute;
top: -198px;
left: -424px;
/* 50% opacity only for demonstration. */
filter: alpha(opacity=50);
opacity: 0.5;
}
The same page with opacity of the iframe set to 0.
Even multiple steps (e.g. confirmation dialogs) can be bypassed.
.htaccess
or server configuration
<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>
Unintentional execution of (malicious) JavaScript code
<script>alert(1)</script>
If it's possible for an attacker to run this sample code,
any arbitrary JavaScript code can be executed on the page as well
Reflected XSS attacks are often delivered by other websites:
http://example.com/search.php?q=<script>alert(1)</script>
Example for a DOM XSS attack
The text content of the search field is displayed unfiltered on the page.
Even <script>alert(1)</script>
Stored XSS attacks are saved on the server
and then delivered to every visitor of the site.
(Source: 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
removes all HTML tags.
a < b
This may be a valid solution, but it's not 100% perfect.
Obviously not a good idea:
<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()
will use document.implementation.createHTMLDocument()
in the future.
Result: XSS code won't be triggered immediately any more …
X-XSS-Protection: 1; mode=block
But you should never rely exclusively on the browser
Prevent execution of arbitrary scripts
Whitelisting of allowed external sources
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>
Loading/executing the script from evil.com is suppressed:
Starting CSP version 1.1:
frame-ancestors: Which domains are allowed to embed the current site via iframe?
You can specify sources by scheme (data:, https:), hostname (example.com),
fully qualified URI (https://example.com:443) or wildcard (*://*.example.com:*)
Warning: 'unsafe-inline' / 'unsafe-eval'
will execute all
inline scripts, including possible XSS vectors.
jQuery CDN, Google web fonts, Tumblr images, embedded 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>
There is no such thing as total security. You have to stay on guard!
Frederic Hemberger (@fhemberger)