CSRF attack vector with Ajax serialization

Web 2.0 applications are increasingly at risk to cross-site request forgery (CSRF) attacks. Shreeraj Shah explains what those risks are and how you can prevent such attacks.

Cross-site request forgery (CSRF) is a commonly observed security issue in Web applications, and it can be exploited by an attacker or by a worm. Exploitation of this bug is very easy given there are several HTML tags and embedded JavaScript code snippets that can be leveraged by the browser to initiate a forged request without the consent or knowledge of an end user.

This request hits the vulnerable Web application like a cruise missile charged with the end user's session identity and the attacker's objective is achieved. This objective may be a request for a change of password, performing a financial transaction or sending forged email. A vulnerable Web 2.0 application can be susceptible to such an attack. With Web 2.0, another dimension is being added to this attack vector -- the blissfully unaware end user.

Ajax and remote calls with object serialization
Web 2.0 applications run with Ajax and Web services where developers deploy back-end objects that can be invoked from the browser. These objects can be invoked in different ways: sending SOAP requests, using XML-RPC calls or JSON streams. Once these objects are deployed on the Web server, developers can call them using different scripting languages from the browser itself and repaint the DOM as required.

The request going from browser to Web server for object access sends session information in the form of cookies. Prior to serving the request, the remote call object needs to check the request for credentials and other related aspects such as content type (MIME). This information resides in the HTTP header, whereas the data stream would be a part of the buffer. The key question from a security perspective is -- Can the browser be forced to generate one of these object serialization requests? Let's look at this in more detail.

Ajax making an XML-RPC call
Let's take the simple example of an online stock broking Web 2.0 application. The application requires a user to authenticate on the site prior to doing online transactions from the application. Figure 1.0 illustrates a simple form that is required to be completed by the user to place an order for a "purchase" transaction. An Ajax call for back-end XML-RPC is made once the "buy" button is clicked.

Figure 1.0: XML-RPC call for "buy" transaction

As you can see from the above HTTP request, the cookie is sent to the server with an XML-RPC call using JavaScript and Ajax, as shown below.

It is interesting to note that Ajax has sent "Content-Type: application/xml" to the server to allow the server to make decisions on the basis of "Content-Type". The application responds with the following XML block for the above XML-RPC call.

It is clear that by having the right session in place, the order is executed using XML-RPC. The next task is to check for CSRF vulnerability by making the same call from the browser.

Forcing the browser to generate an XML-RPC call – leads to CSRF
We need to make a POST request from the browser and pass an XML stream into the buffer. It is possible to craft the form in such a way as to build a possible XML-RPC call. Here is a sample HTML page that would send an almost similar request to the application from a different domain than the one hosting this particular page.

These are the observations from the form being submitted:

  1. ENCTYPE is set to "text/plain" because we need to pass the right XML block.

  2. A hidden input parameter is created and its "name" is set to
    "<xml version". [See Figure 2.0].
    name="<?xml version"

  3. The string "=" is dropped from the XML-RPC block, and the remaining block is set as "value" to the input tag. When the browser sends this request it will embed "=" into it and complete the entire envelope as shown in Figure 2.0.

    Note: Value is set with a single quote.

    Figure 2.0: Dissecting a form's hidden input

  4. The form is submitted automatically with JavaScript, i.e. no user intervention is required. It is also possible to hide this form in an iframe with zero width and length.

    When the user visits this page, the following request would be generated automatically from the browser and sent to the application:

As is evident, we were able to generate a similar request from within the browser by using the right session information. An XML-RPC block is also in place. The only major difference between this request and the previous one is "Content-Type" ("text/plain" in this case). If the back-end Web service or its engine fails to validate the MIME type for incoming requests, this call would be successful as shown in Figure 3.0.

Figure 3.0: Browser is redirected to the target site with POST XML content

Note also that before the end user has realized it, this call has actually placed an order. Hence, CSRF is possible using different Ajax streams. This case study uses XML-RPC calls, but it is also possible to replicate this behavior with JSON and SOAP. It all depends on how Web services are written and what kind of MIME checks are set on the application engine.

It is important to have the right MIME checks in place to protect your Web services from CSRF attacks. Future versions of the browser may support XForms that generate XML requests as well. Ultimately, it all comes down to two things: a check for "Referer" and adding extra security tokens for critical forms to guard against these attacks in the Web 2.0 framework.

With Web browsers taking advantage of numerous JavaScript libraries and applications running with different end points, the current XSS and CSRF attack vector versions are made even more powerful.

About the author: Shreeraj Shah is the founder of Net Square, a technology-based security services organization.

This was first published in December 2006

Dig deeper on Internet Application Security



Enjoy the benefits of Pro+ membership, learn more and join.



Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to: