Testing GWT Applications with Standard Security Tools: How burp-gwt-wrapper Bridges the Protocol Gap
Hook
Google Web Toolkit's binary RPC protocol was so effective at preventing automated security testing that penetration testers often skipped GWT endpoints entirely—treating them as black boxes that only manual testing could crack.
Context
Google Web Toolkit (GWT) revolutionized web development in the late 2000s by letting developers write client-side applications in Java that compiled to JavaScript. But GWT's efficiency came with a security testing cost: its RPC protocol serialized method calls into a compact binary format that standard web security tools couldn't parse. When a penetration tester pointed Burp Scanner or sqlmap at a GWT application, these tools saw gibberish—they couldn't identify individual parameters to test for SQL injection, XSS, or other vulnerabilities.
This created a painful workflow gap. Security professionals using Burp Suite could intercept GWT requests and see the serialized payload, but they couldn't easily manipulate individual parameters or automate vulnerability scanning. Manual testing was possible but tedious: you'd need to understand the GWT RPC wire format, manually craft payloads, and test each parameter one at a time. The burp-gwt-wrapper project emerged to solve this specific pain point by acting as a translation proxy—it sits between your security tools and the GWT application, converting opaque RPC calls into simple HTTP form parameters that any tool can understand and test.
Technical Insight
The architecture is elegantly simple: a Flask web application that accepts Burp Suite XML exports and provides a proxy interface for re-encoding modified requests. The workflow starts with exporting a GWT RPC request from Burp Suite to an XML file. This XML contains the complete HTTP request including headers and the serialized GWT payload. The wrapper then uses the gwtparse library to decode this payload into individual parameters.
Here's what happens under the hood. A typical GWT RPC request payload looks like this:
7|0|6|http://example.com/app/|ABCD1234|com.example.Service|getUserData|java.lang.String|john.doe@example.com|1|2|3|4|1|5|6|
This pipe-delimited format encodes the GWT RPC protocol version, flags, service interface, method name, parameter types, and actual parameter values. The gwtparse library deserializes this into a structure the wrapper can work with. The Flask application then generates an HTML form where each decoded parameter appears as a standard text input field. When you submit this form (or point sqlmap at it), the wrapper re-encodes your modified parameters back into GWT RPC format and forwards the request to the target application.
The proxy implementation is straightforward. Once you've loaded your XML file through the web interface, you get a unique URL like http://localhost:5000/proxy/abc123. This endpoint accepts standard HTTP GET or POST parameters. Behind the scenes, the wrapper maintains a mapping between your simple parameter names (param1, param2, etc.) and their positions in the GWT RPC structure:
# Simplified example of the re-encoding process
def rebuild_gwt_request(original_structure, new_params):
# Parse original GWT payload
tokens = original_structure.split('|')
# Replace parameter values while preserving structure
for param_name, param_value in new_params.items():
param_index = extract_index(param_name)
tokens[param_index] = param_value
# Reconstruct the pipe-delimited format
return '|'.join(tokens)
This lets you use sqlmap with a command like: sqlmap -u "http://localhost:5000/proxy/abc123?param1=test" --risk=3 --level=5. Sqlmap thinks it's testing a normal web parameter, but the wrapper is actually injecting your payloads into the GWT RPC structure and forwarding properly formatted requests to the target application.
The real cleverness is in the workflow integration. Rather than trying to be a full-featured proxy that intercepts all traffic, burp-gwt-wrapper focuses on the specific use case of testing individual requests. You still use Burp Suite for discovery and interception—its strengths—but delegate the encoding/decoding problem to a specialized tool. This separation of concerns keeps the codebase minimal (the core logic is under 300 lines) while solving the actual problem: making GWT parameters accessible to automated testing tools.
The Flask routes are minimal and focused. One route handles XML upload and parsing, another serves the parameter editing form, and the proxy route handles the actual request forwarding. There's no session management complexity, no authentication system, no database—just stateless request translation with temporary storage of the XML structures. This simplicity makes the tool easy to understand, modify, and debug when things go wrong.
Gotcha
The biggest limitation is GWT protocol version compatibility. The tool depends on gwtparse, which was built for GWT RPC protocol version 6 (circa 2012). Modern GWT applications often use protocol version 7 or later, which introduced changes to the serialization format. If you're testing a contemporary GWT application, there's a good chance the parser will choke on the payload or misinterpret parameter boundaries. You'll know immediately—the web interface will either show an error or display garbled parameter values that don't make sense.
The Python 2.7 dependency is another red flag. The codebase uses print statements without parentheses, old-style string formatting, and imports that assume Python 2. While it might run on Python 3 with minimal changes, the gwtparse dependency is frozen in time and would need updates too. This isn't just a maintenance concern—it's a security issue when you're running a local proxy that handles potentially malicious payloads. The manual workflow is also clunkier than you'd hope: you can't just route all traffic through this proxy like you would with Burp. Instead, you export XML files, upload them through a web form, get a unique proxy URL, and then configure your testing tool to use that URL. For testing dozens of endpoints, this quickly becomes tedious. There's no batch processing, no automation API, and no way to integrate this into a CI/CD pipeline. It's firmly a manual penetration testing tool, not something you'd use for ongoing security validation.
Verdict
Use if: You're performing a penetration test on a legacy GWT application (built 2010-2014 era) using GWT RPC protocol version 6, you're already comfortable with Burp Suite workflows and want to add automated scanner capabilities, and you need to demonstrate comprehensive parameter testing in your report without manually crafting hundreds of payloads. This tool fills a specific niche and does it reasonably well despite its age. Skip if: You're testing modern GWT applications (likely incompatible), you need production-ready security automation that runs continuously, you're uncomfortable running unmaintained Python 2 code that handles potentially malicious input, or you have the option to convince developers to add a REST API alongside their GWT RPC endpoints (always the better long-term solution). For most developers encountering GWT applications in 2024, the honest answer is that these applications should be migrated away from GWT entirely—but when that's not an option and you need to test what exists, this wrapper can save hours of manual payload crafting.