An insecure implementation of the intent URL scheme revolves around theIntent.parseUri() method, which allows you to create an intent from an URI. The first thing we did when reversing the Mercury Browser was search for that specific method within the target packages.
We can see the parseUri() method being called from the com.ilegendsoft.mercury.ui.widget.e class. Now we want to see if the URL being loaded within the Main Activity of the browser somehow winds up as the second argument to the shouldOverrideUrlLoading() method. If we generate XREFS for the class we can see a call being made from com.legend.mercury.ui.activities.MainActivity, and to save you the headache of the going through the entire CFG, we did validate that this was indeed the case.
In : d.CLASS_Lcom_ilegendsoft_mercury_ui_widget_webview_e.show_xref()
F: Lcom/ilegendsoft/mercury/ui/activities/MainActivity; a (Lcom/ilegendsoft/mercury/ui/widget/webview/CustomWebView;)V a
The browser checks whether or not the URL starts with the “intent://“ scheme, and jumps if true to passing the URL into the parseUri() call. This object is used to call the startActivity() operation on the MainActivity.
Now that we know the browser supports an insecure implementation of the intent URL scheme, we can investigate Activities that would “benefit” from an intent object that we now control. VerSprite found two target Activities that could be used in either disclosing local files or creating an UXSS:
The BoxAuthActivity is used for Box authorization within the Mercury Browser, and retrieves an intent object within its onCreate() method. It takes the extra string “url_authorize” and passes that as an argument to the method which gracefully loads this string into a WebView via loadUrl().
The SimpleWebViewActivity has pretty much the same issue. It first calls getIntent() to retrieve the intent object. Then uses the method getStringExtra()to assign and call loadUrl() on a WebView from a string with the key “load”. We can exploit this in the exact same way as before.
It is important to realize that both of these vulnerable Activities are not exported and are considered to be private components of the browser application, which makes this type of issue to have a bit more impact.
Passcode and OAuth Exposure
The Mercury Browser allows you to configure a passcode for the application, which you will have to submit each time you open it as a protection mechanism. The problem is the passcode is stored in the browser’s shared preferences unencrypted.
The OAuth tokens used for your Box account will also be stored unencrypted within SharePreferences inside box_auth_info.xml.
The previous version of Mercury Browser for Android (2.2.2) has been verified to have all the above vulnerabilities. Mercury Browser for Android (3.0.0) has only been verified of the insecure intent URL implementation vulnerability and it is assumed that the passcode log is still being stored unencrypted for now. VerSprite has validated that the version of the Mercury Browser for Android (2.2.3) is not vulnerable to the insecure intent URL implementation vulnerability, however has not tested and validated the unencrypted storage of the sensitive information above. It is recommended that all users running this browser on their Android devices not update to the latest version (3.0.0) on the Google Play Store.