Monthly Archives: May 2015

Abusing JavaScript Inclusions to Leak Sensitive Data Across Domains

For our upcoming paper, The Unexpected Dangers of Dynamic JavaScript (PDF here), we analyzed a lesser-known vulnerability which is caused by the handling of cross-origin JavaScript in the browser. While normally, access to data which is hosted by an external site is prohibited by the Same-Origin Policy, the inclusion of third-party content is intentionally possible (think about including jQuery from their CDN). In this post, we will describe the problem and discuss some of the results of our study.

Cross-Origin Script Inclusion

As stated before, the inclusion of script content is somewhat exempt from the protection of the Same-Origin Policy. While a script running at attacker.com may not gain access to the content of any files located on victim.com (given that victim.com does not use CORS), it may include a script which is hosted on said domain. Whenever a script is included from a third-party site, it inherits the origin of the including page, i.e., gains full access to the including page’s DOM and JavaScript global object, but more importantly, registers all its own global variables in the context of the including page. Important to note in this instance is the fact that when the browser conducts the corresponding request to victim.com, it also sends all cookies belonging to victim.com. That means, if the user is logged in to that site and the content of the script is generated on-the-fly depending on the specific user (identified by his cookies), the response may leak sensitive information.

We consider the following example, which is derived from a real-world vulnerability we discovered in our study.

// located at http://victim.com/get_session_information.js
var username="ben";
var sessionid="10265ed845634413e490432d951d00f0";

In this case, the intention is to register the username and the sessionid for an application which is hosted by victim.com. This script, however, is not properly protected against inclusion from another domain. Therefore, the attacker simply puts the following snippet into his Web page, resulting in the victim’s browser conducted an authenticated request towards the target domain.

<script>
function leaked() {
  alert("I know your sessionid for victim.com: " + sessionid);
}
</script>
<script src="http://victim.com/get_session_information.js" onload="leaked"></script>

This way, if the victim visiting attacker.com is currently logged in to victim.com, the attacker will be able to retrieve the sensitive session information and, thus, steal the user’s session.

Our Empirical Study

To gain insight into the actual prevalence of such flaws on the Web, we conducted a study on 150 highly ranked pages which allowed us to register a user account. On a total of 49 domains, we found evidence of dynamic generation of the JavaScript code on the server side, using the provided cookies to identify the user.

In the simplest case, we were only able to identify the Login State of a user, i.e., whether he is logged in to the page or not. While this does not yet leak much information, it might provide a phisher with valuable intel on his target: knowing specifically on which sites a user has accounts increases the chances of a successful phishing attacker. We found that 49 domains had at least one issues related to this information leak.

In addition to the knowledge whether a user actual has an account, we also discovered numerous sites which leaked unique identifiers, such as email addresses or user IDs for a specific site. This allows an attacker to easily track his victim and identify him accordingly. 34 domains in our data set leaked such a unique ID.

Next to these, we found that 15 domains leaked personal data of the victim, such as the full name, date of birth or his location (according to the stored settings for the vulnerable application). Additionally, we found a site which leaked the email senders and subjects of the last 10 emails and another one which allowed to us extract all calendar entries for the victim.

Last, and most interesting, we found that 7 domains actually leaked session information. Among this information were both session IDs to be used with the application as well as CSRF protection tokens, which allowed us to attack the vulnerable application in a second stage. In one case, we could abuse this leaked CSRF token to store a Cross-Site Scripting payload for the victim. That domain also incorporated a login using the Facebook API. The combination of the leaked CSRF token and the XSS flaw (only exploitable due to the leaked CSRF token) allowed to us craft a payload which would steal the Facebook API token. This in turn enabled us to interact with the user’s Facebook account as if we were the actually application, reading personal information and even posting in the name of the victimized user.

Screen Shot 2015-05-26 at 23.57.17Screen Shot 2015-05-26 at 23.58.09

Remedies

This kind of attack is enabled by the fact that the SOP does not apply to script inclusions from remote hosts. If you are an application developers who wants to use such external scripts, extra care must be taken. First and foremost, it is not necessarily a good idea to put user-specific data into scripts with known URLs. As we have shown, this may lead to really weird situations in which your Facebook access is abused by an attacker. If possible, separate your code and data. Data is secure from being in this manner if contained in inline scripts. However, these should not be used as the Content Security Policy forbids them by default (and for a good reason). We therefore propose that the application should only put the code into includable scripts, but never data. Instead, an application should use XmlHttpRequests with CORS to fetch the user-specific data from the server. This mechanism is secure by default and can be configured to allow data access from specified third-party hosts if need be.

Using the Referer header for security is also not a good idea. This header may be stripped by an attacker (see koto’s post on the subject) and then? If you use strict Referer checking, you must decline such a request. However, there are certain proxies which strip the Referer header for privacy reasons. In these cases, the application will certainly break. In our study, we also found a number of sites which conducted Referer checking. However, if we forcefully omitted the header, those sites would serve the content as a fallback, making the application vulnerable again.

If you cannot use a strict separation between code and data, you should fall back to good old CSRF tokens. Not unlike their protection capabilities with respect to CSRF attacks, unguessable tokens as part of the script’s URL stop an attacker from including the correct URL, thus stopping his attack.

Summary

In summary, we found a high number of sites which are susceptible to attacks using dynamically generated JavaScript. The attacks range from simple login oracles, stealing sensitive data such as calendar entries to an XSS attack, enabled by a leaked CSRF token, which allowed us to interact with the victim’s Facebook account. Additionally, we found a session hijacking flaw which enabled us to fully interact with the target application in the name of the user. In a side note, we found a flaw on one bank’s site which enabled an attacker to steal the victim’s credit card information and learn his current account balance.

We are currently in the process of notifying sites of the problems. When the issues have been fixed and the site owners agree, we will provide more in-depth explanations of the exploitable apps and the corresponding proof of concept exploits.