Android WebView Class Poses Significant Security Risk

Tencent Security Labs recently reported a vulnerability that exists across some common apps. The report can be found at http://www.cnvd.org.cn/webinfo/show/4365. The issue, which has been around since 2014, has to do with the misconfiguration or misuse of the WebView class.

The Android WebView class is used to display HTML pages such as the  UI or online content. WebView uses the WebKit rendering engine, which is  included in many web browsers. The engine allows the user to navigate  forward and backward, zoom in and out on a web page, and process  JavaScript in the HTML document.

The following is an example of using WebView:

WebView webView = findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadUrl("http://www.example.com");

JavaScipt is disabled in WebView by default, though the user can enable it. WebView settings also provide methods to interact with other content, such as:

  • setAllowFileAccess

Enables or disables file access in WebView. Note that the assets and  resources are still accessible even if file access is disabled.

  • setAllowFileAccessFromFileURLs

Enables or disables the JavaScript in the file scheme URL from  accessing content from other file scheme URLs. This setting is  overwritten by setAllowUniversalAccessFromFileURLs

  • setAllowUniversalAccessFromFileURLs

Enables or disables the JavaScript in the file scheme URL from accessing content from any other source.

In web applications, there is a “same-origin policy,” which is used  to restrict JavaScript on the page from accessing a user’s most  important data. The browser’s policy is to check for protocol, host and  port in URIs.

A brief sample of URIs compared with URL http: //www.example.com/index.html under the same-origin policy are shown below:

URL                                                             same-origin or not, and description

http: //www.example.com/index2.html        ; same-origin

https: //www.example.com/index.html        ; Not same-origin, protocol is different

http: //example.com/index.html                    ; Not same-origin, host is different

http: //www.example.com:88/index.html   ; Not same-origin, port is different

file:///data/local/tmp/index.html                ; Not same-origin, protocol and host are different

WebView implements the same-origin policy. If the JavaScript is used  in the HTTP scheme, it can’t access the file scheme URLs. Normally,  Android apps are running in separate processes. For instance, App A is  not able to access the private data for App B, and vice versa. However,  if setAllowFileAccess and setAllowUniversalAccessFromFileURLs are enabled, App A can run the exported activity from App B and pass  the malicious file scheme URLs to the WebView in App B to access the  private files in App B.

App B contains WebView which accepts the following parameter url:

WebView webView = findViewById(R.id.webView);
webView.loadUrl(url);

If App A passes a file scheme url “file:///data/local/tmp/index.html” as the parameter “url” for the webView.loadUrl(url) in App B

The index.html file has the following content:

<html>
<head>
<script>
function readfile() {
    alert(document.getElementById('iframe').contentDocument.body.firstChild.innerHTML);
}
</script>
</head>
<body>
<iframe id='iframe' src = "file:///data/data/com.test.webv/abc.txt" onload='readfile()'> </iframe>
</body>
</html>

App A accesses the private file from App B “/data/data/com.test.webv/abc.txt”. In the above sample, the attacker must have the ability to drop the malicious HTML document into the user’s device.

Workarounds for this potential WebView vulnerability include:

  • Disable file scheme URLs in the app if file access is not needed. This can be accomplished by setting methods setAllowFileAccess as false. Since files in assets and res folder are not affected by  these settings, some fixed HTML can be placed in these folders.
  • Check for file scheme URLs to eliminate directory traversal attacks.
  • If the app doesn’t use JavaScript in a WebView, set method setJavaScriptEnabled as false.
  • If activity export is not needed, set android:exported=”false” in the Activity tag in Manifest. Otherwise check the passed parameters for the WebView.