May 06 2010

Fuzzing GWT RPC Requests

Published by Ron Gutierrez under Application Security, Tools

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.

5 responses so far

Apr 23 2010

OWASP NYNJMetro – Pentesting Adobe Flex Applications

Published by Marcin Wielgoszewski under Application Security

I’ve uploaded my slides from the presentation I gave last week at the OWASP NYC Chapter on Pentesting Adobe Flex Applications.

In an upcoming post, I’ll describe in detail working with custom objects and how to craft AMF messages containing them and other data types.

No responses yet

Mar 17 2010

Penetrating Intranets through Adobe Flex Applications

Published by Marcin Wielgoszewski under Application Security, Tools

In my last post, Pentesting Adobe Flex Applications with a Custom AMF Client, I described how one could write a client using Python and PyAMF to perform manual penetration testing of Flex applications. The example application I focused on utilized RemoteObjects and communicated via binary AMF encoded messages, a common roadblock for security testers. If you are new to penetration testing Flex applications, I suggest reading my previous post to familiarize yourself with Flex and the techniques I discussed.

In this post, I’ll show how you can exploit Flex applications that use BlazeDS to gain access to internal networks and other hosts behind the firewall. BlazeDS is a Java-based remoting server that allows developers to utilize existing application logic and web services in Flex applications. The following also applies to applications that use Adobe LiveCycle Data Services ES.

A common insecure configuration that we encounter when assessing Flash applications is an insecure crossdomain.xml policy file (usually hosted within a web site’s root directory). By default, a Flash application hosted on domain A cannot access resources from domain B unless domain B has configured their cross-domain policy to allow domain A. More often than not, the cross domain policy file has been configured to allow the entire world access rather than a specific list of trusted domains. Now, assuming the cross domain policy file has been secured, developers of Flex applications that consume data from external web services must now incorporate this restriction into their design. This makes it difficult to develop Flex applications that will be hosted on multiple, possibly untrusted domains.

Enter BlazeDS. To get around the restrictions imposed by cross-domain policy files, BlazeDS allows developers to configure “Proxy Services”. Using Proxy Services, BlazeDS will make calls to remote service destinations on behalf of the Flex application. BlazeDS Proxy Services allows Flex applications to consume SOAP and Web Services hosted on other domains without the need for a cross-domain policy. A common use case for proxy services is to allow external access to internally hosted web services via a specified destination. A typical proxy service is configured like so (see BlazeDS Developer Guide for more detail):

# contents of WEB-INF\flex\proxy-config.xml:
<service id="proxy-service" class="flex.messaging.services.HTTPProxyService">
  ...
  
  <destination id="web-service">
    <properties>
      <dynamic-url>http://ws.localdomain:9899/web/service/content.jsp</dynamic-url>
    </properties>
  </destination>
  
  <destination id="soap-service">
    <properties>
      <wsdl>http://ws.localdomain:9899/ws?wsdl</wsdl>
      <soap>*</soap>
    </properties>
  </destination>
</service>

In the proxy-config.xml above, we have two destinations defined: web-service and soap-service. If you look closely, the soap property has an asterisk (wildcard) defined. This property can define an absolute domain and path, however like cross-domain policies, an asterisk permits BlazeDS to make requests to any hosts it can reach on the network that match this property. This is a common occurrence, due in part to sample configuration files supplied with BlazeDS and lack of awareness on part of those responsible for securing the application server. In more secure configurations, this property is set to a strict domain or path (such as the web-service destination).

If you want to build a Flex client that communicates with Proxy Services, you’ll need to familiarize yourself with the following objects (refer to the Flex Language Reference for more information):

  • mx.rpc.http.HTTPService (url)
  • mx.rpc.http.mxml.HTTPService(url)
  • mx.messaging.messages.HTTPRequestMessage (url)
  • mx.rpc.soap.WebService (endpointURI)
  • mx.rpc.soap.mxml.SOAPService (endpointURI)
  • mx.messaging.messages.SOAPMessage (url)

Without further ado, I’d like to introduce Blazentoo, a tool I developed to exploit such functionality. With Blazentoo, you can exploit insecurely configured Proxy Services and browse internal websites, potentially those on trusted corporate networks. Just recently I was working on an assessment and I was able to successfully compromise an internal application via an exposed BlazeDS server – as this wasn’t the first (or last) time, I decided it was time to build Blazentoo.

To use Blazentoo, you’ll need to know the following (most of this information can be obtained by examining HTTP requests proxied through a tool like Burp Suite, Charles Proxy, or WebScarab):

  • AMF/HTTP endpoint (the message broker servlet that flex requests are routed to)
  • The “destination” id (if this is left blank, the DefaultHTTP destination is used)
  • An optional “channel” id (leave blank if unknown)

If using SOAP, you’ll need to know the following additional information:

  • A SOAP Action associated with the destination id, and/or
  • URL of the WSDL (required if no destination id is defined)

Below is a screenshot of Blazentoo in action. Note that the URL being accessed in this example is “http://localhost/”. This could just as easily have been an internal IP address or hostname.

Blazentoo in action

You can download Blazentoo from our tools page.

One response so far

« Prev - Next »