First of all, let me say that all that follows is public knowledge and is somewhat described in the Android docs. However, I haven’t seen much discussion, so I thought it’s a good idea to write a blog post.
####Local File Access Things get complicated when a webview loads an HTML page from the local file system, either by design or by mistake.
Up until Android API 16 (version 4.1) Android WebViews treat everything loaded via a
file:// URL like it belongs to the same origin, for Same Origin Policy purposes.
file:// URL can read any file on the filesystem that the application can, including any files in the application’s internal storage.
######HTML files in insecure locations
Say that a WebView loads a local HTML file from an insecure location (e.g. the SDcard) using the
######HTML files loading JS insecurely
Say that a WebView loads a local HTML file, which is stored in private store, thus cannot be edited by a third party application. However, this local HTML file also uses
If the attacker can perform a Man-in-The-Middle attack on the the request that fetches the remote JS file, he can insert his code, which will be able to read private application files.
######WebViews accepting URL via non-validated intents WebView components commonly retrieve the URL to be loaded into the webview using intents from a different part of the application. If a malicious application is able to send an intent with a malicious URL, then the WebView can be forced to load an attacker’s local HTML file, enabling the file-retrieval attack.
There are multiple mitigation techniques.
Second, if receiving the URL to be loaded via an intent, make sure to validate the URL and the sender - set components to non-exported or apply permissions as needed.
Third, you can (and should) disable local file access support, unless absolutely nesecary. Access to the local file system (e.g. loading a file in a WebView) is enabled by calling
WebSettings.setAllowFileAccess(). By default, WebViews have file system access enabled. Use
Finally, also use
WebSettings.setAllowUniversalAccessFromFileURLs(false). These methods exist in API 16 and later and are false by default, but it’s probably a good idea to make sure of the defaults.
~TODO: add some example code