Breaking Through GWT's Binary Wall: A Proxy Approach to Testing Legacy RPC Applications
Hook
Google Web Toolkit applications can smuggle SQL injection vulnerabilities in plain sight—encoded in a binary RPC format that most security scanners simply ignore.
Context
Google Web Toolkit revolutionized enterprise web development in the mid-2000s by letting developers write Java code that compiled to JavaScript. Its RPC mechanism provided a seamless client-server communication layer, but this convenience came with a security testing cost. Unlike REST APIs with readable JSON payloads, GWT RPC uses a proprietary binary serialization format that's opaque to traditional security tools. When a pentester intercepts GWT traffic in Burp Suite, they see encoded strings like "7|0|6|http://example.com/|...|com.example.client.MyService|myMethod|java.lang.String/2004016611|...". Standard tools like sqlmap, Burp Scanner, or even manual testing workflows break down because they can't parse or modify these requests meaningfully.
The burp-gwt-wrapper project addresses this friction point by acting as a translation proxy. It sits between your security tools and GWT applications, consuming Burp Suite's saved XML request files, decoding the GWT RPC protocol into manipulable components, and exposing them through a Flask web interface. This architecture enables security testers to treat GWT applications like any other HTTP target—running automated scanners, fuzzing parameters, and testing for injection vulnerabilities without wrestling with binary encodings. It's a specialized bridge built for a specific pain point: making legacy GWT applications testable with modern security tooling.
Technical Insight
The architecture of burp-gwt-wrapper revolves around three key components: XML request ingestion, the gwtparse library for protocol handling, and a Flask frontend that exposes decoded requests. When you save a Burp Suite request as XML, the tool reads this file and extracts the raw GWT RPC payload. Here's what a typical workflow looks like in practice:
# Simplified example of how the tool processes a saved Burp request
from gwtparse import GWTParser
import xml.etree.ElementTree as ET
# Load the Burp XML file
tree = ET.parse('saved_request.xml')
request_data = tree.find('.//request').text
# Extract the GWT RPC payload from the raw HTTP body
gwt_payload = extract_post_body(request_data)
# Parse using gwtparse library
parser = GWTParser()
parsed = parser.deserialize(gwt_payload)
# Now you have structured data: method name, parameters, types
print(f"Service Method: {parsed.method}")
print(f"Parameters: {parsed.params}")
# Output might be:
# Service Method: searchUsers
# Parameters: ['john', 'doe', 100]
The real power emerges in how Flask exposes these parsed components. The tool creates routes that map to individual GWT RPC methods, presenting their parameters as standard HTTP form fields or query parameters. When you submit a modified request through the web interface, burp-gwt-wrapper re-encodes your changes back into valid GWT RPC format, including recalculating the protocol's checksum and maintaining the proper serialization structure. This bidirectional translation is critical—it's not enough to decode; you need valid encoding to communicate with the GWT backend.
The dependency on the gwtparse library is both a strength and constraint. This library handles the heavy lifting of GWT RPC protocol version 6, including its type serialization table, method signatures, and the peculiar pipe-delimited format. GWT RPC encodes each request with a serialization policy that maps Java types to integers, and gwtparse maintains the logic to interpret these mappings. Without it, you'd be implementing a complex state machine to track type definitions across request boundaries.
The Flask frontend design is deliberately minimal—it's meant for local security testing workflows, not production deployment. Routes are dynamically generated based on the parsed GWT methods, creating endpoints like /invoke/<method_name> where testers can manipulate parameters. This approach integrates smoothly with automated scanners: you can point sqlmap at http://localhost:5000/invoke/searchUsers?param1=test and the tool handles the GWT encoding behind the scenes. The scanner sees a normal HTTP parameter; the GWT backend receives properly encoded RPC.
One architectural choice worth noting is the XML file-based approach rather than live proxying. The tool doesn't intercept traffic in real-time like Burp Suite itself. Instead, it expects you to save interesting requests as XML files, then process them separately. This design simplifies the implementation—no need to handle SSL/TLS interception, manage proxy authentication, or deal with WebSocket connections that modern GWT applications might use. However, it does create a manual workflow: identify request in Burp, save as XML, load in wrapper, test, repeat. For targeted vulnerability assessment, this trade-off makes sense. For continuous testing or large-scale scanning, the friction adds up.
Gotcha
The most significant limitation is protocol version compatibility. The tool explicitly supports GWT RPC protocol version 6, which was prevalent in GWT 2.x applications from roughly 2010-2015. If you're testing newer GWT applications—particularly those using GWT 3.x or later—there's no guarantee the gwtparse library will handle the encoding correctly. GWT's serialization format has evolved, and the tool's documentation doesn't specify version detection or graceful degradation. You might successfully decode some requests while others fail silently, producing malformed RPC calls that the server rejects with cryptic errors. Testing protocol compatibility before committing to a full assessment is essential.
The Python 2.7 legacy poses practical deployment challenges. While the code might run under Python 3 with minimal modifications, you'll likely encounter dependency conflicts. The Flask version, gwtparse compatibility, and XML parsing libraries all need alignment. In 2024, setting up a Python 2.7 environment means using Docker or virtual machines with archived package repositories—a non-trivial barrier for quick testing. The project's apparent abandonment (last commits several years old, minimal community engagement) means you're on your own for Python 3 migration or bug fixes. For organizations with strict security policies around software dependencies, using unmaintained tools creates compliance headaches.
Verdict
Use if: You're conducting security assessments on legacy GWT applications (circa 2010-2015) that use RPC protocol version 6, and you need to leverage automated scanning tools like sqlmap or Burp Scanner against specific endpoints. The tool shines in targeted testing scenarios where you've identified potentially vulnerable GWT methods and want to iterate quickly with parameter fuzzing. It's also valuable if you're comfortable with Python dependency management and can containerize the environment to avoid local system pollution. Skip if: Your target uses modern GWT versions with unknown protocol compatibility, you need real-time proxying capabilities for dynamic application testing, or you require actively maintained tooling with Python 3 support and community backing. The manual XML workflow becomes prohibitively tedious for comprehensive application scans, making it unsuitable for anything beyond focused vulnerability validation. Consider modern Burp extensions with native GWT support or manual browser-based testing for applications outside the tool's sweet spot.