A while ago an application we’ve been working on was submitted to a penetration test during which a possibility of man in the middle attack was exploited. We then embarked on a journey to find the best solutions & stumbled upon multiple options so we decided to gather all our findings in this series.
In this first part, we'll dive into the basics: what a man-in-the-middle attack is, why HTTPS alone isn't enough, and how SSL pinning can be a game-changer. Let's start by understanding the problem we're trying to solve.
What exactly is Man in the middle attack?
It’s a cyberattack in which the attacker intercepts and potentially modifies the communication between two parties who mistakenly believe they are communicating directly with each other.
You might be thinking that communication over a secure network using HTTPS should do the trick. You’d be mistaken.
Even though it surely reduces the risk, HTTPS relies on digital certificates from trusted Certificate Authorities (CAs) to verify the identity of websites. If the attacker was able to create their own certificate or worse if a CA is compromised and tricked into issuing a fake certificate, he can then perform a MITM attack by impersonating a legitimate website.
There’s also the threat of public networks where an attacker downgrades an HTTPS connection to HTTP before passing it to the user making the communication unencrypted and easier to intercept.
Another possibility although a lot harder, the attacker could try to trick a user into installing a malicious root certificate on their device. If successful, the attacker could generate certificates for any website, and the user's device would treat them as valid.
The goal now is to find a way for a specific client and their trustworthy server to be certain they’re uninterruptibly communicating with one another.
Let us delve deeper and uncover the methods to achieve this.
SSL Pinning
SSL pinning is when the client stores the expected server's SSL certificate (or a public key derived from it) directly within its code. During communication, the app compares the server’s certificate against the stored one. If they match, the app proceeds with the connection. If they don’t, the connection is blocked.
Types of SSL pinning:
There are two types of SSL pinning, let’s explore each one in detail.
Public Key Pinning
The client stores only the certificate's public key instead of the whole certificate.
The upside to this approach is that you don’t need to concern yourself with the certificate expiry time since as it rotates or renews since you would have the ability to reuse the same public/private key pair eliminating the need for the client side to update the pin.
Certificate Pinning
The app stores the entire SSL certificate. Making it a necessity to push updates every time the certificate renews in order to pin the new one, and if not updated on time all server calls will fail and your app won’t function properly.
First we need a little more clarification on types of certificates.
Certificates are issued in a hierarchy called Certificate Chain, there are three levels of certificates:
Root Certificate which is issued by a trusted Certificate Authority (CA), this certificate is at the top of the hierarchy and has a long validity period, often 20 years or more. Root certificates are self-signed and are trusted by operating systems and browsers.
Intermediate Certificate: Issued by the root certificate or another intermediate, this certificate acts as a “middleman” between the root and the server’s end-entity (leaf) certificate. Intermediate certificates are typically valid for 5–15 years.
End-Entity (Leaf) Certificate: The actual certificate used by your server, issued by the intermediate certificate. These have shorter validity periods, starting from 1 month up to 3 years.
It’s also important to note that TLS plays an important role in verifying both the domain & the certificate validity, so if the attacker uses the same Root/Intermediate certificate with another domain it won’t work.
The choice of which type of certificate to use and where in the certificate chain to pin depends on your specific needs. Pinning higher up the chain, such as at the root or intermediate certificate, offers greater flexibility and longer validity periods, as these certificates are generally less likely to be compromised due to the security measures employed by Certificate Authorities (CAs). However, pinning closer to the leaf certificate provides maximum security by tying communication to a specific end-entity certificate, though it sacrifices the broader flexibility of higher-level pinning.
Opting for an intermediate certificate is often recommended as it strikes a balance, offering a longer validity period while maintaining a reasonable level of control.
Keeping in mind that if the CA or intermediate certificate eventually changes, you might still need to update your pin, though this happens infrequently.
Here are some links we found particularly helpful while implementing SSL pinning 👇🏼
SSL pinning link iOS SSL pinning Android SSL pinning
In summary, SSL pinning is a strong way to protect your app from man-in-the-middle attacks, ensuring secure communication between the client and server. While it significantly enhances security, it does come with challenges, such as managing certificate expiry and the need for frequent updates. In our next article, we'll explore strategies to overcome these limitations, balancing security with user convenience.
Click 👉🏼 here 👈🏼 to read Part Two!