When a security assessment on a mobile application is being carried out (specifically on Android) there are two main roads an analyst can take:
First performing a static analysis: decompiling the apk and diving into the code to find interesting code patterns (IPC and component exposure, embedded cryptographic secrets, among other things). However, it is common to encounter obfuscation and antireversing techniques that often make it difficult to fully understand the decompiled code.
Having this difficulties in mind, a second approach is to analyse the behaviour of the app in runtime or in other words a dynamic analysis. The aim of this is to understand which native Android functions are being called by the app, how user data is being handled, how the app is integrating with the backend, which APIs are being called (including their inputs and outputs at runtime) and also manipulating the behaviour of the app for each of these points. When this second path is followed, then dynamic code instrumentation comes into play, an area for which there is a de facto framework called Frida.
Wait a minute - what is Frida?
Frida, apart from being a well known Mexican painter, is also the name of a dynamic instrumentation toolkit that allows the injection of custom Javascript into a target process. The main advantage of this tools is that it is scriptable. In other words, any function can be hooked in runtime with an ad-hoc script and modifications made to that script on the fly without any need to recompile the app. In this way an iterative runtime security analysis can be achieved: whilst progressively understanding what the application does under the hood, the script can be optimised on the fly without recompiling or restarting the target.
A second feature that establishes Frida as a main player in dynamic instrumentation, is that it offers a single unique toolkit for working on multiple platforms. Frida can be used to perform a security assessment not just on apps built for Android and iOS, but also when working with target programs running on Windows, Mac and GNU/Linux operating systems.
Finally Frida is also an open source project, with many years of maturity and a strong and active community around it. Plus it provides an API for building custom tools above the Frida core if required.
How functions tracing works with Frida?
To illustrate the potential of Frida when function tracing and its ability to modify the app behaviour in runtime, here is an example on how to bypass a security protection as SSL Pinning with Frida. SSL Pinning is a security control technique that allows a mobile app - when communicating with a server - not to simply trust any server with certificates trusted by the operating system's trust store, but instead trust only one or more pinned (or embedded) certificates inside the application. The developer of the app embeds one or more certificates inside the code of the application, and when a connection to a server occurs, it compares the server certificate with the pinned certificate(s). If both match, then communication is established.
For security analysts this undoubtedly introduces an additional layer of difficulty when monitoring the traffic of an app during its communication with the server.
In this scenario, Frida can be relied upon to help bypass the protection of SSL pinning. As Frida is an open source project, it not only exposes its own codebase but also has a public listing of code snippets useful for security assessments available at the Frida Codeshare site. As an example on how to bypass SSL pinning using Frida, a script by the name of Universal Android SSL pinning bypass can be used, that allows the app to be re-pinned with a different custom certificate.
The code of the script is fully available in the link provided but to briefly to explain how it works, here is a small snippet of the code:
// Load CAs from an InputStream
console.log(
"[+] Loading our CA..."
)
var cf = CertificateFactory.getInstance(
"X.509"
);
try
{
var fileInputStream = FileInputStream.$
new
(
"/data/local/tmp/cert-der.crt"
);
}
(...)
// Create a KeyStore containing our trusted CAs
console.log(
"[+] Creating a KeyStore for our CA..."
);
var keyStoreType = KeyStore.getDefaultType();
var keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(
null
,
null
);
keyStore.setCertificateEntry(
"ca"
, ca);
// Create a TrustManager that trusts the CAs in our KeyStore
console.log(
"[+] Creating a TrustManager that trusts the CA in our KeyStore..."
);
var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
console.log(
"[+] Our TrustManager is ready..."
);
console.log(
"[+] Hijacking SSLContext methods now..."
)
console.log(
"[-] Waiting for the app to invoke SSLContext.init()..."
)
SSLContext.init.overload(
"[Ljavax.net.ssl.KeyManager;"
,
"[Ljavax.net.ssl.TrustManager;"
,
"java.security.SecureRandom"
).implementation = function(a,b,c) {
console.log(
"[o] App invoked javax.net.ssl.SSLContext.init..."
);
SSLContext.init.overload(
"[Ljavax.net.ssl.KeyManager;"
,
"[Ljavax.net.ssl.TrustManager;"
,
"java.security.SecureRandom"
).call(
this
, a, tmf.getTrustManagers(), c);
console.log(
"[+] SSLContext initialized with our custom TrustManager!"
);
}
Taking a closer look at how the code works.
Instead of using the certificate pinned by the app, the script loads an alternative certificate and creates a KeyStore with new trusted CAs and a TrustManager (that trusts the CAs in the new KeyStore). As the creator of the script states, the 'magic' happens when the app "initializes its SSLContext we hijack the SSLContext.init() method and when it gets called, we swap the 2nd parameter, which is the application TrustManager, with our own TrustManager we previously prepared".
The function overload() at the end of the script is actually the one that not only allows Frida to intercept function, log their arguments and return values, but also hook the original functions and modify the way they are called to alter the app behaviour. In this case to allow the traffic that is protected with SSL Pinning to be intercepted.
To implement this SSL pinning bypass, the first thing required is to upload a new ad-hoc certificate to the mobile phone or emulator running the target app (for example the certificate of Burp, a tool for proxying the traffic). In this example adb will be used to upload the file to the device.
$ adb push burpca-cert.crt /data/local/tmp/cert-der .crt |
After that the Frida CLI is used with the parameter --codeshare
pointing to the script "Universal Android SSL pinnin bypass" remotely from FridaCodeShare or the script can be used locally after downloading it from the repository to a host machine.
$ frida --codeshare pcipolloni /universal-android-ssl-pinning-bypass-with-frida -f com.target.app |
or locally:
$ frida -U -f com.target.app -l universal-android-ssl-pinning-bypass-with-frida.js --no-pause |
After running any of these commands in the command line of the host, the main thread of the target app must be resumed with the command "%resume"
The app can then be used on the device or emulator.
Finally the bypass of the security protection via SSL pinning - using a new certificate - can be seen.
Simplifying our work with Objection
Without doubt the previous example shows the potential of Frida as a scriptable framework, additionally the API that Frida exposes is a fertile ground for the emergence of additional tools to be mounted over the core code of Frida. A great example of this is Objection, a runtime mobile exploitation toolkit that has the main advantage of simplifying the dynamic instrumentation process. Bypassing SSL pinning is an example of the capabilities offered by this tool, and requires only two steps.
First Objection is launched via command line using the following command:
$ objection --gadget= "target.android.app" explore |
And then using the simple directive "android sslpinning disable" on the Objection console, that handles the bypass of the security measures implemented in the app.
To sum up, bypassing SSL pinning protection is a good example on how Frida and the universe of tools surrounding this framework are essential aids when making a security assessment on a mobile app.
______________
References
- Frida framework
- OWASP Mobile Security Testing Guide
- Universal Android SSL Pinning bypass with Frida by Piergiovanni Cipolloni
Teresa Alberto
Security Researcher at Dreamlab Technologies