- XAML Hot Reload for Xamarin.Forms
- Xamarin Community Standups
- Xamarin Chat on Slack
- Xamarin.Forms 101 on YouTube
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
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.
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:
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.
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 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.
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.
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:
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.
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:
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:
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.
I’ve updated my previous post “The many flavors of HttpClient” with current information on everything you need to know about HttpClient on Xamarin.
I co-authored a blog post with my co-worker Robin Wiegand on bringing Xamarin and Cordova together. Enjoy!
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:
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
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
Alternatively, you can use ModernHttpClient by handing a
NativeMessageHandler to the HttpClient constructor which will also use native implementations for making HTTP calls.
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
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:
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.
Here’s an update on the current state of
AndroidClientHandleryour Android project’s properties page, just as you already could for iOS.
BoringSSLinto their codebase. For Android, this option is also selectable in your project’s properties page.
BoringSSLalso brings TLS 1.2 to the Unix/Linux implementations of Mono.
ServicePointManager. Thomas Bandt wrote an excellent blog post on how to get certificate pinning working with ModernHttpClient and even
And here’s the updated matrix: