Thursday 2 August 2007

GWT Security Concerns - Object Injection

GWT opens a new way of building webapps with it's different AJAX development method(ology) and it also opens a new area of "hackable" software.

I will term this new area "Object Injection".

GWT makes the AJAX development easier as the code is written in a type safe language (Java) and "compiled" out to JavaScript, dealing with all the browser inconsistencies and nuances behind the scenes. You still have the ability to write JavaScript via a Java Native Interface (JNI) and "look and feel" is done through CSS.

The process of writing a GWT web application is to write your GUI web interface or just parts of it in Java , and using the GWT compiler (a java app) compile your Java to JavaScript.

What the GWT does, is trawls your code and converts what it finds to JavaScript. So if you use ObjectA as a POJO to make changes to a Drop Down Select Box (for example) then this ObjectA will be exposed (someway) as JavaScript.

One of the niceties that the GWT Java-to-JavaScript model brings up is that your direct domain model objects can be worked on at the front interface without the need of DTOs, a code/time saving benefit.

So .. code might look something like (simplified by not showing the Asyn Callback()

MyDomainObejct obj = finder.findDOByID(myId);
myTextBox.setText(obj.getName());

Now this code above would be compiled to JavaScript and, even with the GWT J2JS compiler set to "DETAILED" and not OBF(USCATED)" you get some pretty hefty JavaScript.

This is some real JavaScript from the GWT in Detailed Mode, showing a "BusinessEntity" object. (a POJO if you like)

function pkg_BusinessEntity(){
}

_ = pkg_BusinessEntity.prototype = new java_lang_Object();
_.java_lang_Object_typeName = package_pkg_ + 'BusinessEntity';
_.java_lang_Object_typeId = 4;
_.pkg_BusinessEntity_abn = null;
_.pkg_BusinessEntity_commencementDate = null;
_.pkg_BusinessEntity_isCurrent = false;
_.pkg_BusinessEntity_isRegisteredForGST = false;
_.pkg_BusinessEntity_name = null;
_.pkg_BusinessEntity_postcode = null;
_.pkg_BusinessEntity_registeredState = null;

So, where is the security concern ?

Well in some cases, such as most of my world, the domain model is fairly significant, with trading / transaction objects and user accounts with passwords, and money and settings etc etc.

So if, in a GWT class, someone were simply to expose the DAO (Data Access Object) service such as

service.storeObject(myUserObject);

Then, essentially we have, assuming there is no or not sufficient checks, a direct way to store objects into the domain (database) from the browser.

I will call this "Object Injection" in the same vain as "SQL Injection". An Object injection hole is could really be termed as a

Poorly Coded RPC interface which does not check values and who and why of what it is "doing".

Of course, finding an Object Injection hole in a GWT application is going to prove fairly complex to do (but surely not as hard as searching for a buffer over/under run). The types of tasks that a would-be inquisitive person might have to do is as follows.

  1. De-Obfuscate the javascript to find the "meaningful" objects that are being worked with
  2. Dump out all the "Service" methods and try and tie these to where they are being used in the GUI (Web Application).
  3. Identify the types of objects which would provide benefit of "changing", such as Bank Accounts, Limits, restrcitions, user account saving (like storing settings etc) and locate how the interface is working with the RPC method calls
  4. Write some Javascript to create a generated GWT object .. and send it to the RPC API.
The code that you write in Java to be compiled to JavaScript, is now available for all to see.
Anything you do, can be repeated, out of step with simple JavaScript calls.

If parts of the domain model are exposed, this is a good place to start hacking.

The problem is no different with current non-GWT AJAX development. It is just that GWT does a lot of smoke and mirror compiling for you and if you unwittingly create holes in your Java RPC methods (without sufficient checks), then those holes are exposed for all to see (and play with).

So what techniques can we use to prevent us making such a holes. The following would be my quick and dirty set of rules.

1. Don't expose the domain model to the GWT compiler.

Why ? Well for a few reasons

(a) It will expose your internal workings of the application to the browser, and this is one place where the would-be nefarious person can start looking to analyse your application to understand its structure, thus weaknesses. You might think, "Gee, that's a lot of work when this JavaScript is obfuscated", but think for a second, is there anywhere in you application that one can profit (monetarily or otherwise) from your application, giving them an incentive to start the work ?

(b) To expose a Domain Model Object, means you probably want to "change" and store it, which means the DAO service (or similar) will have to take an object and save it to the database. Simply, find that DAO Service and the right object that it requires, and I can then start poking in (Object Injection) other object values to see if I change some stuff at the server.

2. Have Users / Accounts and Password - and Audit them
If you use usernames/passwords and sufficient checks in the right places you will have the ability to log who is doing what. Another way to think of this is, minimise the amount of GWT you use to people who are not authenticated against your application.

A way that I always achieve this these days is to use Acgei Security with Spring and webfilters over the whole application. This way I know which users are hitting which RPC methods and could audit appropriately.

3. Expose ONLY that which needs to be - Use DTO's, simple APIs, push "work" to the server, Separate Projects.

Use DTO's to push and pull your data back and forth. This way you can check the DTO values before storing and also know what is being exposed at the front end.

Use Simple API's - Make you RPC methods simple (ie, don't push too much back and forth). This is probably just a KISS principal and will help in making sure you don't inadvertantly expose that which shouldn't be.

Move as much logic as you can to the server. This ties in with the previous point. A simple API logically means that the complex stuff is on the server. This way, code which does not need to be seen, is not seen. Plus the burden on the browser *our unknown environment* is kept at a minimum (which has an added bonus because we don't want the help desk of our application getting complain calls saying the application slows down their browser thus tarnishing the "company".)

Separate Projects - One method I am using in my GWT apps is to have a separate project for GWT compiled code, for server (RPC and JSPs etc) and business / domain model. I use Maven 2 and a parent project compiles and assembles all 3 pieces together. So three projects, but ONLY one is the GWT compiled code, so I know that, anything potentially that goes in this client project, is going to be in JavaScript. Anything OUTSIDE that project, is hidden from the browser.

4. Secure all RPC interfaces
Use Aspects or Filters (I use Acegi Security) to secure your GWT RPC methods. You will be able to lock down the method calls to the user and also ensure that the "objects" are allowed to be transported that are.

I hope this little entry helps people see the potential issues and raise awareness in their designs about this potential security "feature".

It is nothing new, of course, but the way in which GWT development is done, can have an impact on the "bad applications" we write if we are not careful.

Current 5 booksmarks @ del.icio.us/pefdus