GWT-3D
Discover, Decode, Destroy

About


GWT Penetration Testing Toolkit originale version is from GDSSecurity.
It is "a set of tools made to assist in penetration testing GWT applications". The last update on this tool is from years ago. But GWT has updated since then and the tool doesn't work anymore. That's where this one comes.

It is a new version of the tool that uses the same parsing algorithm as before but updated thanks to how GWT creates requests now. It also has new options and usability has been improved a lot. A lot of bugs from the previous versions are now fixed. Moreover it is usable with Python 2 and Python 3 (however, the documentation will use Python 3)!

There are two types of usage for the tools: enumerate Java (server side) methods and parameters and/or decode GWT requests to have a better understanding of how it works and to create fuzzing strings.

Howto


Program help

                                
$ python3 gwt.py --help
usage: gwt.py [-h] [--verbose] [--debug] {enum,en,e,decode,de,dcd,dec,d} ...

GWT pentest tool

optional arguments:
  -h, --help            show this help message and exit
  --verbose             Verbose mode
  --debug               Debug mode

Actions:
  Possible actions

  {enum,en,e,decode,de,dcd,dec,d}
                        Actions that can be performed by the tool
    enum (en, e)        Enumerates all Java methods with their associated
                        parameters
    decode (de, dcd, dec, d)
                        Decodes a [set of] GWT RPC request(s)
                                
                            

You have the possibility to use to different "actions": enum (aliases: en, e) or decode (aliases d, de, dcd, dec).
The first one enumerates all Java (server side) methods with their params (if found) and the second one decodes one or more GWT requests and shows fuzzable parts of the payload.


Method enumeration

                                
$ python3 gwt.py enum --help
usage: gwt.py enum [-h] -u URL [-p PROXY] [-b BASICAUTH] [-c COOKIES]
                   [-o OUTPUT]

Possible options

optional arguments:
  -h, --help            show this help message and exit
  -u URL, --url URL     URL of the nocache.js file
  -p PROXY, --proxy PROXY
                        Proxy host and port (i.e.: "http://localhost:8080")
  -b BASICAUTH, --basicauth BASICAUTH
                        Basic authentication credentials
  -c COOKIES, --cookies COOKIES
                        Cookies to use to get the JS files
  -o OUTPUT, --output OUTPUT
                        Absolute path were to store all parsed requests
                        (default "stdout")
                                
                            

This action can help you to enumerate Java methods and parameters. To do so, you have to give the script the URL to a "nocache.js" file. This file is a particular GWT JS file that helps get other JS files from server cache. By using some tricks, an unauthenticated user can enumerate all server methods.
If needed, you can set up a bunch of options like a proxy, some cookies to use with the request and basic authentication (you will be prompted for credentials during the execution of the script). The last option is to use a different output than the default one (stdout). You can specify a file (that will be created if doesn't exist) and then everything will be saved in there!


Examples

                                
$ python3 gwt.py enum -u "https://site.com/plop.nocache.js?3790"
This can take a very long time (like 3-4mn)
AppletImportRpc.getAppletProperties()
AppletImportRpc.getJavascriptProperties()
AuthorizationRpc.getAuthorizations()
[...]
UserRpc.setNewPwd(java.lang.Integer, java.lang.String, java.lang.String)
UserRpc.setNewPwd(java.lang.Integer, java.lang.String, java.lang.String, java.lang.String)
UserRpc.storeMetamodelForImport(com.site.client.transport.media.CustomMetamodelTransport)
                                
                            

This enumerates Java methods from the JS file given in parameter and outputs results on stdout.


                                
$ python3 gwt.py enum -u "https://site.com/plop.nocache.js?3790" -o test.txt
This can take a very long time (like 3-4mn)
Output saved to test.txt
                                
                            

This enumerates Java methods from the JS file given in parameter and outputs results in the file specified.


Request parsing

                                
$ python3 gwt.py decode --help
usage: gwt.py decode [-h] -i INPUT [-s SURROUND] [-r REPLACE] [-b] [-p]
                     [-o OUTPUT] [-m METHODS] [-f]

Possible options

optional arguments:
  -h, --help            show this help message and exit
  -i INPUT, --input INPUT
                        The RPC request payload or Burp log file
  -s SURROUND, --surround SURROUND
                        Surrounds fuzzable parameters by a given string
  -r REPLACE, --replace REPLACE
                        Replaces fuzzable parameters by a given string
  -b, --burp            Surrounds fuzzable parameters by Burp Intruder
                        characters
  -p, --pretty          Human readable formatting of the request
  -o OUTPUT, --output OUTPUT
                        Absolute path were to store all parsed requests
                        (default "stdout")
  -m METHODS, --methods METHODS
                        You can specify a file were all Java methods are
                        enumerated (line separated).This file can be obtained
                        by running the "enum" script
  -f, --fuzz            Outputs only fuzzable strings
                                
                            

Ths action can help you understand GWT RPC requests made by the application you're auditing. It can also help to know which parameters are fuzzable in a request. This action can work on a single request or on a Burp proxy log, for example. Then, using some options, you can configure fuzzing settings to suit your needs.
As for the enum action, you can specify an output file or use stdout.
Note — the -p/--pretty switch is not yet implemented, it will be in next versions.


Examples

                                
$ python3 gwt.py decode -i "4ï¿¿0ï¿¿6ï¿¿https://site.com/ï¿¿C33C748610876DA5ACE277F0EA893A44ï¿¿com.site.client.rpc.MediaRpcï¿¿getMediaHiresHttpPathï¿¿java.lang.Integerï¿¿java.lang.Integer/3438268394ï¿¿1ï¿¿2ï¿¿3ï¿¿4ï¿¿1ï¿¿5ï¿¿6ï¿¿123ï¿¿"

Original request:
4ï¿¿0ï¿¿6ï¿¿https://site.com/ï¿¿C33C748610876DA5ACE277F0EA893A44ï¿¿com.site.client.rpc.MediaRpcï¿¿getMediaHiresHttpPathï¿¿java.lang.Integerï¿¿java.lang.Integer/3438268394ï¿¿1ï¿¿2ï¿¿3ï¿¿4ï¿¿1ï¿¿5ï¿¿6ï¿¿123ï¿¿
Resulting fuzzing string:
4|0|6|https://site.com/|C33C748610876DA5ACE277F0EA893A44|com.site.client.rpc.MediaRpc|getMediaHiresHttpPath|java.lang.Integer|java.lang.Integer/3438268394|1|2|3|4|1|5|6|%d|
                                
                            

This command line shows you how to basically use GWT-3D decoder with one simple GWT RPC request. The "Resulting fuzzing string" shows you where you can fuzz and the type of the variable that will be used server-side.


                                
$ python3 gwt.py decode -i "4ï¿¿0ï¿¿11ï¿¿https://site.com/ï¿¿C33C748610876DA5ACE277F0EA893A44ï¿¿com.site.client.rpc.UserRpcï¿¿findActivatedUsersByProfileIdï¿¿java.lang.Integerï¿¿Iï¿¿java.lang.Stringï¿¿java.lang.Integer/3438268394ï¿¿pwdï¿¿ASCï¿¿nadminï¿¿1ï¿¿2ï¿¿3ï¿¿4ï¿¿6ï¿¿5ï¿¿6ï¿¿6ï¿¿7ï¿¿7ï¿¿7ï¿¿8ï¿¿1ï¿¿0ï¿¿100ï¿¿9ï¿¿10ï¿¿11ï¿¿" -m "~/available_methods.txt" -b

Original request:
4ï¿¿0ï¿¿11ï¿¿https://site.com/ï¿¿C33C748610876DA5ACE277F0EA893A44ï¿¿com.site.client.rpc.UserRpcï¿¿findActivatedUsersByProfileIdï¿¿java.lang.Integerï¿¿Iï¿¿java.lang.Stringï¿¿java.lang.Integer/3438268394ï¿¿pwdï¿¿ASCï¿¿nadminï¿¿1ï¿¿2ï¿¿3ï¿¿4ï¿¿6ï¿¿5ï¿¿6ï¿¿6ï¿¿7ï¿¿7ï¿¿7ï¿¿8ï¿¿1ï¿¿0ï¿¿100ï¿¿9ï¿¿10ï¿¿11ï¿¿
Equivalent Java method call:
UserRpc.findActivatedUsersByProfileId(java.lang.Integer 1, I 0, I 100, java.lang.String pwd, java.lang.String ASC, java.lang.String nadmin)
Resulting fuzzing string:
4|0|11|https://site.com/|C33C748610876DA5ACE277F0EA893A44|com.site.client.rpc.UserRpc|findActivatedUsersByProfileId|java.lang.Integer|I|java.lang.String|java.lang.Integer/3438268394|§pwd§|§ASC§|§nadmin§|1|2|3|4|6|5|6|6|7|7|7|8|§1§|§0§|§100§|9|10|11|
                                
                            

With this command line, you are able to see the server-side call equivalent to the GWT RPC request currently analyzed and to surround fuzzable parameters with Burp characters.


                                
$ python3 decode -i "/home/miaouplop/security/web/burp/logs/requests.log" -o "plop.txt" -f -b
Encountered Error During Parsing with request:
4|0|14|https://site.com/|C33C748610876DA5ACE277F0EA893A44|com.site.client.rpc.TreeRpc|getThumbnailsDatas|java.lang.String|java.lang.Integer|java.lang.Boolean|I|Z|[Ljava.lang.String;|jxtrh8ts-1413979603637|java.lang.Integer/3438268394|java.lang.Boolean/476441737|creationDate|1|2|3|4|9|5|6|7|8|8|5|9|10|7|11|12|-1|13|0|0|60|14|0|0|0|

Encountered Error During Parsing with request:
4|0|14|https://site.com/|C33C748610876DA5ACE277F0EA893A44|com.site.client.rpc.TreeRpc|getThumbnailsDatas|java.lang.String|java.lang.Integer|java.lang.Boolean|I|Z|[Ljava.lang.String;|k4tnblyc-1413979609284|java.lang.Integer/3438268394|java.lang.Boolean/476441737|creationDate|1|2|3|4|9|5|6|7|8|8|5|9|10|7|11|12|-1|13|0|0|60|14|0|0|0|

Encountered Error During Parsing with request:
4|0|14|https://site.com/|C33C748610876DA5ACE277F0EA893A44|com.site.client.rpc.TreeRpc|getThumbnailsDatas|java.lang.String|java.lang.Integer|java.lang.Boolean|I|Z|[Ljava.lang.String;|ll11tggc-1413979603775|java.lang.Integer/3438268394|java.lang.Boolean/476441737|creationDate|1|2|3|4|9|5|6|7|8|8|5|9|10|7|11|12|-1|13|0|0|60|14|0|0|0|

Encountered Error During Parsing with request:
4|0|14|https://site.com/|C33C748610876DA5ACE277F0EA893A44|com.site.client.rpc.TreeRpc|getThumbnailsDatas|java.lang.String|java.lang.Integer|java.lang.Boolean|I|Z|[Ljava.lang.String;|anprx235-1413979619663|java.lang.Integer/3438268394|java.lang.Boolean/476441737|creationDate|1|2|3|4|9|5|6|7|8|8|5|9|10|7|11|12|-1|13|0|0|60|14|0|0|0|

Output saved to plop.txt
                                
                            

With this command line you are able to parse an entire burp log file and send the output to "plop.txt" file. The -f switch is used to output only fuzzable requests line by line. With this, can can send the file to your favourite fuzzer (burp here).
Note — here we can see that there were errors during the parsing. Currently, they are printed on stdout but in the next versions they will be printed on stderr so that you can use stream redirections. There will be a deep inspection on this to see why some requests are not parsed.

Futur of GWT-3D


GWT-3D is at its beta version. It's, for now, only an adaptation of an existing tool to the newer versions of GWT. I didn't have the occasion to test it much so I hope you will be as many as possible to test & open issues on the repository so that I can build a good tool. Feel free to fork and make pull requests!

I am also working on a Burp Suite plugin that can decode GWT RPC requests on the fly and pass fuzzable requests direclty to Burp Intruder. This plugin will be open-sourced too and the more you participate on testing the tool, the more the Burp plugin will be good!

Contact Me


You can contact me on GitHub & Twitter or by mail at miaouplop+gwt3d[ at ]gmail.com.
Feel free to participate on testing the tool (I had access to only one GWT website) and post issues on GitHub. Feel also free to fork and send pull requests!
Have fun using the tool!