#wedskaas: What every developer should know about app security, part 2: Why you should be using certificate pinning

HTTPS is on the rise. This is a good thing. HTTPS ensures your network communication is encrypted in both directions, protecting your app’s users. If you write the code

you are basically doing the same as a user entering the URL into the browser’s address bar would do. The user agent does a handshake with the host you specified, retrieves its certificate and checks the validity of that certificate according to a few criteria, e.g., host name, expiration date, revokation, and trust chain. Let’s have a look at a certificate, in this case the one for www.microsoft.com:

You can see details such as the expiration date or the host names the certificate is valid for. You can also see the certificate chain. This certificate was issued by the certificate authority “Microsoft IT TLS CA 4”. And its certificate was issued by “Baltimore CyberTrust Root”. Baltimore CyberTrust Root is in the list of trusted root certificates of most operating systems and that is why I can connect to https://www.microsoft.com/ without getting an error message.

This root certificate list is unfortunately the weakest link in the entire HTTPS story. Most users don’t check which root certificates are installed on their machine. There have been cases where computer vendors added their own certificate to the root certificates list. And there are also numerous companies that install the company’s root certificate onto each employee’s device so they can monitor all traffic by doing a man-in-the-middle attack.

For the browser story, this is currently the only way to make sure your browser can connect to all HTTPS servers on the internet, even those it has never contacted. But for a connection from a mobile app to its backend, you usually know exactly which server you’re connecting to. From a security perspective, it is a good idea to take advantage of this.

Check which server you’re connecting to

The most effective thing you can do is to get the root certificate list out of the picture. If you control the server and the certificate on the server, you can check if the certificate is the exact certificate you are expecting. You can do this by comparing if certificate’s public key is the one you are expecting. Here’s how to do that with .NET:

This code replaces the default certificate validation with custom code. This code compares the public key of the server’s certificate with the expected pubic key of the server. This public key corresponds with the private key that is installed on the server. Since it is not possible to derive the private key from a public key, this means that we can guarantee we’re talking to that one server and not any server our operating system happens to trust.

This code has a couple of limitations you should be aware of:

  • It only works for this one server. If you have multiple servers you’re connecting to with different public keys, you’ll have to differentiate her.
  • This code does not account for changes to the server certificate. In the case of connecting to a server you don’t control yourself, the certificate could be changed at any point which we require an update of the app for it to work again.
  • You could check other criteria, e.g., the certificate’s expiration date.

An alternative you can think about is rolling your own certificate authority and pinning not the certificate itself but the certificate authority. Even though a browser would not trust such a certificate from an unknown certificate authority, a mobile app would work just fine.

Only allow up-to-date TLS

What is commonly referred to as SSL (Secure Sockets Layer) was actually renamed to TLS (Transport Layer Security) in 1999. TLS 1.2 is the current version and TLS 1.3 is expected to be finalized soon. All older version, including SSL 2, SSL3, TLS 1.0, and TLS 1.1 should not be considered sufficiently secure anymore at this point. At this time, TLS 1.2 should be used for all communication.

When using default settings, both the client and server will allow downgrading the connection to an older standard as part of the initial handshake. This is to allow new clients to connect to old servers and to allow old clients connect to new servers. But since we’re controlling both client and server, there is no reason to allow downgrades to the not sufficiently secure TLS version 1.1 or lower. The solution is to force both the client and the server to only allow TLS 1.2 connections. With HttpClient in .NET, this is done like this:

If you’re using Azure Websites as your backend, here’s an article on how to disable older TLS versions.

Xamarin-specific issues

Xamarin developers will have to be aware that there are different implementations of HttpClient available and not all support TLS 1.2 or other security features. For help on picking the right HttpClient, I wrote a blog post entitled The many flavors of HttpClient.

Summary

Pinning both the certificate and the TLS version will make it much harder to intercept the communication between your app and its backend. It should be employed whenever making calls to a backend within the control of the app developer.

Other post in this series

#wedskaas: What every developer should know about app security, part 1: How to handle API keys

A few weeks ago at Xamarin Dev Days Graz I was asked a question I’ve been asked many times before: How do I obfuscate my mobile app’s code? My answer is always a counter-question: What are you trying to achieve by obfuscating your code? I’ve gotten different answers to this question and I want to dig into some answers I’ve received in the past in this blog post series.

A common answer is that there is some key or certificate that needs to be protected in the code.

I don’t believe code obfuscation is a good solution to this problem. I believe there typically isn’t anything that requires obfuscation inside an app’s code. Any attempts at hiding things inside an app’s code will only increase the effort it takes to get at that information but will not prevent it.

Some solutions I’ve heard for hiding a key inside the app code:

  • Encrypt the key (using which key?)
  • Assemble the key from strings in different portions of your source code
  • Hide the key in the last bytes of an embedded image
  • Use a code obfuscation tool
  • Don’t put it into the app’s code at all but load the key from a backend after the app has been installed

Let’s look at API keys

Let’s look at why these keys are there in the first place. In most cases, the key is used to authenticate the app towards a backend which is commonly referred to as an API key. For example, if you look at the Parse SDK Getting Started in the Xamarin Component Store, you’ll find this:

What the API expects here is a unique app ID and a key. The key gives you access to your data on the backend. The big problem here is that this one key is being used by all instances of the app.

A team at the University of Paderborn did an experiment to see if they could find that key inside app bundles in the Google Play store for apps that were using Parse. Using a simple static code analysis was enough for some apps but combining that with a dynamic (runtime) analysis was enough to retrieve the API key for all apps that were analyzed. Think about it: At some point, the app will have to call the method ParseClient.Initialize() with the plaintext key in memory.

The team then went on to analyze what they could access using those extracted API keys. The least information they could get for each app was a list of verified user email addresses. In many cases, they had complete read or even write access to all database tables for each app’s backend. The data found ranged from pictures, location information, contact information, and sales information to data gathered by trojans (yes, even the bad guys used Parse as a backend).

Parse is just an example here. You can find these API keys used in many backends and there is hardly an app out there that does not use any API keys. Anyone who extracts that API key can do whatever is allowed with that API key. This may or may not be a problem depending on what type of API key is at hand. It’s important to put yourself into the position of an attacker: What could someone who gets ahold of your API key do with that key?

In the case of Parse, it would have been possible to add user management and additionally authenticate users to access resources. That way, the API key itself would not have allowed access to all this data.

Authenticate the user, not the app

If you’re designing your own backend, you need to think about what type of data it is you are exchanging with your backend. Sometimes it may be OK to have your app access data from the backend without providing any credentials. This may be true for information you could also put on an unauthenticated website. But many times, you will be exchanging non-public information with your backend. In this case, it is always better to authenticate not the app but each user. The advantages are:

  • You can fully control what each user can see, even after your app has been distributed.
  • You can revoke access for individual users without breaking access for all other users.

If an API requires an API key, call it from your backend

If you do have to use a service that requires an API key, it is usually best to not make that call from within your app. A better approach is to make an authenticated user request the information from your own backend and then let your backend make the 3rd party API call on behalf of the user. The advantages here are:

  • It is not possible for an attacker to extract the API key and use your account to access the 3rd party API.
  • You can control how many calls are made with your API key.
  • You can cache results from the API and reduce the number of calls necessary.
  • You can block individual users from using the 3rd party API.

To hear more about this topic, you can watch my Xamarin Evolve talk on app security or stay tuned on this channel for more posts in this blog series.

Other post in this series

The many flavors of HttpClient

HttpClientHandler

When using Xamarin, you can use the standard .NET HttpClient. By default, HttpClient is Mono’s complete reimplementation of the entire HTTP stack. It is sufficient for many use cases but there are other alternatives out there that can be defined by selecting an alternative HttpClientHandler. For my Evolve talk, I put together an overview of the different HttpClientHandlers you can use:

HttpClientHandlers

CFNetworkHandler (iOS 6+) and the new NSUrlSessionHandler (iOS 7+, starting with Xamarin.iOS 9.8) are the handlers that utilize Apple’s native APIs instead of the Mono implementation. You can define which handler the HttpClient default constructor will use either in the IDE or by providing an argument to mtouch (e.g., --http-message-handler=NSUrlSessionHandler).

iOS options: HttpClientHandler

For Android, there is now AndroidClientHandler (starting with Xamarin.Android 6.1). There is no IDE option for defining the default handler yet but you can define it using the @(AndroidEnvironment) build action on a text file in your Android project to define an environment variable XA_HTTP_CLIENT_HANDLER_TYPE to the value Xamarin.Android.Net.AndroidClientHandler.

Alternatively, you can use ModernHttpClient by handing a NativeMessageHandler to the HttpClient constructor which will also use native implementations for making HTTP calls.

SSL/TLS

The default Mono implementation does not support the newest (and most secure) TLS standard 1.2 while the native handlers do. To use TLS 1.2 with the Mono implementation, Xamarin.iOS 9.8 introduced the option to swap the TLS implementation with P/Invoke calls into the Apple’s TLS implementation. This can be selected either in the IDE or by adding the --tls-provider=appletls option to mtouch‘s options.

iOS options: TLS

For Android, there is no such option but it is expected that BoringSSL support will be added soon.

Here’s the summary slide I showed in my talk:

HttpClient comparison

Xamarin have actually gone through the trouble of reimplementing the TLS code to support TLS 1.1 and 1.2. However, it is expected that it will be abandoned because of security considerations in favor of the native platform implementations, just as Microsoft has done for Windows.

Update (2017-02-15)

Here’s an update on the current state of HttpClient:

  • You can now specify that you want to use AndroidClientHandler your Android project’s properties page, just as you already could for iOS.
  • As expected, Xamarin have added TLS 1.2 support to the Mono (non-native) HttpClientHandler by incorporating Google’s BoringSSL into their codebase. For Android, this option is also selectable in your project’s properties page. BoringSSL also brings TLS 1.2 to the Unix/Linux implementations of Mono.
  • Contrary to my previous knowledge, ModernHttpClient does support certificate pinning using ServicePointManager. Thomas Bandt wrote an excellent blog post on how to get certificate pinning working with ModernHttpClient and even AndroidClientHandler.

And here’s the updated matrix:

HttpClient comparison

Wow, I’m a Microsoft MVP!

On April 1, 2016, I was awarded the Microsoft MVP status for “Visual Studio and Development Technologies”. It is an incredible honor for me and I am still a little in shock. Already, I’m seeing new information pour in and new connections being made and I am really excited about the road ahead.

The shocking part for me was that I had concentrated my community work almost entirely on Xamarin technology. In October 2015, a change in the MVP program categories meant Xamarin was now one of the award category technologies (hey, even Java is on that list!).

MVP Award Categories

I was nominated by Microsoft Technical Evangelist Daniel Meixner at the end of 2015 (thank you very much!), then there was a review, and apparently, my contributions were sufficient for the award committee.

I don’t plan on decreasing my efforts in 2016. I contributed to the MvvmCross 4.0 release at the beginning of the year, I’ve already done two public presentations, and I’ve found the time to blog. With Xamarin Evolve around the corner (where I’ll also be speaking) I’m anxious to find out which direction Xamarin and now Microsoft are going to take the cross-platform adventure we’re on. The announcements at Build made me very happy, personally, and I’m looking forward to sharing the knowledge with more people.

If you want to hear one of my presentations, keep an eye on my public speaking list where I’ll also be posting links to any videos or slides in case you missed the talk.

Above all, many thanks to my employer Zühlke who is supporting my community activity with time and money!

Calling C/C++ libraries from Xamarin code

The Xamarin platform allows developing iOS and Android applications entirely in C#. Sometimes, however, some legacy code may be too large or complex to make porting it to C# for your mobile app worthwhile. Most examples found online show you how to use existing Objective-C libraries in Xamarin.iOS and existing Java libraries in Xamarin.Android. However, it is entirely possible to call C code from a Xamarin app. Microsoft’s recent support for C/C++ on iOS and Android in Visual Studio can make this a simple task.

You will need the sources for the code you want to call to compile it for iOS and Android. The code cannot access any libraries which you only have binaries for that have been compiled for other platforms.

To get started, create a new C++ cross-platform project using Visual Studio 2015.
Create new cross-platform project
You will need to have the corresponding Visual Studio package installed to have this option available.
Visual Studio Setup Cross-Platform Mobile C++
This will create three projects: one for Android, one for iOS, and a shared project.
Project structure

It is important to understand the shared project concept for this. The code in the shared project does not result in a DLL or library being generated. A shared project can hold any type of file. Projects referencing the shared project can access code from any file in the shared project. The code will then be compiled in the context of the referencing project. If code is not referenced, it is not compiled. For this reason, it is necessary to have calls into all code needed contained in the platform-specific projects. This means that the platform-specific C/C++ projects need to contain code, too. This code can be identical in the Android and iOS projects and reside in the same files. Unlike in .NET projects, file linking is not needed for C++ projects; source code files do not have to reside inside a project’s folder or subfolder.

In the example, I’ve created a simple function clib_add_internal() that add two integers and resides in the shared project.


This code is called from a function in the platform-specific projects.

For the example code, this doesn’t make any sense. For a real project, you will put any call that needs to be directly invoked from the .NET code (your interface) into the platform-specific projects while underlying code can reside in the shared project.

The calls from .NET will be using P/Invoke since C++/CLI is not available on iOS or Android. So the basic P/Invoke rules apply for your interface’s code: Either the code is plain C or, if you are using C++, the calls are either plain functions or static methods and contain only POC parameters and return values.

For the iOS project, the output format needs to be changed to a static library (.a file) since iOS does not allow dynamically loading code. For Android, a dynamic library (.so) should be built.

iOS Settings
Android Settings

While the Android library can be compiled within Visual Studio, compiling the iOS library needs a connection to a build agent on the Mac. This is not the regular Xamarin.iOS installation on a Mac but a Microsoft tool that is installed on OS X using npm. Visual Studio will communicate with this tool through TCP/IP.

Connection to build host

To call the native code, create a Xamarin project for iOS and Android each. Include the native libraries in the respective Xamarin projects.

On iOS, if you’re targeting multiple processor architectures (either supporting pre-iPhone 5s or supporting the simulator), you can build the iOS project for multiple platforms using the dropdown in the toolbar. Then, combine the libraries into one using lipo according the Xamarin docs. On Android, you’ll need to modify the .csproj according to the Xamarin documentation to specify the .so files for each platform.

The calls into the native code are regular P/Invoke calls (although DLLs don’t play a role here). On Android, you specify the name of the shared library.

On iOS, use the special Mono name __Internal to call into the static library.

And that’s it! You can find the example code at https://github.com/lothrop/XamarinNative. In the example, I put the C# marshaling code into another shared project that is referenced by the Xamarin.iOS and Xamarin.Android projects.

iOS User Interfaces with MvvmCross

When using MvvmCross in a cross-platform mobile project you have the choice of four different approaches for creating the iOS user interface. Xamarin.Forms is one of those approaches that can be a good choice for many use cases (even if there is not graphical designer at this point). However, if your view has very specific visual requirements, it may be necessary to create a native view. There are three different ways you can do this:

  • Hand-coded: Create all visual elements in code. This approach is more widespread on iOS than on most other popular platforms. It gives you the advantage of having the maximum control possible over your user interface.
  • XIB files: XIB files are XML files that describe the visual elements. XIB files are typically not edited by hand but created using Xcode’s Interface Builder. Since Xamarin 4, XIB files can also be visually created and modified in Xamarin Studio or Visual Studio.
  • Storyboard files: This is the newest approach. Storyboards are also XML files visually edited with Xcode, Xamarin Studio, or Visual Studio yet they contain not only a single view but a series of views along with the workflow to navigate between these views.

MvvmCross supports all three native approaches.

Hand-coded

This approach obviously produces the most code. It may be challenging for people new to the platform but it saves you the hassle of battling with the UI designers.

XIB files

If you’re already on Xamarin 4 and prefer a visual editor, this is likely the best choice for you. Create a new XIB View Controller file using Xamarin Studio or Visual Studio. The ViewController code will also be created for you. All you need to do for MvvmCross is to change the base class from UIViewController to MvxViewController. In the example, three UI elements were created using the designer and were given the (not so creative) names UiLabel, UiTextField, and UiButton. These elements are then referenced in the data binding code that is common to all three approaches.

Setting element names

Storyboard files

The big advantage of storyboards, the ability to design your screenflow in the designer, does not fit well with MvvmCross’s cross-platform navigation approach. If you define a transition from view A to view B in the designer it will only apply to the iOS platform. It is typically a better idea to move this navigation logic down into the cross-platform code inside your ViewModels. That is why it’s best to use a one-ViewController-per-storyboard approach when using storyboards in MvvmCross.

Setting the storyboard ID

In the editor, you need to set the storyboard ID to the name of your ViewController. As with the XIB approach, change the base class from UIViewController to MvxViewController. Create a constructor taking an IntPtr and passing that on to the base class’s constructor. The last step is to add the [MvxFromStoryboard] attribute to the class.

Summary

The good thing is: You don’t have to make this decision at project start. MvvmCross supports implementing your view with the technology that is best for each view. You only need to ensure you don’t have multiple views for the same ViewModel and the same platform.

I’ve updated the example in the MvvmCross Starter Pack Nuget (starting with 4.0.0-beta8) to use a XIB file instead of the previous hand-coded approach with absolute coordinates (from the auto layout days). That should make it easier for people to get started.

Making your iOS views scrollable

If you’re using iOS auto layout (you should) and you’ve ever tried to add a scroll view in Interface Builder or the Xamarin iOS Designer you might have noticed that it is not an easy task. If you’re interested, here are some instructions. This is especially true if you only realize that you need a scroll view after designing your view (after you’ve realized that the keyboard covers up parts of the view).

Here’s code to inject a UIScrollView at runtime to solve all your worries. Add this code to your base UIViewController for all controllers that should be vertically scrollable.

In Interface Builder or Xamarin iOS Designer you’ll need to make sure you’ve not only defined constraints for the vertical position of your elements but also a constraint to define the distance from the bottom of the bottom element to the bottom of the your view controller’s view. That way, you’ll have defined the vertical size of the scroll view’s content view.

Building secure apps: Need help from app store operators

Communicating securely between a mobile app and a the corresponding backend is not a trivial task. Sure, nowadays we can write https and almost be certain our app is actually having encrypted communication with the right backend. However, just recently, I decided to do a communications check of apps on my iPhone using Fiddler as a proxy and was surprised to find that I could do a man-in-the-middle attack for an app I use regularly without the app noticing this. Apparently, the developers had opted to disable certificate validation (perhaps so the app would work with a developer backend that doesn’t have a pricey SSL server certificate installed) and forgot to turn it on again before publishing the app to the store.

However, there is an even better way to solve that problem that doesn’t involve buying an SSL server certificate. It’s called certificate pinning. Instead of relying on the operating system to check the validity of the presented server certificate by looking at its list of root certification authorities (which may contain entries the user is not aware of, see Superfish) developers can instruct their https calls to only accept a specific server certificate or, better yet, only certificates issued by a specific certification authority. This is not only much safer, it also avoids the costs of buying SSL server certificates.

So there we are, we have a method to ensure our app is talking to the right backend. The trickier part, though, is ensuring that whoever is making the call to our backend is actually who we think they are (i.e., our own app).

A simple approach to this problem would be to include an SSL client certificate in all requests to the backend, using a certificate whose private key is included as part of the app bundle. The problem with this is that it’s just not possible to hide the certificate well enough in our bundle to make it impossible to extract that certificate and its private key through reverse engineering. And since all clients would be using the same certificate, having that certificate compromised means we cannot tell if it’s acutally our app that is calling the backend.

The solution to this problem is to issue individual SSL client certificates to each device that is accessing the backend.

The vendors of Mobile Device Managament (MDM) software have great solutions that do exactly that. The problem is that these solutions can only be applied to devices that are in full control of the MDM solution. That’s great for internal apps on company devices but doesn’t help at all for apps you’re distributing to others.

Here is my proposal: App store operators should include a method to create an unique SSL client certificate upon installation of the app that is signed either using a certificate (public and private key) the app creator uploads into the app store or a certificate created by the app store vendor. This would make it very easy to check on the server side if a request is coming from an app that was actually distributed through the app store (and paid for, in the case of non-free apps) by using the signing certificate’s public key.

Such a feature could also be included in cloud backends like Azure Mobile Services where one could limit requests only to genuine apps and provide the corresponding functionality the client libraries accessing the backend.

All in all, this approach would greatly increase app communication security without much effort for the app developer. Now, how to convince the app store operators?