Bypassing certificate pinning with Gabriel Franco | Faraday
Bypassing certificate pinning with Gabriel Franco
June 5, 2023
#Mobilesecurity
Many apps implement a security feature called Certificate Pinning, creating some problems when trying to intercept the traffic between the application and the server. Today, we’ll cover the fundamentals of Certificate Pinning and give some examples of how to bypass it using an Android mobile.
Certificate pinning is a security measure that protects your online communication by establishing a trusted connection between your device and a specific web or service. It verifies the digital certificate presented by the server to ensure it matches a pre-defined set of trusted credentials. This way, even if attackers obtain a fraudulent certificate, they won’t be able to intercept your data.
Before you decompile and modify something, you can open it with jadx:
If I want to decompile:
apktool d test.apk
In res/xml, under Resources in JADX, I didn’t find any network_security_config directive, so I have two ways to go:
- Decompile the app, add it by hand, compile and sign the app and then install it on the device.
- Install the burp certificate, but at the system level.
A) Decompile and modify the app
First, I decompile and I’m going to create a new file called network_security_config in the res/xml/ path:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="user"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
Also, I have to add the directive in the AndroidManifest.xml file:
<application android:allowBackup="false" android:networkSecurityConfig="@xml/network_security_config" ...>
Once ready, I start to compile the app:
apktool b test # where TEST is the app’s decompiled folder
The resulting app will be in the folder test/dist/test.apk.
To sign it, I’m going to create a key:
keytool -genkey -v -keystore my-release-key.keystore -alias gabiTEST -keyalg RSA -keysize 2048 -validity 10000
Change gabiTEST to whatever you want, same as keystore name, mine in this case is my-release-key.keystore. The latter will be saved in the folder where everything is running.
Now to sign it:
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore test/dist/test.apk gabiTEST
To see that everything went well, you can run:
jarsigner -verify -verbose -certs test/dist/test.apk
Warning:
This jar contains entries whose certificate chain is invalid. Reason: PKIX path building failed:
- unable to find valid certification path to requested target
- The SHA1 digest algorithm is considered a security risk.
- Without a timestamp, users may not be able to validate this jar after any of the signer certificates expire.
If the app is not aligned, you have to align it:
/Users/0x1gab/Library/Android/sdk/build-tools/29.0.2/zipalign -v 4 test/dist/test.apk test_aligned.apk
Now, all that remains is to install:
adb install test/dist/test.apk
B) Install the burp certificate as SYSTEM
- Go to BURP and download the export certificate in DER format.
- Convert it to PEM format:
openssl x509 -inform DER -in cert.der -out burp.pem
- Get the hash value of the subject:
openssl x509 -inform PEM -subject_hash_old -in burp.pem | head -1
- Rename the certificate with that value:
mv burp.pem HASH.o
- Push the certificate:
adb push 9a5ba575.o /system/etc/security/cacerts
- Set permissions and reboot:
chmod 644 /system/etc/security/cacerts/<subject_hash>.0
reboot
If everything goes well, we shouldn’t have any certificate pinning problems. In case there is something that we have not seen:
- Touch the source code of the APK by hand, delete the Certificate Pinning entries and compile again.
- Use a framework like XPOSED.
- Use Frida.
Using Frida
To install it:
- Frida server is downloaded from the official site.
- Push Frida server to device:
adb push frida-server /data/local/tmp/
- Give it permissions and start the service:
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"
- Run Frida:
frida --codeshare sowdust/universal-android-ssl-pinning-bypass-2 -U com.lucyapp