Search for lockpicking, and you’ll see that there’s no shortage of suppliers ready to serve locksmiths and hobbyists. Each community has a legitimate need. Is there any reason to believe burglars don’t shop at the same sites?
Hackers are developers, and they have a long history of enthusiastically embracing and adapting development (and DevOps) innovations to speed their work, extend their reach, and ship software – the only difference is that they’re more likely to use those development tools and platforms on YOUR software rather than on their own. Static code analysis tools, debuggers, and even public bug-tracking databases are all go-to hacker resources.
Any comprehensive app security strategy must include controls to prevent or significantly reduce the unauthorized use of development tools on (or against) applications. Suppose you want to tie this requirement back to regulations and compliance obligations. In that case, these topics typically fall squarely inside unauthorized privilege escalation or non-privileged user access to privileged utilities and tools.
Let’s examine Frida, an archetypal example, and examine the controls that have proven effective in limiting its unauthorized use.
The Frida website defines Frida as a “Dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers.” A dynamic (binary) instrumentation toolkit (such as Frida) injects instrumentation code at runtime that can reveal and change the behavior and state of a targeted application throughout its execution.
The injected code executes as part of the normal instruction stream after being injected but is transparent to the application it’s been injected into, making it both a legitimate alternative to debuggers and a powerful hacker tool.
Further, to encourage adoption and maximize its legitimate value, Frida has published an open API itself and built a suite of productivity tools based largely on this core technology. These include:
This is so invasive! Why not just ban these tools? These are three legitimate use cases (offered on the Frida website) where Frida is especially effective versus alternative approaches (thus justifying their existence).
Frida is free, useful, and, with the help of its extended development community, it’s getting easier and easier to use.
Let’s begin by looking at a specific use case. Hail Frida!! The Universal SSL pinning bypass for Android applications offers a step-by-step guide (using Frida) to bypass an Android application’s SSL pinning (a technique used to ensure that an app is communicating securely with a verified service/server) for penetration testing. The use case is legitimate, but the identical steps can also be used to implement a “man in the middle” attack (an attack where the attacker secretly relays and possibly alters the communications between two parties who believe they are directly communicating with each other).
Effective risk management strategies combine preventative, detective, and responsive controls (also referred to as defensive or corrective controls) to present a layered approach to minimizing the likelihood of an actual loss event (successful exploit) without incurring excessive cost or complexity. In-app protection is no exception to this “golden rule.”
The injection script must be run on a rooted mobile device (or an emulator).
One way to prevent the injection of instrumentation is to prevent your application from running on a rooted device or inside an emulator, but developers often need to run their apps in an emulator (or on a rooted device) during development and testing.
The requirement is that the app should not be run on an unauthorized rooted device or an emulator after deployment.
PreEmptive Protection products combine obfuscation transformations with “Checks.” A Check is a code injected into application methods post-code before signing and publication. At runtime, it ” checks” whether a particular condition is true and, if so, triggers various responses.
Unlike the dynamic form of code injection employed by Frida, this injection is entirely controlled by the original development organization and fully integrated into its build chain. The injected code consists of code included as part of PreEmptive Protection (the “check” component and the default “response” code) and, optionally, customized response code written by the development organization.
Each product component of the PreEmptive Protection suite includes a collection of relevant checks. PreEmptive Protection™ DashO™ for Android & Java (DashO) options include:
Configuring DashO to inject these two controls dramatically reduces the exposure stemming from Frida and similar dynamic instrumentation and hooking frameworks. However, no preventative control is perfect. New rooting and hooking kits are constantly being developed, and some will inevitably find a way to avoid detection. Because of this reality, the layered approach of prevention, detection, and response is essential.
Continuing with the Frida Android tutorial, the Frida server is moved to the device (or emulator), the script is run, and your application is now “hooked.” The SSL Pinning control you had painstakingly included in your app has been defeated.
Fortunately, PreEmptive Protection—DashO also includes a Hooking Check. The Hooking Check runs through a number of heuristics and attempts to determine if your app is somehow being run after being hooked (note: For a complete list of the Checks currently, See Runtime Checks inside PreEmptive Protection for Android).
What is the appropriate response when your app detects it is being run on a rooted device or inside an emulator? Certainly, there are numerous scenarios other than a threat actor beginning the process of hooking your app with Frida. What if your app is a consumer banking app or an app helping to monitor a patient’s insulin level? It is reasonable to expect different responses to be required in these two scenarios. Neither is likely a default behavior conceived and implemented by a third-party software vendor. This is why the ability to include custom responses can be so valuable (having said that, default responses are ideal for simple responses, minimizing custom development effort).
Any Check can provide its custom response, so an application can defend itself based on many conditions and at many different stages in its lifecycle.
The problem of preventing unauthorized use of development tools in the wild is complex and constantly evolving. While development teams are sometimes tempted to develop their runtime defenses, this is almost certainly a losing battle in the long run. Effective detection of debuggers, tampering, rooted devices, etc., requires constant evolution with the changing toolkits and frameworks. We can say this with some measure of confidence because this is our full-time job, and it is a full-time job. Learn more about mobile in-app protection.