Mobile apps are no less secure than web apps, but they are more exposed as they can also run in the attacker’s environment. So, trusting it is a mistake. No single defense method is foolproof for preventing secret recovery, app tampering, and man-in-the-middle (MitM) attacks.
We look at why it’s dangerous to assume the requests originate from the app you built in this article. We will then examine the various mobile-specific defenses and why a layered approach may be most essential, as it treats the mobile app as an untrusted endpoint.
Why You Can’t Trust Requests From Your App
Rooted or jailbroken devices compromise the baseline sandboxing protection of Android and iOS, enabling attackers to access local app data, alter behavior, or extract runtime secrets. Even obfuscated secrets in APK/IPA files can be decompiled and extracted.
App tampering, where altered apps are installed on any device (including non-rooted ones), allows manipulation of traffic and runtime behavior. Additionally, MitM attacks, which are common in web applications, allow attackers to intercept and modify requests, even over TLS, by using custom root certificates.
We frequently see backend attacks like secret recovery (extracting API keys for unauthorized access) and MitM with request tampering (intercepting and modifying app-backend communication). Attackers also create bot farms by automating app interactions on emulators/devices, or by reverse-engineering API protocols to forge direct requests.
These attacks are no longer just a theory. We’ve observed real breaches where improperly scoped APIs leaked location data, or where attackers reverse-engineered mobile clients to automate credential stuffing. In one case, a popular fitness app leaked user location data due to over-permissive API responses. In another instance, attackers reverse-engineered apps to identify private endpoints and launch credential-stuffing attacks.
How to Prevent Secret Recovery
The ideal approach is to keep secrets on the backend and proxy sensitive requests. This prevents extraction, but it can add latency and increase backend complexity.
If your app absolutely needs to use a secret, consider dynamically retrieving it from your backend at runtime, such as after user authentication, to prevent static extraction from the app binary. While better, local storage on rooted/jailbroken devices remains a risk. You can mitigate by using secure storage mechanisms that leverage trusted execution environment (TEE) or secure element (SE) APIs.
Runtime application self-protection (RASP) can also detect and block attackers using hooking or other dynamic analysis techniques to extract secrets during runtime. A significant benefit of dynamic retrieval is the ability to update compromised secrets without requiring an app update, thereby simplifying rotation and limiting the impact.
If a secret must always be available and cannot be dynamically retrieved, hardcoding is the least secure option and should be assumed compromised. To reduce risk, use code obfuscation and encryption, RASP anti-hooking, anti-MitM protections, and frequent secret rotation (ideally per app release) to minimize exposure and impact from leaks.
How to Prevent MitM & Request Tampering
MitM attacks are simple and effective, requiring only that an attacker install a proxy and add its certificate to the device’s trust store. This allows interception, decryption, and modification of TLS-protected traffic, revealing your app’s request structure and behavior. A layered defense is essential, as no single method is foolproof.
1. Certificate Pinning
One key technique is certificate pinning, which ensures the app only accepts certificates signed by known certificate authorities (CAs) or only accepts specific public keys. This means that your application will reject connections from a MitM proxy certificate that is not on its approved list.
However, certificate pinning can be bypassed using general-purpose tools unless combined with RASP, so using anti-hooking/tampering on top is strongly recommended to increase its resilience. Operationally, any change to the pinned certificate will render previous apps unable to connect to your backend, so you need to be prepared for that.
2. Mutual TLS (mTLS)
Mutual TLS (mTLS) enables your backend to authenticate your application. Your app uses a private key to authenticate to the backend, which trusts its associated public key or certificate authority. This allows your backend to detect if communication isn’t originating from your application, effectively bypassing client-side bypasses seen with traditional certificate pinning.
However, mTLS isn’t foolproof. It requires your app to possess a private key, which attackers can recover and then use in a man-in-the-middle (MitM) proxy (as demonstrated in this blog post). Furthermore, mTLS doesn’t prevent app tampering — a modified app will still use the same private key.
Despite these limitations, mTLS offers valuable security benefits. Implement it while understanding its boundaries, and be prepared for potential architectural changes. Crucially, protect the private key as securely as possible.
3. Application-Layer Encryption
Application-layer encryption adds a second layer of protection beyond TLS, as MitM proxies can decrypt TLS traffic. By encrypting payloads before they are handed off to TLS, a MitM proxy cannot automatically decrypt them. Attackers would need to reverse-engineer your app and recover encryption keys, making it significantly more difficult. Resilience can be further enhanced by applying obfuscation, RASP, and secure storage for static secrets as recommended in the secret recovery section.
4. Application Attestation
Application attestation verifies that a request originated from an untampered app on a known-good device, meaning it is not rooted, jailbroken, or running in an emulator. The app gathers runtime metadata and sends it to a trusted third party, which then returns a token that your backend can validate and decrypt. Some solutions can even bind the token to a specific request, allowing for real-time tampering detection. Attestation helps you detect request tampering, spoofing, and malicious environments. It’s a high-ROI way to maintain platform integrity and user trust.
Summary Table: Request Tampering Protections
Technique | Prevent passive MITM (only monitor requests) | Prevent active MITM (tamper requests) | Detect request tampering done by patching the application itself | Difficulty bypassing an unprotected app |
---|---|---|---|---|
Certificate pinning | Yes | Yes | No | Easy |
mTLS | Yes | Yes | No | Easy |
Application layer encryption | Yes | Yes | No | Moderate |
Application Attestation | No | Yes | Yes | Hard |
It is crucial to always perform server-side validation of client data and design your backend to detect and respond to malicious behavior, just as you would with a web application.
How to Prevent Bot Farms
Attackers can automate your app’s user flows either on real or emulated devices, or worse, by forging backend requests directly. Bot farms can be created by using devices running your application and instrumenting them to interact with it, potentially using real devices with accessibility features to emulate user interaction, or rooted devices and emulators. Alternatively, attackers can create headless bot farms if they have fully reverse-engineered your communication layer, allowing them to use scripts to perform direct requests to your backend.
Let’s see if the mitigations related to request tampering help against bots:
Device-based bot farm | Headless bot farm | |
---|---|---|
Certificate pinning | ![]() |
![]() |
mTLS | ![]() |
![]() ![]() It depends on whether the private key is recovered |
Application layer encryption | ![]() |
![]() ![]() It depends on whether application-layer encryption has been reverse-engineered |
Application attestation | ![]() |
![]() |
Among the previously discussed protections, only Application Attestation is particularly effective in this context. It remains the best defense because it detects emulators, rooted devices, and repackaged apps, ensuring that requests originate from unmodified applications. Furthermore, tokens bound to the request state prevent replay and tampering.
Server-Side Protections
While client-side defenses slow attackers, backend protections stop them. Implement rate limiting to throttle API usage by user, IP address, or device, particularly for sensitive actions such as login, purchases, and redemptions. Enforce strict access controls, utilizing role-based or context-sensitive rules such as geo-based restrictions. Conduct API traffic monitoring to identify anomalies like spikes, repeat payloads, or suspicious patterns, and use behavioral analysis and anomaly detection tools to detect automation and reconnaissance activities. Effective bot protections help avoid fake accounts, promo abuse, skewed analytics, and backend overload, delivering a strong security and ROI upside.
Conclusion: Think Like a Black Hat
When designing your mobile app’s communication layer, test your implementation against best practices using tools like OWASP MASVS and automated scanners, such as AppSweep.
Once the basics are in place, add obfuscation and RASP to protect against tampering and real-world attacks. Finally, all the classic server-side techniques from web security still apply to your mobile backend and should be implemented with equal rigor.
Achieving proper security means thinking like an attacker and staying one step ahead of them.