Friday 19 July 2013

Android webview security loadDataWithBaseURL

A quick lesson in web views in Android. Normally they are a big risky area, be it adding JavaScript interfaces (http://labs.mwrinfosecurity.com/blog/2012/04/30/building-android-javajavascript-bridges/), or just generally enabling javascript and opening yourself up to webkit exploits (which given how little the OEMs update their firmware, is not hard to do).

So another interesting bit to concern yourself with is found on the following page's code:
http://www.androidsnippets.com/webview-with-custom-html-and-local-images

The code is as follows:

/**
 * This code loads a custom HTML from a string which references a local image
 * - for this to work, simply place the image in the directory /assets/
 */
 
public void loadHTML() {
    final String mimeType = "text/html";
    final String encoding = "utf-8";
    final String html = "

Header

Custom HTML "; WebView wv = (WebView) findViewById(R.id.wv1); wv.loadDataWithBaseURL("fake://not/needed", html, mimeType, encoding, "");

The problem is with the loadDataWithBaseURL's first argument. This defines how relative links on the page should be dealt with. Normally setting it to null or "" is enough, although this obviously produces invalid links. A better way is to use "file://android_asset". The problem with "fake:" is that if any other app registers for this custom url scheme, they will receive the link and start one of their activities.

Not a bad issue, unless the url has sensitive data in it right? Well as a malware writer, this is could still be useful. Imagine if this screen is part of the Facebook app and has a relative link on it, or has JavaScript that changes the window.location to a relative page. All the malware needs to do is dress the pop up screen in nice Facebook attire and ask the user to re-enter their creds. It doesn't even require the malware app to request any permissions from the user.

To fix it, just set the baseurl to null, or include a custom webview client (setWebViewClient)