Intro

Mobile applications nowadays make heavy use of WebViews in order to render their user interfaces. Frameworks such as PhoneGap / Apache Cordova are even used to implement most of the application’s functionalities using WebViews only.

While native code, both in Android and in iOS, can quickly be analyzed using dynamic analysis tools like Frida, operations performed in WebViews cannot be easily debugged with the same methods.

Debugging WebViews

In Chrome there is a nice solution (actually, a similar solution is available in Safari) to debug WebViews, by using the Chrome DevTools. Open Chrome and type chrome://inspect/#devices

DevTools showing one debuggable WebView in the PhoneGap Demo App

After having clicked the inspect link, the WebView can be inspected and debugged like a web application. The example shows the PhoneGap Demo App:

Working with DevTools: On the left the simulated view of the app; on the right the resources and code of the application

More on remote debugging Android devices can be found here.

The only precondition for this solution to work, is that the app needs to be debuggable or at least the WebViews need to have the flag WebContentsDebuggingEnabled set to true. While these options are commonly enabled during app development, this is not the case anymore when the application is deployed using the Google Play Store.

Enabling Debug Option on WebViews

In order to make the app debuggable, there are principally two methods that can be used. Either statically by decompiling the app, modifying the Android Manifest and recompiling it, or my preferred option to do it dynamically at runtime with a Frida script.

In order to change the WebView we need to hook a Java function. Ideally, a function that is used by all apps, to implement a universal solution that will always work. A function that is likely used by all apps using WebViews is the onTouchEvent, the event that is triggered every time the user touches the screen. The onTouchEvent is also very handy for our purpose because it is easy to trigger, just tap somewhere in the app and it will be executed. Here is the Frida script that will enable the debug mode for the current WebView:

Java.perform(function() {
   var Webview = Java.use("android.webkit.WebView")
   Webview.onTouchEvent.overload("android.view.MotionEvent").implementation = 
   function(touchEvent) {
     console.log("\n[+]Hooking onTouchEvent");
     console.log("[+]Setting setWebContentsDebuggingEnabled() to TRUE");
     this.setWebContentsDebuggingEnabled(true);
     this.onTouchEvent.overload("android.view.MotionEvent").call(this, touchEvent);
   }
});

After having run the script one can unload the Frida script, otherwise it will fire on every subsequent touch.

Testing the Solution

While testing the solution on different apps, I noticed a strange behavior. After running the Frida script on one particular app a debuggable WebView showed up in the Chrome DevTools. However, instead of the name of the open app being shown “Chrome (77.0.3865.92)” was reported.

Chrome was reported as debuggable instead of the app name

I double checked the setup and verified that only the app to be analyzed was running on the phone and no Chrome instance was open. What was going on here?

Chrome Custom Tabs

The app used Chrome Custom Tabs. Chrome Custom Tabs is an alternative to WebViews. The app will use the installed Chrome browser within the app to render webpages. With Chrome Custom Tabs you get automatically all security features of Chrome. The usage will be more user-friendly by having for example synchronized AutoComplete functionality across devices for better form completion and session information can be shared between app and browser.

But what are the security consequences of using chrome custom tabs in your app?

First of all, session information like cookies will be shared with the browser and with all other apps that use Chrome Custom Tabs. Let’s assume an app has implemented with native language a PIN screen to unlock the app and afterwards uses Chrome Custom Tabs to manage all other functionalities of the app. In such a case, the local PIN screen could be bypassed by just opening the browser and navigate to the endpoint of the app. Furthermore, using Chrome Custom Tabs will also expose the app to common web application attacks that are not possible on native apps, such as Cross-Site Request Forgery or Clickjacking attacks.

Finally, if the app performs certificate pinning to secure the communication to its backend, the endpoints accessed via Chrome Custom Tabs will not profit from this security measures. Even worse, different than native apps (targeting Android version 7.1 and later), Chrome generally trusts user imported certificates when connecting to a server. This could be abused by tricking a victim into importing a malicious CA certificate into their Android trust store to perform man-in-the-middle attacks on apps using Chrome Custom Tabs.

CSRF Attacks on Mobile Phones

I’ve created a simple demo video showing what could happen if you use Chrome Custom Tabs in your app. For the purpose I have created two different applications on my servers, one simulating a vulnerable application (www.application.ch) and another simulating a malicious server (hacker.com). In the demo, I will first try to login with the user hacker to show that the user does not exist in the system (“User does not exist.”). Then I use the admin user. The app then is closed but the session cookie remains stored in Chrome (note here that the cookie from www.application.ch was a session cookie. Chrome for Android keeps it stored also after having closed the browser, there is an issue in chromium about this behavior but is marked as WontFix). Afterwards, the victim will open a link pointing to hacker.com. This will be opened in the email app, that also makes usage of Chrome Custom Tabs. The malicious website will automatically create a new user on www.application.ch with a Cross-Site Request Forgery attack. At the end of the video I show that the user hacker can now log in to the application.

The HTML code of the malicious website contains an auto-submitting form pointing to www.application.ch:

<iframe name="formDestination" width="1px" length="1px"></iframe>
<form name="myForm" action="http://www.application.ch/create-user.php" method="POST">
   <input type="hidden" name="user_name" value="hacker" />
   <input type="hidden" name="password" value="hacker" />
   <input type="hidden" name="display_name" value="hacker" />
   <input type="hidden" name="email" value="hacker@hacker.com" />
</form>
<script type="text/javascript">
 window.onload=function(){
    document.forms["myForm"].submit();
 }
</script>

Conclusion

I’m using Chrome Custom Tabs in my application, should I panic?

No, probably not. If your application is resistant against classical web application attacks like Cross-Site Request Forgery or Clickjacking attacks you should be safe. Of course, the fact that certificate pinning cannot be easily implemented with Chrome Custom Tab should be evaluated as a possible threat. The fact that a valid session of the user remains stored in the Chrome browser and in all other apps using Chrome Custom Tabs even after the browser is closed should also be reviewed.

Is there something similar in iOS?

Yes, a similar functionality is present in iOS and is called SFSafariViewController In iOS 9 and iOS 10 it shares cookies and other website data with Safari. If you used SFSafariViewController with these older iOS versions, the CSRF attacks should be possible. Starting with iOS 11, SFSafariViewController will not automatically share session data with Safari anymore, therefore by default you’ll be safe. If the developer wants to share session data with Safari he can do it with the Class ASWebAuthenticationSession. As stated on the description of the class, All cookies, except session cookies, can be shared with the web browser. Some tests performed on apps using ASWebAuthenticationSession in iOS 11 confirmed this behavior: Session cookies were not shared between apps and Safari.

Do you want to know more about mobile security topics regarding both Android and iOS applications? Then join us during the upcoming Secure Mobile Apps course taking place at the beginning of November in Zurich. We will cover many security related topics relevant to mobile application as well as performing several hands-on challenges. Further details can be found on our web site (German only): https://www.compass-security.com/en/services/security-trainings/secure-mobile-apps-november-2019-zuerich/