Search
RSS Feed
Twitter

Entries in GWT (3)

Tuesday
Jul202010

GWTEnum: Enumerating GWT-RPC Method Calls

Google Web Toolkit (GWT) applications do not provide a straight forward way to enumerate all services and method calls. By default, GWT obfuscates client-side Javascript code which, as a tester, prevents one from being able to easily enumerate GWT-RPC method calls. Most pen testers typically limit testing to only the method calls that can be captured while crawling the application.

Using a technique described by Sripathi Krishnan, one can programmatically de-obfuscate GWT’s Javascript files in order to enumerate all of the exposed method calls. This typically leads to the discovery of vulnerable un-used or administrative methods that may not normally be seen during normal application use. It is worth noting that this technique can usually be performed anonymously, potentially leaving a GWT application open to attack if authentication and authorization checks are not properly performed. What follows is a short walkthrough of Krishnan’s enumeration technique along with a tool that I wrote to automate the process.

De-obfuscating the Javascript

First, it is worth noting that not all GWT applications you will encounter will be obfuscated. GWT applications can be compiled in one of the following three modes:

  • Obfuscated: Javascript is obfuscated and minified to reduce the size of the generated files. This is the default compilation mode for GWT applications.
  • Pretty: Generated Javascript is human readable
  • Detailed: Javascript code contains even more detail, such as verbose variable names.

When a GWT application first loads in the browser, the main entry page will typically call a Javascript file with the “.nocache.js” suffix. This file is responsible in detecting the browser type and loading the correct browser-specific Javascript code for the GWT application. Most of the core GWT client logic is kept inside files with the “.cache.html” suffix. These are ultimately the files we are most interested in since they also contain the logic responsible for invoking GWT-RPC calls.

Before we dive into the de-obfuscation logic, let’s start by analyzing the similarities between Javascript created when the GWT application is compiled in “obfuscated mode” versus “pretty mode” to see how RPC calls are performed. Below is the “pretty” version a generic “greetServer” method call which accepts one string parameter.

Pretty Mode

function $greetServer(this$static, arr, callback){
var $e0, payload, requestId, streamWriter, clientSerializationStreamWriter;
requestId = requestId_0++;
!!$stats && $stats({moduleName:$moduleName, sessionId:$sessionId,
subSystem:'rpc', evtGroup:requestId,

method:'GreetingService_Proxy.greetServer'
, millis:(new Date).getTime(), type:'begin'});
try {
append(streamWriter.encodeBuffer, '' + $addString(streamWriter, 'com.gwttest.client.GreetingService'));
append(streamWriter.encodeBuffer, '' + $addString(streamWriter, 'greetServer'));
append(streamWriter.encodeBuffer, '1');
append(streamWriter.encodeBuffer, '' + $addString(streamWriter, '[Ljava.lang.String;/2600011424'));

$writeObject(streamWriter, arr);
payload = $toString_3(streamWriter);
$doInvoke(this$static, ($clinit_187() , 'GreetingService_Proxy.greetServer'), requestId, payload, callback);

By analyzing this method call, we see a hash table is assigning the “method” key a string value containing the GWT-RPC service and method name ( ‘GreetingService_Proxy.greetServer’ ). Within a try block we also see the building of a GWT-RPC Payload string which contains how many parameters the method expects (One Parameter)

append(streamWriter.encodeBuffer, '1');

and the data type it is expecting (String)

append(streamWriter.encodeBuffer, '' + $addString(streamWriter, '[Ljava.lang.String;/2600011424'));

Now, search through the obfuscated version of the same GWT application using the following regular expression:

"^function \w+\(.*method\:([A-Za-z0-9_\$]+),.*$"

You should eventually encounter a matching method. Below is an example of the obfuscated version of the same method (code expanded for readability)

Obfuscated Mode

function aH(b,c,d){
var a,f,g,h,i;
g=Ky++;
!!$stats&&$stats({moduleName:$moduleName,sessionId:$sessionId,subSystem:AQ,evtGroup:g,
method:kS,millis:(new Date).getTime(),type:lS});
h=(i=yy(new vy,b.b,b.e),i.e=0,lK(i.f),lK(i.g),mM(i.h),i.b=DJ(new AJ),iy(i,i.c),iy(i,i.d),i);
try{
Ey(h.b,KO+fy(h,mS));
Ey(h.b,KO+fy(h,nS));
Ey(h.b,oS);
Ey(h.b,KO+fy(h,pS));

hy(h,c);
f=Cy(h);
!!$stats&&$stats({moduleName:$moduleName,sessionId:
$sessionId,subSystem:AQ,evtGroup:g,
method:kS,millis:(new Date).getTime(),type:qS});
Py(b,(oz(),kS),g,f,d)
..snip..

The highlighted areas of the obfuscated code above are the parts we are most interested in. The service and method name is once again assigned to the “method” element of the hash table. The value of the variable “kS” is assigned towards the end of the same Javascript file.

kS='GreetingService_Proxy.greetServer

Within the “try” block, you’ll see several “Ey” method calls which correspond to the “append” method we previously saw in the “pretty” version. Looking at the second parameter of the 3rd append call we see that the variable “oS” is passed.

Ey(h.b,oS);

By searching the Javascript code for the assigned value of “oS” we see that it is the expected value of “1”.

oS='1'

Moving onto the next append method call

Ey(h.b,KO+fy(h,pS));

the “fy” method call is called, which corresponds to the “$addString” method call seen in the “pretty” version. The value assigned to the second parameter of the “fy” method will provide us the data type the GWT-RPC method is expecting.

pS='[Ljava.lang.String;/2600011424'

As you can see, the process of performing de-obfuscation manually is time consuming and tedious due to the amount of variable tracing involved. For this reason I created GWTEnum, a python tool that automates the process of enumerating GWT-RPC method calls for any GWT application compiled in obfuscated mode.

The Tool

GWTEnum works by analyzing the “nocache.js” file, which contains references to the underlying “cache.html” files where the actual method calls lie. Simply point GWTEnum to the “nocache.js” file and the tool will take care of the rest. A good example of how the tool works can be seen in the following example, where GWTEnum was run against the Whirled.com virtual world website. This site was chosen for this example since it is accessible to the public and uses GWT compiled in obfuscated mode.

>python gwtenum.py –u "http://www.whirled.com/gwt/frame/frame.nocache.js"

Analyzing http://www.whirled.com/gwt/frame/02DA50B7EB86809D55630981FE1D7F1A.cach
e.html

===========================
Enumerated Methods
===========================

FacebookService_Proxy.getStoryFields(com.threerings.msoy.facebook.gwt.FacebookService$StoryKey/2584007011 )
FacebookService_Proxy.trackPageRequest( I,java.lang.String/2004016611 )
FacebookService_Proxy.trackStoryPosted(com.threerings.msoy.facebook.gwt.FacebookService$StoryKey/2584007011,java.lang.String/2004016611,java.lang.String/2004016611 )
WebMemberService_Proxy.escapeTheme( )
WebMemberService_Proxy.getInvitation( java.lang.String/2004016611,Z )
WebMemberService_Proxy.getMemberCard( I )
WebMemberService_Proxy.isThemeManager( I )
WebMemberService_Proxy.noteNewVisitor(com.threerings.msoy.data.all.VisitorInfo/3279131818,java.lang.String/2004016611,Z )
WebMemberService_Proxy.trackTestAction( java.lang.String/2004016611,java.lang.String/2004016611,com.threerings.msoy.data.all.VisitorInfo/3279131818 )
WebUserService_Proxy.getApp( I )
WebUserService_Proxy.getConnectConfig( )
WebUserService_Proxy.loadLaunchConfig( I )
WebUserService_Proxy.validateSession( java.lang.String/2004016611,java.lang.String/2004016611,I,I )

As shown above, we now have a complete list of all accessible RPC methods. Once the available methods have been enumerated, there are several ways to invoke RPC calls to these methods.

The simplest method of invocation would be for cases where you have already encountered another method (through normal site use) that accepts the same number and type of parameters. In this case, you can intercept the original method call with an intercepting proxy like Burp and change the method name in order to execute the new method. There will likely be cases, however, where the new method accepts a unique combination of different parameters than the methods you have already encountered. For these cases, you can use a tool such as GWT SyncProxy in order to invoke GWT-RPC calls using Java.

In summary, GWTEnum aims to eliminate the complexities posed by obfuscated GWT code that normally make testing these applications more difficult. Hopefully application testers out there find this tool and enumeration technique helpful when encountering an obfuscated GWT application. If you encounter any issue while using the tool, feel free to send an email to rgutierrez at gdssecurity.com

GWTEnum can be downloaded here

Thursday
May062010

Fuzzing GWT RPC Requests

In a previous post,  I went through the process of parsing GWT RPC requests to determine the method and parameter values sent. In this post I will discuss, GwtParse, a tool that I wrote to automate this process in order to easily determine the values within a GWT RPC payload that can actually be manipulated. GwtParse can be downloaded here but I recommend you continue reading...

Why use this tool?

Fuzzing every delimited value in GWT RPC requests is not practical and produces a lot of unnecessary output. GWT client side code is heavily obfuscated, which makes it difficult to identify all the fuzzable values passed in the request by reviewing the JavaScript. Additionally, there could be values passed in the request that do not necessarily originate from user input. For example, assume there is a custom “User” object which contains a numeric property that indicates a user’s role membership. Manipulation of this value could result in unauthorized access to data or privileged functionality. The tool I wrote gwtparse.py will help identifying the meaningful values in a GWT RPC request so that you can more easily identify security bugs in GWT applications during a Black Box assessment.

gwtparse.py

A command line tool that parses a GWT RPC payload and creates a new payload value with all fuzzable values identified. This new payload value can then be plugged into the web application fuzzer of your choice. The tool has currently only been tested using GWT version 2.0.

The following types can be parsed:

  • Primitive Java Types and Object (ie. Integer, Double, Byte, etc )
  • Strings
  • Arraylist, Vector, LinkedList
  • Arrays
  • Custom Objects ( to a limited extent )

Parsing of custom objects cannot be guaranteed to work correctly in all scenarios as they can be very complex. I created a number of test cases with custom objects, but there is bound to be cases that the current version of my tool cannot handle. I just want to point out a couple key points:

  • Parsing a GWT RPC request is as simple as follows

$ python gwtparse.py -i "5|0|12|http://127.0.0.1:8888/gwt_test/|4E7583E4BED25F58DDD5F1A1D675522A|
com.gwttest.client.GreetingService|greetServer|java.util.ArrayList/3821976829|
com.gwttest.client.CustomObj/427743781|com.gwttest.client.Person/2847577871|
PersonName|java.lang.Integer/3438268394|CustomObjParam1|CustomObjParam2|
CustomObjParam3|1|2|3|4|2|5|6|5|2|7|200|8|7|200|8|6|9|200|10|11|12|10|"

Output from above command:

GWT RPC Payload Fuzz String

5|0|12|http://127.0.0.1:8888/gwt_test/|4E7583E4BED25F58DDD5F1A1D675522A|
com.gwttest.client.GreetingService|greetServer|java.util.ArrayList/3821976829|
com.gwttest.client.CustomObj/427743781|com.gwttest.client.Person/2847577871|
%s|java.lang.Integer/3438268394|%s|%s|%s|1|2|3|4|2|5|6|5|2|7|
%d|8|7|%d|8|6|9|%d|10|11|12|10|

The default output of the script replaces the fuzzable string values with a %s and numeric values with a %d.  This is incredibly useful since Java is a strong typed language and will throw an exception if a string value is passed anywhere the application is expecting an Integer.

  • Tool output can be customized so that the fuzzable values are easily recognized by your favorite fuzzer. This is done with the “-s” option, which surrounds the values with the string/character of your choice.
  • For Burp Suite users, there is the “-b” switch to surround the values using the Burp Intruder Position Value (Section Sign). Note that the Section Sign character is only output to the command-line when run within a terminal that can output UTF-8 values (i.e. Linux, Cygwin). Windows users can add the “-w” or “-a” switches to write or append the output to a text file.
  • Lastly, there is the “-p” switch that displays the request in a human readable format. This can be especially useful in identifying the values which belong to a custom object. I have included an example of this at the end of my post.

The gwtparse.py program simply calls functionality available within my GWTParser object. The GWTParser object can be easily reused by testers within their own python fuzzers or tools. Hopefully, application testers will find the tool useful when tackling a GWT application assessment.

If you find GWT RPC payload strings which are not properly handled by my tool (which I am sure there will be), send an email to rgutierrez at gdssecurity.com and I will work on incorporating a fix for the next version. GwtParse can be downloaded here

Sample output when using the –p Switch to Display GWT RPC Requests in Human Readable Format

Serialized Object:

5|0|12|http://127.0.0.1:8888/gwt_test/|4E7583E4BED25F58DDD5F1A1D675522A|
com.gwttest.client.GreetingService|greetServer|java.util.ArrayList/3821976829|
com.gwttest.client.CustomObj/427743781|com.gwttest.client.Person/2847577871|
PersonName|java.lang.Integer/3438268394|CustomObjParam1|CustomObjParam2|
CustomObjParam3|1|2|3|4|2|5|6|5|2|7|200|8|7|200|8|6|9|200|10|11|12|10|


Stream Version: 5
Flags: 0
Column Numbers: 12
Host: http://127.0.0.1:8888/gwt_test/
Hash: 4E7583E4BED25F58DDD5F1A1D675522A
Class Name: com.gwttest.client.GreetingService
Method: greetServer
# of Params: 2

Parameters:
{'flag': False,
'is_array': False,
'is_custom_obj': True,
'is_list': True,
'subtype': 'com.gwttest.client.Person',
'typename': 'java.util.ArrayList/3821976829',
'values': [<Parameter.Parameter object at 0x7fee4a4c>,
<Parameter.Parameter object at 0x7fee4a6c>]}

{ 'flag': False,
'is_array': False,
'is_custom_obj': True,
'is_list': False,
'typename': 'com.gwttest.client.Person/2847577871',
'values': [200, 'PersonName']}
{ 'flag': False,
'is_array': False,
'is_custom_obj': True,
'is_list': False,
'typename': 'com.gwttest.client.Person/2847577871',
'values': [200, 'PersonName']}

{'flag': False,
'is_array': False,
'is_custom_obj': True,
'is_list': False,
'typename': 'com.gwttest.client.CustomObj/427743781',
'values': [200,
'CustomObjParam1',
'CustomObjParam2',
'CustomObjParam3',
'CustomObjParam1']}


The above “pretty” output shows that the RPC call has two parameters. The first parameter is an ArrayList of Person Objects with two member variables and the second parameter is another object called CustomObj which has five member variables.

Thursday
Oct082009

GWT-RPC in a Nutshell

Hello folks, Ron Gutierrez here. Recently I chose to dissect the cryptic serialized HTTP requests used by Google Web Toolkit RPC to better understand which fields are actually “fuzzable”. If you were looking to find a flaw in the implementation of GWT RPC then every single value in the request would be fuzzible. In this case, I’m looking for the fields that the web application will actually be processing.

First, a little bit about Google Web Toolkit (GWT). GWT is a Java framework that is used to create AJAX applications.  Rather than having to write complex JavaScript code, GWT makes it easy to build AJAX enable Java web applications by allowing developers to build the components in Java and then compiling that code into optimized JavaScript for browsers to run.  One of the added bonuses that GWT provides is the ability to reuse code.  GWT-RPC provides the ability to send native and custom Java objects from the client-side Javascript code over to the Java server-side backend.  GWT-RPC sends a serialized stream containing the Class name, Method name, Parameters through the wire whenever an AJAX call is made. This serialized stream is what we need to dissect in order to understand which fields can be fuzzed without invalidating the request.

The serialized steam is in plaintext and delimited by pipes.  The calls are sent through the browser as a typical HTTP POST Request with the serialized method call in the body of the request. Here is an example of a very simple GWT RPC request to a method called greetServer that takes in two strings as parameters.

5|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|1|2|3|4|2|5|5|6|7|

The stream can be split into three different parts (keep in mind that I am using Google’s naming convention for these parts as seen through the code that implements the serialization).

Header 

  1. Contains the SERIALIZATION_STREAM_VERSION value which at present will always be set to 5.  If this value is changed, it will cause an error on the server side. Therefore, this value is not fuzzable.
  2. The next value is a flag value. I have yet to seen somewhere where this value is set to anything other than 0. Modifying this value does not break a request.

5|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|1|2|3|4|2|5|5|6|7|

String Table

  1. The first value is an integer that tells you how many pipe delimited values to read in to fill the String Table.  In this example, the next seven values will be the String Table contents. Consider this data structure to be similar to that of an array in that each value has an index that corresponds to the values in the Payload (discussed next).

5|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|1|2|3|4|2|5|5|6|7|

Payload

  1. Consists of numeric values used to reconstruct the method call and parameters in the String Table. For example, 1 refers to the second element (http://localhost:8080/testproject), 2 refers to the third element (29F…), etc.
  2. These values for the most part should not be fuzzed. Since the payload values are used to reconstruct the method call on the server changing them to anything that will create an invalid call which will result in a request error.
  3. There are a few caveats which I’ll get into more detail as we progress.

5|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|
1|2|3|4|2|5|5|6|7|

The first four values of the payload can be expected to appear in every GWT RPC request. The first two values consist of the directory containing all the Javascript that was generated during the GWT compiliation and what looks to be an identifier for the Service. Regardless of their meanings, their contents should not be fuzzed as the values are not taken into consideration by the server. The next values “com.test.client.GreetingServer” and “greetServer” corresponds to the server side service name and method name that will be called. Altering these values to an incorrect class or method will cause an exception to be thrown and returned in the response if the exception is not properly handled by the server.

5|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|
java.lang.String|
myInput1|myInput2|
1|2|3|4|2|5|5|6|7|

This is where the Payload gets a little more interesting … The fifth payload value (2) actually tells you how many method parameters are being sent. In this example the user is sending two parameters; since two parameters are being sent, there are two subsequent payload values (5|5 in this case) that refer to the indices of the String Table containing the data types of the parameters.  In this example, The Java data type of both method parameters is java.lang.String.

5|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|
1|2|3|4|2|5|5|6|7|

The final two values refer to the indices of the String Table containing the actual string values that are being passed in the method. These are the primary subjects for application-level fuzzing. It’s worth noting that integer values that are sent as parameters will be appended to the payload rather than being stored in the String Table. Integer values can be modified, however since Java will be expecting an integer value you will be limited to only numeric values.

5|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|
1|2|3|4|2|5|5|6|7|

Keep in mind that this was a walkthrough of a request with primitive data types. In reality, developers can be sending custom objects or more complex common Java objects such as Vectors, Linked Lists, etc. These data types will follow a different protocol for reading values from the String Table and Payload. To properly de-serialize these types, I found it easiest to capture sample requests and script the de-serialization.  I am planning to share this research and my script for automating the fuzzing of GWT RPC applications in an upcoming blog post.