Abusing WebView JavaScript Bridges

Android applications often use the WebView class to embed a browser component within an Activity in order to display online content. For example, the following code will show the Google homepage within an Activity.

An application can inject Java objects into a WebView via the addJavascriptInterface function. This allows JavaScript code to call the public methods of the injected Java object. Exposing Java objects to JavaScript could have some negative security implications, such as allowing JavaScript to invoke native phone functionality (sending SMS to premium numbers, accessing account information, etc.) or allowing JavaScript to subvert existing browser security controls such as the same origin policy. I could not find much information documenting how to exploit these issues, but an academic paper titled Attacks on WebView in the Android System explores a number of attacks and describes a situation in which a file utilities object is exposed to JavaScript code thus allowing attackers to manipulate the file system if an attacker can control any of the content rendered in a WebView via MiTM, JavaScript injection, or redirection attacks.

The paper goes on to state that “in our case studies, 30% Android apps use addJavascriptInterface. How severe the problems of those apps are depends on the types of interfaces they provide and the permissions assigned to them.” The following code exposes the SmokeyBear class to JavaScript, but only declares one public function that returns a string. Is this interface safe to expose?

Probably not. Prior to Android 4.2, if an application uses the addJavascriptInterface and allows an attacker to control the content rendered in a WebView, then an attacker can take control over the parent application regardless of the type of interface exposed contrary to popular belief. Consider the following code that uses reflection to acquire a reference to a Runtime object via the SmokeyBear interface in order to write an ARM executable to the target application’s data directory and then execute it via Linux commands. The executable in this case sends all files stored on the SD card to a remote server (steal photos, videos, and any other data improperly stored on the SD card). This type of payload works against unrooted and rooted devices, since anything on the SD card is world readable and writable. If the attacker wants to break out of the Android application sandbox, an attacker could use this same technique to drop a root exploit onto the device (gingerbreak, rageagainstthecage, zergRush, psneuter, etc.) and then execute it.

Applications targeted to API level 17 (Android 4.2), and above in the future, protect against the previous reflection-based attack by requiring programmers to annotate exposed functions (@JavascriptInterface), and I’m assuming the getClass function is missing this annotation, but currently only 0.8% of devices support API level 17, so we can’t realistically recommend using annotations to prevent this type of attack for a couple years. So, how should we recommend our clients fix the issue?

Use addJavascriptInterface only if the application loads trusted content into the WebView component (Internet || IPC == sketch).

Develop a custom JavaScript bridge using the shouldOverrideUrlLoading function. An application could check the newly loaded URL for a custom URI scheme and respond accordingly, but be careful about what functionality you expose via this custom URI scheme, and use input validation and output encoding to prevent the standard injection attacks.

Reconsider why a bridge between JavaScript and Java is a necessity for this Android application and remove the bridge if feasible.