XSRF/CSRF and GWT RPC- Cross site request forgery and Google web toolkit

May 30th, 2010 Alex Moffat

This is a minimal set of changes to protect existing GWT 2.0.3 RPC methods from CSRF (aka XSRF) attacks. GWT 2.0.3 has two different RPC mechanisms, the orignal one, and the new direct-eval RPC implementation. I’m going to talk mostly about the orignal RPC mechanism.

There are two parts to the protection. The first relies on the difficulty of setting a header on an HTTP request made from the browser. The only way to add a header to a request via JavaScript is to use an XMLHttpRequest. If you make a simple GET or POST request from a form element or a GET request using an img element or similar you can not modify the headers sent with the request. Access to the XMLHttpRequest is protected by the same origin policy. This means that simply setting a non standard header on the request and then checking on the server that it is present protects against CSRF done via JavaScript because the code setting the header must have been loaded from the server receiving the request. In GWT 2 custom headers are already set on the client for all RPC requests and are checked by the direct-eval RPC RpcServlet, so this protection already exists for direct-eval RPC calls. The only change needed is to add the check to the RemoteServiceServlet. If you look at the source for the doFinish method in the RpcRequestBuilder class you’ll see that two headers, X-GWT-Permutation and X-GWT-Module-Base are added to all XMLHttpRequest RPC calls.


  protected void doFinish(RequestBuilder rb) {
    rb.setHeader(STRONG_NAME_HEADER, GWT.getPermutationStrongName());
    rb.setHeader(MODULE_BASE_HEADER, GWT.getModuleBaseURL());
  }

RpcRequestBuilder is used on the client by both the original and direct-eval RPC mechanisms. The servlet for the server side of the direct-eval RPC is called RpcServlet and if you look at the source for the getClientOracle method you can see


    String permutationStrongName = getPermutationStrongName();
    if (permutationStrongName == null) {
      throw new SecurityException(
          "Blocked request without GWT permutation header (CSRF attack?)");
    }

To add the same protection to the original RPC mechanism you need to add a similar check to the subclasses of RemoteServiceServlet you implement. I use a common subclass of RemoteServiceServlet as a superclass for all my remote service implementations so in that class I overrode the onBeforeRequestDeserialized method to add a check.


@Override
    protected void onBeforeRequestDeserialized(String serializedRequest) {
        String permutationStrongName = getPermutationStrongName();
        if (permutationStrongName == null) {
            throw new SecurityException(
                 "Blocked request without GWT permutation header (CSRF attack?)");
        }
    }

This change will protect against CSRF attacks made from JavaScript. However, there are apparently ways to set headers from Flash that open a window of vulnerability. There’s more information available about other non JavaScript request mechanisms in part two of the Browser Security Handbook. To protect against this I add another header to the request, this one containing the value of the JSESSIONID cookie, which is accessible on the server as the session id. A cookie value is only accessible to code loaded from the server that set the cookie so checking on the server that the value passed from the client is correct protects against attack by non-javascript mechanisms, provided of course they, and the browser they are using, obey the same origin policy for cookies.

Implementing this second protection requires more work. On the server the principle is the same, retrieve the header value and check it, though you have to handle missing sessions and sessions that have just been created and the client isn’t aware of yet. The example code below would work in the onBeforeRequestDeserialize method.


        HttpServletRequest servletRequest = getThreadLocalRequest();
        HttpSession session = servletRequest.getSession(false);
        // If there is currently no session or if the client doesn't know about it yet then don't check.
        // Otherwise the client must provide the id of the session in a header.
        if (session != null && !session.isNew()) {
            String sessionId = servletRequest.getHeader(SESSION_HEADER);
            if (sessionId == null || !sessionId.equals(servletRequest.getSession().getId())) {
                throw new SecurityException(
                    "Blocked request without session header (CSRF attack?)"));
            }
        }

On the client you have to go to more effort to be able to set an additional header, specifically you need to subclass RpcRequestBuilder and then use your subclass when creating your remote service implementation. For example if the subclass is SubRpcRequestBuilder then the code below creates and configures SomeService correctly.


  SomeServiceAsync svc = (SomeServiceAsync)GWT.create(SomeService.class);
  ((ServiceDefTarget) svc).setRpcRequestBuilder(new SubRpcRequestBuilder());

In SubRpcRequestBuilder you can access the JSESSION id cookie and set the session header in an override of the doFinish method


     String sessionId = Cookies.getCookie("JSESSIONID");
     if (sessionId != null) {
         rb.setHeader(SESSION_HEADER, sessionId);
     }

I’m interested if anyone has any suggestions for further security enhancements or holes I’ve overlooked.

Posted in EffectiveGWT, GWT | 8 Comments »

Expanded multi-touch example

May 10th, 2010 Alex Moffat

I’ve done some more work on my multi-touch example hosted at touchexample.appspot.com. As well as working with the fingers on the iPad/Pod/Phone it also works on Safari, Chrome and Firefox with the mouse. There is little code difference between the different implementations, it’s mostly hidden behind some GWT.create calls so that the majority of the code works with drag events. You can drag and drop the squares into various locations. As you drag a square the others nudge slightly horizontally or vertically to indicate where the dragged square will go if you drop it.

A few things I found interesting, or problems I ran into.

1. Knowing what to do with multi-touch is harder than writing the code to support it and multi-touch drag and drop is going to be hard to do well. When you have only one object moving around it’s fairly simple to work out how to move the rest of the objects on the screen in response. Multiple moving objects make this much more difficult. At the moment though you can drag multiple things at once in touchexample the rest of the animation really only works for one. It is likely the case that just because you can support multiple drags at once you probably shouldn’t in many cases. Of course the importance of user experience design isn’t really a surprise but it does bear thinking about.

2. On the iPad etc., and even on the iPad simulator, if you rapidly start a drag you’ll see that the dragged square moves correctly but the other squares don’t move out of the way as they should. As far as I can tell the events are being delivered to my code as they should be and the correct dom manipulations are being performed but things just aren’t moving. Move investigation is needed here.

3. Debugging problems like 2. are difficult. For most of the work I was able to use the mouse driven code and GWT dev mode. When you’re debugging on the iPad though I needed to use a logging based approach and stream the data to the server for examination.

4. The extra support for CSS3 that Chrome/Safari provides over Firefox 3.6.n lets you achieve some nice effects very simply. Just compare the way touchexample behaves. The animated motion of the non-dragged objects and the fade in and out of the grid is all done with -webkit-transition CSS properties. It’s very easy to get nice animation with no JavaScript/GWT coding at all.

5. No support for IE yet. I’ve not looked very hard but it’s probably just the canvas I’m using to draw the grid when an item is being dragged.

6. Weird focus artifact on Chrome. A small square to the right of the selected square appears when you put the press the mouse button.

Posted in GWT, Multi-touch | 1 Comment »

Inline GWT serialized data with direct-eval RPC

May 1st, 2010 Alex Moffat

Earlier in the year I wrote about my experiences with using Inline GWT serialized data for reduced page load time. I recently tried out the GWT 2.0 direct-eval RPC implementation to see what impact it had in the same situation. First the numbers and then some information on the implementation. I recorded average deserialization timings and payload size using IE6, IE8, Chrome and Firefox 3.6 for one of the largest example processes I have in Blueprint.

RPC

  IE6     391ms 170kb
  IE8     198ms 170kb
  Chrome   31ms 170kb
  Firefox  80ms 170kb

Direct-eval RPC

  IE6     142ms 301kb
  IE8      95ms 301kb
  Chrome  159ms 301kb
  Firefox  76ms 301kb

As you can see the best saving is about 2 tenths of a second, for IE6, while Chrome is actually about 1 tenth of a second slower, which I was not expecting. The payload size just about doubles, as expected from the GWT documentation. Based on this and the advice in the documentation not to use this experimental code in production yet I decided to stick with our current SerializationPolicy based system.

The code on the client side is the same as when you’re using the previous serialization implementation. GWT.create can create the correct sort of serialization factory because ClientDataService implements the RpcService marker interface instead of RemoteService. In the example code below a ClientDate object is deserialized from a string embedded in the HTML page. The calls to Doings.mark and Doings.measure are to record the time take to do the deserializaton.


    public void loadRepository(String serializedData) {
        SerializationStreamFactory factory = GWT.create(ClientDataService.class);
        try {
            // Decode the data
            Doings.mark("deserialize");
            SerializationStreamReader reader = factory.createStreamReader(serializedData);
            clientData = (ClientData) reader.readObject();
            Doings.measure("deserialize");
        } catch (SerializationException e) {
            ClientRepositoryManager.logError("Error loading the repository!", e);
        }
    }

On the server the code is more complex. The basic idea is the same as I described before in the earlier post, you need to create an instance of some class using information produced at compile time and use that as a parameter to a method to serialize the data. When you’re using direct-eval RPC the class you need an instance of is ClientOracle. Once you’ve got that you can call streamResponseForSuccess on RPC. The example code below serializes a ClientData object.


        ClientData data = /* build data */

        // Encode the data to send to the client
        ClientOracle oracle =
            serviceManager.clientOracleProvider(request).getClientOracleFor(request, page);

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        RPC.streamResponseForSuccess(oracle, os, data);

        String payload = "";
        try {
            payload = os.toString("UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("UnsupportedEncodingException converting json.");
        }

The tricky bit is constructing the ClientOracle and it’s tricky for the same reasons constructing a SerializationPolicy is, you need to use information created at compile time that is normally accessed at run time, and when it’s normally accessed it uses information passed from the client to the server. For direct-eval RPC what you need is the strong name for the permutation that you are going to generate the data for. You can see how this is done if you look at the code for RpcServlet. The data for the ClientOracle is in a file named <strong name>.gwt.rpc. This is in contrast to the SerializationPolicy case where you have a file per RemoteService interface instead of a file per permutation. Unfortunately the permutation is chosen on the client, not on the server, so there is no ready made code to pick the permutation that can be used on the server. You can’t, of course, wait for the client to determine the value because that defeats the whole purpose of this work, avoiding a roundtrip.

My solution uses the symbol maps produced when you pass the -extras flag to the GWT compile. There is one symbol map for each permutation and the name of the symbol map file is <strong name>.symbolMap. The useful thing about the symbol map for my purposes is that at the top of it is information about which values of which deferred binding properties apply to that map. So, by reading the top of the map you can work out which strong name goes with which deferred binding property values. Here’s the first 4 lines from one of the symbol map files. This one is for the permutation used by ie6.

  # { 0 }
  # { 'user.agent' : 'ie6' }
  # jsName, jsniIdent, className, memberName, sourceUri, sourceLine
  KMf,,boolean[],,Unknown,0

As part of the build process I create a mapping from property values to strong name and record this in a file. Then, if you can calculate the values of the binding properties on the server for a particular request, you can choose the correct strong name value and therefore pick the correct .gwt.rpc file. As part of the application initialization a client oracle provider object is configured with the information from the file. When a ClientOracle is requested at runtime the correct property values are calculated from the incoming HTTP request and the appropriate ClientOracle is returned. Caching is used as a single oracle can serve multiple threads.

Posted in EffectiveGWT, GWT | 2 Comments »