SSL Pinning in Swift
Every Mobile application needs to retrieve information from the server to display it to the user. However, there can be some sensitive information shared between the application and the Server, for example, the username and password of the user.
With iOS 9, Apple provided App Transport Security (ATS), which forces the application to maintain a secure network connection by adopting HTTPS protocol and Transport layer security. This makes the application not communicate with a non-secure (http) connection. However, it is possible to bypass App Transport Security by setting up man-in-the-middle attacks that may use self-signed certificates. In this article, we will discuss how we can implement SSL pinning in iOS applications to secure network connections. We will also cover the basics of Transport Layer Security and man-in-the-middle attacks.
Transport Layer Security
Apple provides us App Transport Security (ATS), which allows us to transmit data over a secure (HTTPS) network by implementing Transport Layer Security (TLS). It enables us for the data sharing over a secure network in the following three steps.
In this process, the client trusts the digital certificate provided by the Server. A certificate works as identity proof for the Server. A certificate is a text file that contains the Server's information and follows X.509 standard. It must be signed by the trusted certificate authority.
In a man-in-the-middle attack, the attacker sets up an SSL proxy server to intercept the data being sent by the client to Server. The SSL proxy performs the encryption and decryption between the client and the Server. For example, Charles, which is a proxy server, works between the app and the Server and intercept the data for testing purpose. Charles works in the following phases.
SSL Pinning is a technique used in swift to prevent man-in-middle attacks. In this process, the app validates the Server's certificate again after the SSL handshaking. There is a local copy of trustful certificates maintained at the client's end and compare them with the Server's certificates at runtime. The connection is aborted in case if a mismatch between Server's certificates and local copy occurs.
One disadvantage of this technique is, it requires an app update whenever the pinned certificate expires. However, we can also violate this by also pinning future certificates in the application. Instead of pinning the whole certificate, we can use the hashed public key, which will be the same across the future certificates.
SSL Pinning is performed in the following two steps.
To implement SSL Pinning in the iOS application, we need to have a SecTrust object, which will be prepared with one or more certificates and policy objects. The SecCertificate object is provided by Apple to represent a X.509 certificate. We can retrieve the certificate from a bundle by using the following code.
As we now have a certificate, we can prepare a policy or use a standard basic policy for X.509 certificates. Consider the following code to prepare a policy.
We can also create our policy by calling SecPolicyCreateSSL(_:_: ), which accepts Server (bool) and hostname.
Apple provides SecTrust object to validate both certificates and policies. Implement the following code to validate certificates and policies.
We need to evaluate the SecTrust that we receive during a network call with the policies and compare the certificate with the pinned certificate.