By Hitesh Duseja In Information Security 02 April 2021
SSL Certificate Pinning Bypass – The Manual Approach!
SSL Certificate pinning is a process where an application on the client-side is coded to connect over an encrypted connection to only those HTTP servers which has the correct certificate.
Thus, the client application will only trust a server if that server can provide a valid certificate which is signed by one of the trusted certificate authorities that come pre-installed or embedded in the client, otherwise, the connection will be aborted.
SSL Certificate pinning is usually implemented by one of the following options:
- Hardcoding the entire certificate in the application client
- Hardcoding the hash of the certificate in the application client
- Hardcoding only the public key in the application client
When this is not properly implemented, the application becomes susceptible to MITM (Man-In-The-Middle) Attacks, including routing SSL/TLS traffic through a proxy tool where application data is visible in cleartext. This usually happens because the application client is usually looking for a specific certificate instead of any valid one.
Now, this application client can be a Windows thick client (.exe i.e. Portable Executable) or macOS or Ubuntu binary or a platform-independent jar file or an android or iOS mobile app. As a matter of fact, the browser is a thin client. Here's why? – A browser-based on the endpoint address (domain or IP) shows the front end client of any web application i.e. provides flexibility, hence thin client. Whereas these other application clients mentioned above are thick clients as they are developed only to connect with one particular application server to provide only its functionalities in a client-server model. No flexibility hence called as fat clients.
Before understanding how to bypass SSL Certificate pinning, let's brush up on some
HTTP proxy basics:
When we use an HTTP proxy such as Burpsuite or ZAP or Fiddler or Charles-Proxy, we have to install the respective proxy's certificate in the browser to intercept HTTPS connections. What we are doing is creating certificate trust between the browser and the proxy tool. Why we do it? Because, 2 SSL/TLS connections are made whenever a proxy tool has to be used, one connection between the browser and the proxy tool and the other between the proxy tool and the target server. As per PKI, for every SSL/TLS connection, a session key is generated per session for encryption and decryption between two endpoints (browser and the webserver), which in turn, is generated on the basis of a unique public key private key pair.
Note: For more info, read about the SSL/TLS handshake here:
https://www.ssl.com/article/ssl-tls-handshake-overview#ftoc-heading-2
Proxying a web application over HTTPS using Burpsuite looks as shown in the above flow. There are two key takeaways of this:
- First, when the application traffic is in Burpsuite or any proxy tool, because of the control over session key in this connection (i.e. session key-1), the proxy tool is able to decrypt application layer data to be visible in clear text i.e. the application layer data gets SSL-stripped, and with the help of proxy interception feature, it becomes possible to modify requests and responses. Hence such proxy tools are also called SSL/TLS terminating proxies.
- Secondly, the connection between Burpsuite and the target web application HTTP server is similar to what happens in a normal SSL/TLS connection between the browser and the Web application. As described in the first takeaway, since the application data gets decrypted in clear text in Burpsuite with the help of session key-1, it then uses session key-2 (generated during the SSL/TLS handshake process between Burp Suite and target web application HTTP server) to encrypt the data and the target web application HTTP server is able to decrypt it. The target Web application cannot distinguish if the traffic is coming from an actual browser or a proxy tool.
Now, that our proxy basics are clear, let's hop on brush up some SSL or TLS digital certificate basics in the context of PKI (Public Key Infrastructure):
Digital certificates are electronic credentials issued by a trusted third party. It not only verifies the identity of the owner but also verifies that the owner owns the public key.
As clearly stated here, a digital certificate comprises the following fields:
- Subject: Provides the name of the computer, user, network device, or service that the CA issues the certificate to. It generally has CN or Common Name field. The subject name is commonly represented by using an X.500 or Lightweight Directory Access Protocol (LDAP) format.
- Serial Number: It is to uniquely identify a certificate for each certificate that a CA issues. This is also used in OCSP (Online Certificate Status Protocol) lookups.
- Issuer: Provides a distinguished name (DN) for the CA that issued the certificate. The issuer name is commonly represented by using an X.500 or LDAP format.
- Valid From: Provides the date and time when the certificate becomes valid.
- Valid To: Provides the date and time when the certificate is no longer considered valid.
- Public Key: Contains the public key of the key pair that is associated with the certificate.
- Signature Algorithm: The algorithm used to sign the certificate.
- Signature Value: Bit string containing the digital signature of the certificate issuer i.e. CA.
In addition to the version 1 fields, X.509 version 3 certificates include the following optional functionality and feature-based extensions to the certificate:
- Subject alternative name: A subject can be presented in many different formats. E.g., if the certificate has to include a user’s account name in the format of an LDAP distinguished name (DN), e-mail name, a user principal name (UPN), or simply IP Address or DNS Name, you can include all that or any of that in a certificate by adding a subject alternative name extension that includes these additional name formats.
- CRL distribution points (CDP): When a user, service, or computer presents a certificate, an application or service must determine whether the certificate has been revoked before its validity period has expired. The CDP extension provides one or more URLs where the application or service can retrieve the certificate revocation list (CRL) from.
- Authority Information Access (AIA): After an application or service validates a certificate, the certificate of the CA that issued the certificate — also referred to as the parent CA — must also be evaluated for revocation and validity. The AIA extension provides one or more URLs from where an application or service can retrieve the issuing CA certificate.
- Enhanced Key Usage (EKU): This attribute includes an object identifier (OID) for each application or service a certificate can be used for. Each OID is a unique sequence of numbers from a worldwide registry.
- Certificate policies: This describes what measures an organization takes to validate the identity of a certificate requestor before it issues a certificate. An OID is used to represent the validation process and can include a policy-qualified URL that fully describes the measures taken to validate the identity.
So, fields of importance in our context are Subject (Certificate owner's name), Issuer (CA or Certificate Issuer's name), Validity and Signature value (Digital signature of CA). PKI is based on trust or chains of trust. What I mean by that, CA or Certificate issuing Authority such as Verisign, DigiCert etc are universally known. All browsers and their OS are baked in such a way that by default, they trust certificates signed by a known CA. When we browse to a website such as google.com, the browser will verify that the certificate shown by google.com is valid and digitally signed by a known CA, and then SSL/TLS handshake process begins. This is why, when we navigate to a website that uses a self-signed certificate, the browser issues a warning stating that it doesn't trust the certificate. This is because the issuer is not universally known to the browser. As the issuer can be any entity such as the organization itself, which is not a universally trusted third party, such certificates are known as self-signed certificates. The following side-by-side comparison perfectly sums up the difference:
Another point to be noted is that the application clients are usually shipped with their own Keystore. Keystore can be said as a container that can hold public certificates, public keys, or private keys. This is analogous to windows certificate manager, where all certificate that can be used by the OS has to be placed, so as to manage and build trust or chain of trust. The application client can use the components present in the Keystore to encrypt or decrypt the data in a secure connection or validate a public key certificate by comparing the one present in the Keystore with one presented by an endpoint.
Now that, all our basics are clear, we can understand scenarios where SSL Certificate pinning can be bypassed.
As goes true for all application-level bugs, the code level implementation on how an SSL certificate is validated matters. Many-a-times, the developers validate only either the Subject Name, Issuer Name, Validity, Subject Alternative Names or some sort of combination of these fields. These fields in the certificate can be cloned. The fields that cannot be cloned are Subject Public Key Info which has the modulus or the actual public key. This certificate cloning technique is central to the process of bypassing SSL Certificate pinning.
If an application client accepts and trusts fake self-signed certificates when connecting to an end-point, then proxy interception is possible, as validation stage where application client compares the fake certificate with the end-point certificate is passed or one can say bypassed☺. What we are basically doing is that we are inducing the application client to encrypt its data using the session key generated and exchanged between itself and the proxy tool, so the application clients think it is connecting to the endpoint, but in reality, it will be connecting to our proxy tool. This is a similar process to what we do when we import the certificate in the browser's certificate store.
Before learning how to clone certificates, please go through this page which lays out the various formats in which a certificate file is available.
That's the last prerequisite, seriously, we know ;) I swear, ahead of this is only an actual demonstration where steps are explained.
During a security assessment, we came across a java based thick client communicating with its server over HTTPS. This thick client has its own Keystore. It has SSL Certificate Pinning done but implementation was improper.
We realized this when we tried to redirect its traffic to Burpsuite by importing burp's certificate in Keystore used by the thick client:
keytool –importcert –alias "any_name_you_wish_to_give" – trustcacerts –file "burp_certificate_name.cer" –keystore "name_of_the_java_keystore.jks"
keytool –list –keystore "name_of_the_java_keystore.jks"
The error that the thick client had thrown said something of the lines of, No Subject Key Alternative match with endpoint. That means the thick client was validating this field. The error came because the burp's CA certificate does not have this field. Luckily, we had openssl installed on my system, so we set out to generate my fake certificate as shown below:
Step 1: We first checked my target endpoint certificate:
Step 2: We dumped the certificate present in the Keystore, to read it:
OpenSSL x509 –in "original_certificate_name.cer" –noout -text
Step 3: We made a config file (configuration.cnf) where fake details are given to clone the certificate for fields of CN in the subject, subject alternative names.
Step 4: Then we created a private key, public key pair and also embedded the public key in the certificate and self-signed it with the same issuer.
openssl req –newkey rsa:2048 –nodes –keyout fake_key_name.pem – x509 –days * -out fake_certificate_name.pem –config configuration_name.cnf
Where * is no. of days remaining such that Valid to date is same as the original certificate has.
Step 5: Convert the certificate in der format (file format is .cer) which was the format used in that java Keystore
openssl x509 –inform pem –in "fake_certificate_name.pem" –outform der –out "fake_certificate_name.cer"
Step 6: Put the fake certificate with same alias as the original one i.e. completely replaced the original certificate
keytool –list –keystore "name_of_the_java_keystore.jks"
keytool –delete –alias " original_certificate_alias_name" – keystore " name_of_the_java_keystore.jks"
keytool –importcert –alias "original_certificate_alias_name" – trustcacerts –file "fake_certificate_name.cer" –keystore "name_of_the_java_keystore.jks"
Step 7: Put the public key embedded certificate and its corresponding private key in PKCS container and gave it to burp as it accepts that format.
openssl pkcs12 –inkey fake_key_name.pem –in
fake_certificate_name.pem –export –out
fake_certificate_pkcs_filename.p12
After this, we were able to intercept SSL/TLS traffic of thick client. The same method can be used for other types of application clients. This is a generalized manual approach.
Conclusion:
While there are various ways to bypass the SSL pinning in Android devices, it comes down to the person’s ability and the situation to select which method to proceed with. The above-discussed method would allow you to intercept the traffic and bypass the most common defence employed by the developers.
We at qSEAp Infotech Pvt. Ltd. have a dedicated team working on application security for various Android and iOS applications. If you are stuck on how to proceed with security testing for your application, feel free to reach out to us at info@qseap.com