Bypass OkHTTP CertificatePinner on Android
There are several methods to pin server’s X509 certificate to defense on MITM attacks and enable proxy to capture applications traffic.
OkHTTP is an open-source project designed to be an efficient HTTP client. OkHTTP implements a SSL certificate pinner called CertificatePinner() as see below:
String hostname = "example.com";CertificatePinner certificatePinner = new CertificatePinner.Builder().add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=").build();OkHttpClient client = OkHttpClient.Builder().certificatePinner(certificatePinner).build();Request request = new Request.Builder().url("https://" + hostname).build();client.newCall(request).execute();
‘AA…AAA=’ is the base64 encoding of the server’s public key hash.
As you see when the client sends SSL hello packet and receives the server’s certificate, calculates the received certificate’s Public key hash and compare with which placed in the code and if they are the same SSL connection will be established.
You need to change the hash value with a new hash value. The new hash value is the proxy server or application’s Public key hash value.
Export Burp’s CA Certificate
For example to get BurpSuite’s certificate, follow the below steps:
- Open BurpSuite go to the Proxy tab.
- Then go to the Options tab.
- Press Import/Export CA Certificate button
- Check Certificate in DER format.
- Press Next button
- choose a file name, the file name should be in .cer format.
Determine Burp’s CA Certificate’s Hash value
Now we should get the base64 encoded of Public key hash value of exported Burp CA certificate, for this use below Linux command (be sure that OpenSSL is installed on your system, How to install?) :
h@sajadi:~# openssl x509 -inform der -in XXX.cer -out XXX.pem //Convert .Cer to .Pem certificate format.h@sajadi:~# openssl x509 -in XXX.pem -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha1 -binary | openssl enc -base64
XXX.pem is the name of the exported CA certificate from Burp.
Be careful about the hashing algorithm using in the source code.
Now in the output, you see the base64 encoded of Public key hash value of exported Burp CA certificate, then we should place this hash value to the source code.
De-compile and Compile Android Application
First, we need to de-compile the APK file using APKTool which is preinstalled on some Linux distribution like Kali but I recommend that use the last .jar file from the source which you can find here. Now de-compile APK file using below command (be sure that Java is installed on your system, recommended the last version):
h@sajadi:~# apktool d XXX.apk //using preinstalled version
or
h@sajadi:~# java -jar apktool_x.y.z.jar d XXX.apk //using downloaded jar
Now you should find the smali class that handles the CertificatePinner() using below command in the APK de-compiled directory:
h@sajadi:~# grep -r "certificatePinner"
Then change the hash value with Burp’s Public key calculated hash value.
invoke-direct {v0}, Lcom/squareup/okhttp/OkHttpClient;-><init>()Vnew-instance v1, Lcom/squareup/okhttp/CertificatePinner$Builder;invoke-direct {v1}, Lcom/squareup/okhttp/CertificatePinner$Builder;-><init>()Vconst/4 v2, 0x1new-array v2, v2, [Ljava/lang/String;const/4 v3, 0x0const-string v4, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="aput-object v4, v2, v3const-string v3, "example.com"invoke-virtual {v1, v3, v2}, Lcom/squareup/okhttp/CertificatePinner$Builder;->add(Ljava/lang/String;[Ljava/lang/String;)Lcom/squareup/okhttp/CertificatePinner$Builder;move-result-object v1invoke-virtual {v1}, Lcom/squareup/okhttp/CertificatePinner$Builder;->build()Lcom/squareup/okhttp/CertificatePinner;move-result-object v1sget-object v2, Ljava/util/concurrent/TimeUnit;->MILLISECONDS:Ljava/util/concurrent/TimeUnit;const-wide/16 v3, 0x4e20
Change ‘AA…AA=’ with the new hash vale of Burp’s CA certificate.
When you change the hash value, you need to re-compile the application to APK using below command:
h@sajadi:~# apktool b XXX/ -o SSL-Unpinned.apk
‘XXX/’ is the de-compiled directory of the application.
At the end you should sign the APK to able to install on the Android device, using below command to create Digital Signature:
h@sajadi:~# keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
And then use the created signature to sing APK using below command:
h@sajadi:~# jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore XXX.apk alias_name
‘XXX.apk’ is the Android application name which you want to sign.
Now SSL Pinning is bypassed.