Mobile security has become a hot topic. For any app that communicates remotely, it is important to consider the security of user information that is sent across a network. In this post, you’ll learn the current best practices for securing the communications of your iOS app in Swift.
When developing your app, consider limiting network requests to ones that are essential. For those requests, make sure that they are made over HTTPS and not over HTTP—this will help protect your user’s data from “man in the middle attacks”, where another computer on the network acts as a relay for your connection, but listens in or changes the data that it passes along. The trend in the last few years is to have all connections made over HTTPS. Fortunately for us, newer versions of Xcode already enforce this.
To create a simple HTTPS request on iOS, all we need to do is append “
s” to the “
http” section of the URL. As long as the host supports HTTPS and has valid certificates, we will get a secure connection. This works for APIs such as
NSURLConnection, and CFNetwork, as well as popular third-party libraries such as AFNetworking.
App Transport Security
Over the years, HTTPS has had several attacks against it. Since it’s important to have HTTPS configured correctly, Apple has created App Transport Security (ATS for short). ATS ensures that your app’s network connections are using industry-standard protocols, so that you don’t accidentally send user data insecurely. The good news is that ATS is enabled by default for apps built with current versions of Xcode.
ATS is available as of iOS 9 and OS X El Capitan. Current apps in the store will not suddenly require ATS, but apps built against newer versions of Xcode and its SDKs will have it enabled by default. Some of the best practices enforced by ATS include using TLS version 1.2 or higher, forward secrecy through ECDHE key exchange, AES-128 encryption, and the use of at least SHA-2 certificates.
It’s important to note that while ATS is enabled automatically, it doesn’t necessarily mean ATS is being enforced in your app. ATS works on the foundation classes such as
NSURLConnection and stream-based CFNetwork interfaces. ATS is not enforced on lower-level networking interfaces such as raw sockets, CFNetwork sockets, or any third-party libraries that would use these lower-level calls. So if you are using low-level networking, you’ll have to be careful to implement ATS’s best practices manually.
Since ATS enforces the use of HTTPS and other secure protocols, you might wonder if you will still be able to make network connections that can’t support HTTPS, such as when you download images from a CDN cache. Not to worry, you can control ATS settings for specific domains in your project’s plist file. In Xcode, find yourfile, right click it, and choose Open As > Source Code.
You will find a section called
NSAppTransportSecurity. If it is not there, you can add the code yourself; the format is as follows.
This lets you change ATS settings for all network connections. Some of the common settings are as follows:
NSAllowsArbitraryLoads: Disables ATS. Don’t use this! Future versions of Xcode will remove this key.
NSAllowsArbitraryLoadsForMedia: Allows loading of media without ATS restrictions for the AV Foundation framework. You should only allow insecure loads if your media is already encrypted by another means. (Available on iOS 10 and macOS 10.12.)
NSAllowsArbitraryLoadsInWebContent: Can be used to turn off the ATS restrictions from web view objects in your app. Think first before turning this off as it allows users to load arbitrary insecure content within your app. (Available on iOS 10 and macOS 10.12.)
NSAllowsLocalNetworking: This can be used to allow local network resources to be loaded without ATS restrictions. (Available on iOS 10 and macOS 10.12.)
NSExceptionDomains dictionary lets you set settings for specific domains. Here is a description of some of the useful keys you can use for your domain:
NSExceptionAllowsInsecureHTTPLoads: Allows the specific domain to use non-HTTPS connections.
NSIncludesSubdomains: Specifies if the current rules are passed down to subdomains.
NSExceptionMinimumTLSVersion: Used to specify older, less secure TLS versions that are permitted.
Perfect Forward Secrecy
While encrypted traffic is unreadable, it may still get stored. If the private key used to encrypt that traffic is compromised in the future, the key can be used to read all the previously stored traffic.
To prevent this kind of compromise, Perfect Forward Secrecy (PFS) generates a session key that is unique for each communication session. If the key for a specific session is compromised, it will not compromise data from any other sessions. ATS implements PFS by default, and you can control this feature using the plist key
NSExceptionRequiresForwardSecrecy. Turning this off will allow TLS ciphers that don’t support perfect forward secrecy.
Certificate Transparency is an upcoming standard designed to be able to check or audit the certificates presented during the setup of an HTTPS connection.
When your host sets up an HTTPS certificate, it is issued by what is called a Certificate Authority (CA). Certificate Transparency aims at having close to real-time monitoring to find out if a certificate was issued maliciously or has been issued by a compromised certificate authority.
When a certificate is issued, the certificate authority must submit the certificate to a number of append-only certificate logs, which can later be cross-checked by the client and scrutinized by the owner of the domain. The certificate must exist in at least two logs in order for the certificate to be valid.
The plist key for this feature is
NSRequiresCertificateTransparency. Turning this on will enforce Certificate Transparency. This is available on iOS 10 and macOS 10.12 and later.