Security testing comes in many forms. For our purposes, we will consider manually-driven, black-box testing that aims to identify the maximal set of vulnerabilities that can be identified within an application. Terminology can be contentious, but this is widely referred to as an application penetration test, which includes an attempt to exploit identified vulnerabilities, demonstrating impact, and – to the extent possible – quantifying risk. If we wanted to be precise, we could use Josh Groassman’s term Tool Assisted Manual Application Security Testing ((TA)MAST) from his relevant talk How to get the best AppSec test of your life, but I will simply use application penetration testing. So how do we optimize such an engagement? First, we will need to agree on its purpose.
I believe that testing should be conducted with the goal of further securing the application (I suspect security professionals will agree unanimously). This may seem obvious, but it is not the only reason that testing is conducted. For example, penetration testing is a common requirement for various compliance standards. I have seen many such cases where a client would rather see an unremarkable result in order to check a box than receive an informative and actionable report. More findings, after all, means more work. It may also result in fail condition for a compliance standard (keep in mind, however, that exploited vulnerabilities in your applications can lead to much more work and compliance troubles later on).
If your goal is to actually secure your mobile application, as I believe it should be, then I can offer some recommendations. It is important to consider the major restriction that a penetration tester has compared to prospective attackers: time. To even the odds, it is best to facilitate efficient use of a tester’s time.
For mobile applications, there is an increasingly common class of technologies use to protect apps that can be an inefficient time sink when testing: runtime application self-protection (RASP) mechanisms. This class of protections generally includes root/jailbreak detection, emulator detection, certificate pinning, dynamic integrity protections, and more. This can be a real pain for testers who typically use rooted, jailbroken, and emulated devices, and intend to intercept and manipulate traffic (effectively a self-MitM).
Crucially, these protections are typically all implemented client-side within the logic of the mobile app itself. While they may increase the difficulty of reverse engineering and tampering of mobile applications, they can always be bypassed on devices where attackers maintain privileged control of the execution environment. The only question is how much effort is required. While many of these protections can be trivial to bypass in practice, a motivated developer could theoretically develop mechanisms that require an effort well beyond the time established for testing.
Once these protections are bypassed, an attacker is free to identify vulnerabilities that exist in the core logic of the application. This is why I highly recommend deploying an app build for penetration testing that has these protection mechanisms disabled or removed entirely in order to facilitate efficient testing. If there is a desire to test these RASP defenses specifically, I would recommend setting aside time for a separate, dedicated engagement to determine the level of effort required for a bypass.
If you proceed with a penetration test and choose not to (or cannot) disable these mechanisms, please be aware that you will be paying for time spent testing known bypassable protections instead of important application logic. As these protections are often implemented through third party components, you might not even be paying for your own code to be tested.
In addition to these defenses, you may also want to consider the following if you are preparing for a penetration test:
- Are you using code obfuscation tools? These do not make reverse engineering impossible, only more annoying. Avoiding the use of these tools for testing builds may save the security tester time.
- Consider also server-side defenses, including web application firewalls (WAFs) and anti-automation protections such as rate limiting. These protections limit testers more than actual attackers and most risks posed by mobile applications typically arises from the supporting web services and APIs.
- Even the most adept manual testers use automated and semi-automated tooling to augment testing coverage in a short period of time (and automate the boring stuff). Out-of-band security mechanisms (such as multi-factor authentication) may be challenging to automate around as even commercial tooling is quite limited in these capabilities. By providing testing accounts where these protections can be disabled, you are saving the tester the time it would take to develop tooling to automatically handle these interactions (assuming it is even feasible within the generally short period of testing).
As a final note, make sure you communicate to the tester which mechanisms have been disabled for testing. Any competent consultancy will make a note about this context in their report.
I hope these recommendations help you get more effective penetration tests. At very least, you will make your consultants happy when you work with them and not against them.