Series · Hardening before AWS · Part 2 of 3 ← Part 1: Securing the application · Mobile banking app hardening · Part 3: Identity-first migration →
Companion to the AWS-for-banks architecture series and the DSI banking threat picture.
A customer in Surulere downloads what looks like her bank's app. The icon is identical. The store listing has the right colours, the right blue, the right disclaimer. She enters her PIN. Two minutes later, the actual bank's fraud team flags an N3.2 million transfer to a money-mule account in Apapa. The customer never opened the real app. She opened a near-perfect clone hosted on a third-party store, with an additional listener bolted on that exfiltrated her credentials the moment she typed them.
This is not a hypothetical. Customer-help-desk reporting names it as the single most common vector in the Nigerian retail segment. The app on the customer's phone is the bank. The cloned app on the customer's phone is the bank's worst day. And the only thing standing between the two is what hardening was done to the genuine artefact before it shipped.
Key takeaways
- Over 70% of Nigerian Tier 1 banking traffic now flows through the mobile app, making it the single most-targeted surface in the sector.
- The defensible 2026 stack stacks five layers: RASP, SPKI certificate pinning with at least two keys, root/jailbreak detection with monitored or degraded response, migration off SMS OTP, and HSM-signed updates only via Play Store / App Store.
- SIM-swap-driven fraud accounted for 12–18% of authenticated-session fraud in 2025; the migration off SMS OTP is a four-phase journey ending in device binding.
- OWASP MASVS Level 2 plus the full RESILIENCE profile is the bar counter-party assurance teams now enforce — and maps cleanly to CBN CSAT and NDPA obligations.
- A 16-item pre-publication checklist (SAST/SCA clean, RASP verified, pinning telemetry confirmed, HSM signing logs archived) is the evidence chain that defends the release if it produces an incident.
The App Is The Bank Now
By 2026 the Nigerian Tier 1 banking customer interacts with the bank through a mobile app for over 70% of all transactions. The branch is residual. The internet-banking web channel is a long tail. The agent network is a complementary surface. The app is the bank.
The app is also the most-targeted surface — by reverse engineers, SIM-swap rings, store-side repackagers, and the network of fraud operators the sector has documented in post-incident reports. The AWS-for-banks architecture in Part 2 of the architecture series defends the backend the app talks to. The pre-migration application baseline in Part 1 of this series defends the build pipeline that produces the app. This piece documents what hardens the app itself — the artefact that lives on the customer's device, outside the bank's control perimeter, in an environment where root access, modified runtimes, repackaging, and adversarial networks are all operating assumptions.
Six Adversaries, In Order Of Frequency
Generic mobile-security guidance treats the device as a uniform threat surface. The Nigerian banking-app threat model is more specific.
Modified or repackaged apps distributed via third-party stores. The Surulere scenario at the start of this piece. A customer searches for the bank's app, lands on a parallel store, installs a repackaged build with an additional listener that exfiltrates credentials on first login. The single most common vector in the Nigerian retail segment.
Rooted or jailbroken devices running tampered runtimes. Frida, Xposed, Magisk modules hooking the app's authentication and crypto routines. Frequent enough that "if the device is rooted, refuse" is now an industry-default posture.
Network interception on public Wi-Fi. Cafés, hotels, NIPOST data points, conference centres. The TLS handshake is the only thing between the customer and the attacker. If the app trusts any certificate the platform trusts, the attacker buys a wifi-portal-friendly cert and watches.
SIM-swap and SS7-class attacks against SMS-based OTP. Nigerian SIM-swap as a service has been a documented criminal economy for years. SS7 abuse is rarer but credible against high-value accounts. SMS OTP is structurally unrecoverable from these — like trying to deliver a sealed envelope through a courier who already works for the burglar.
Static reverse engineering for credential extraction. Hardcoded API keys, signing keys, encryption keys, debugging tokens — extracted from the APK or IPA, used against the production backend. Often what enables the "modified app" attacks above.
Memory-resident credential capture. Less common but well-documented in research. Dumping the running app's memory to recover plaintext credentials, session tokens, or PINs that the developer assumed were transient.
The hardening below addresses all six, not as separate features but as a layered programme where each control closes part of the gap and the controls reinforce each other.
Layer One — RASP, The Immune System Inside The App
RASP is the umbrella term for protective code embedded inside the app that detects and responds to threats while the app is running. Think of it as an immune system rather than a wall — the wall is the platform's sandbox; RASP is what notices when something nasty has already gotten inside the cell.
The category has consolidated around a handful of credible vendors: Appdome, Promon SHIELD, Guardsquare DexGuard / iXGuard, Verimatrix Application Shielding, OneSpan Mobile App Shielding. The choice between them is mostly a procurement question; the controls they deliver are similar.
Six RASP controls we deploy as a minimum on a Nigerian Tier 1 banking app. Debugger detection refuses to run under JDWP, lldb, or any attached debugger — Frida and Xposed both surface here. Emulator detection refuses Android emulators (Bluestacks, Genymotion, Android Studio's emulator) and iOS simulators, because fraud rings emulate at scale to test stolen credentials. Hook framework detection looks for Frida-server, Xposed module presence, Substrate hooks, Magisk modules with suspicious capabilities — detect, refuse, report. Tamper detection verifies the app's own signature at runtime, integrity of DEX or Mach-O sections, integrity of native libraries; a repackaged build fails this check on first launch. Memory protection adds anti-debug primitives (ptrace_traceme, exit on PT_DENY_ATTACH), anti-dump, runtime decryption of sensitive constants so they do not sit in memory as plaintext. Server attestation has the backend ask "what kind of device are you on, what version, what's your tamper status" — the backend refuses high-value operations from devices that fail attestation.
RASP converts "device hostile" from a vague worry into a measurable posture. The sector's published incident pattern is consistent on this point: apps that survive sustained attack campaigns have RASP active; apps that contribute to incidents typically do not.
Layer Two — Certificate Pinning, Done Properly
TLS is necessary and not sufficient. The platform's default trust store contains a few hundred root CAs. An attacker who controls a Wi-Fi network and can persuade the customer to install a portal cert — or who has subverted a non-bank CA — can present a valid-looking certificate to the app, and the app's default behaviour is to trust it.
Certificate pinning closes this. Two variants exist and the choice matters. Certificate pinning embeds the bank's leaf or intermediate certificate; the app refuses any TLS connection that does not terminate at that exact certificate. Simple, brittle, breaks the day the certificate rotates. Subject Public Key Info (SPKI) pinning embeds the SHA-256 hash of the public key. The certificate can be renewed (with the same key) without breaking pinning. This is the option to deploy.
The rotation problem is the second part. Pin one key and the day that key needs to rotate the bank ships an emergency app update — customers who do not update are locked out. Picture a building where the locks are perfect but the locksmith only has one key on the ring: lose the key and the tenants sleep in the hallway. The defensible posture is to pin at least two keys (the current production key and a backup held offline), pin to an intermediate rather than the leaf where the bank controls its own intermediate, and implement pin-failure telemetry. When a pin verification fails, the app reports the event (without the failing certificate) to the backend's security telemetry plane — landing in CloudTrail Lake or Security Lake per the AWS architecture in Part 2. Three thousand failed pins in Lagos on a Tuesday morning is the first sign of an active MITM campaign.
The "if your pinning is too restrictive, just turn it off" temptation has to be resisted at the architecture level. The bank holds two pinned keys. Not zero.
Layer Three — Root And Jailbreak, And What To Do When You See One
Detection is the easier half. iOS provides isJailbroken heuristics (presence of /Applications/Cydia.app, /private/var/lib/apt, write access outside the sandbox, suspicious file paths). Android provides root-detection patterns (presence of su, Magisk daemon, suspicious mount points, busybox binaries). RASP vendors bundle hundreds of these checks. Do not rely on a single check, because every single check has a known bypass.
The harder half is the response. Three options exist, in increasing order of severity. Monitor means the app continues to run on rooted devices but reports the device's status to the backend; the backend then applies elevated friction (additional OTP, lower transaction limits, more manual review) to operations originating from those devices. Most permissive, right for emerging markets where root and jailbreak are common for legitimate reasons. Degrade means the app runs but refuses high-value operations — check your balance, view your statement, yes; transfer above N50,000 from a rooted device, no. Refuse means the app does not run at all on rooted or jailbroken devices; strongest control, highest customer-support cost, right for high-net-worth or corporate-banking apps but usually too strict for retail.
The defensible landing point for a Nigerian Tier 1 in 2026 is Monitor or Degrade for the consumer app and Refuse for the corporate or treasury app. There is no single right answer; there is the answer that fits the customer base and the risk appetite the bank's board has signed off on.
Layer Four — Moving Off SMS OTP
The 2025 incident data we have reviewed indicates SIM-swap-driven fraud against Nigerian banks accounted for somewhere between 12% and 18% of authenticated-session fraud, depending on the bank. SMS OTP is the enabling weakness. Removing it is not an app-hardening control — it is a whole-bank-authentication redesign — but it has to land in this programme because the alternative is to keep funding the SIM-swap criminal economy with your own customers.
The migration path has four phases. Phase 1 is push-based OTP — a push notification to the bank's app on the registered device, with the customer approving the transaction in-app. The mobile network operator is no longer in the authentication path. Phase 2 is TOTP for opt-in customers — a time-based one-time password seeded into the app at enrolment, displayed in-app, used as the second factor, with no network dependency. Phase 3 is biometric or WebAuthn/passkey on supported devices: Face ID, Touch ID, Android Biometric Prompt, hardware-backed key attestation. Strongest option, increasingly available on the device base Nigerian banking customers actually use. Phase 4 is device binding — the customer's app instance cryptographically bound to a specific device, with authentication on a new device requiring step-up verification (branch visit, video KYC, or an existing device's approval). This closes the residual SIM-swap path even when SMS OTP is gone.
The four phases stack. A Tier 1 bank in 2026 is realistically operating Phase 1 for most customers, Phase 2 for digital-savvy customers, Phase 3 for opt-in customers, and Phase 4 as a baseline for new enrolments. SMS OTP gets demoted from "primary second factor" to "rare fallback" over twelve to eighteen months. It does not get eliminated immediately because the customer base will not tolerate it.
Layer Five — Update Channels And The Signing Chain
The app on the customer's device has to be updatable, and the update channel has to be trustworthy. Play Store and App Store are the trusted channels. Sideloaded updates, in-app update downloads from non-store URLs, and any update mechanism that bypasses the platform's signature verification are not.
Two requirements. Signing keys live in a Hardware Security Module — Android upload key, Android app-signing key (after Play App Signing migration), iOS code-signing certificate. Not on a build server's filesystem. Not in a CI variable. In an HSM with audit logging, where each release signing is an attested operation. The app rejects sideloaded updates and unsigned plug-ins; it does not load executable code at runtime that was not part of the signed bundle — no remote JavaScript-as-code patterns, no dynamic native-library loading from anywhere except the app's own protected directory.
This connects to the signing chain documented in Part 1 — the in-toto attestation and SLSA 3 provenance the build pipeline produces is the input to the signing operation. Provenance is verified at sign-time; the published artefact carries verifiable evidence of its build conditions.
OWASP MASVS, Mapped
The Mobile Application Security Verification Standard (MASVS) v2 is the international reference for mobile-app security controls. The seven layers above map cleanly to the MASVS categories a CBN examiner, NDPA assessor, or counter-party assurance team will recognise:
| Layer | MASVS category |
|---|---|
| RASP — debugger, emulator, hook detection | MASVS-RESILIENCE (R1, R3, R4) — anti-debugging, anti-emulator, anti-hooking |
| RASP — tamper detection, memory protection | MASVS-RESILIENCE (R2) — anti-tampering, integrity verification |
| Certificate pinning | MASVS-NETWORK (N2) — public key pinning |
| Root / jailbreak detection | MASVS-RESILIENCE (R5) — runtime environment verification |
| Move off SMS OTP | MASVS-AUTH (A2, A3) — strong authentication, device-binding |
| Secure update channels, code signing | MASVS-PLATFORM (P1) — secure use of platform features; MASVS-CODE — secure coding and verified build |
We deliver against MASVS Level 2 as a minimum and the MASVS-RESILIENCE profile in full. This is the bar a Tier 1 bank in 2026 is being held to by counter-party assurance teams — international card schemes, correspondent banks. CIS Controls v8 mobile-application provisions map cleanly here too, alongside the NIST Risk Management Framework application-tier expectations.
The Pre-Publication Checklist
We do not publish a new release of a Nigerian Tier 1 banking app to the Play Store or App Store without the following sixteen items verified, signed off, and archived:
- SAST scan clean, with documented exceptions for any high or critical findings. (From Part 1.)
- SCA scan clean against the dependency tree; no high or critical CVEs in shipped components.
- SBOM generated, signed, archived. (From Part 1.)
- RASP active and verified — debugger, emulator, hook, tamper, memory protections all reporting healthy.
- Certificate pinning verified — pin set includes current production key plus backup key; pin-failure telemetry confirmed reaching backend.
- Root / jailbreak detection verified — at least eight independent detection patterns, all reporting status to the backend.
- Backend device-attestation endpoint accepting and verifying client attestations.
- No hardcoded credentials, API keys, encryption keys, or signing material in the build. (Scanner-verified, manual code-review confirmed.)
- Authentication flow verified — primary factor, secondary factor, step-up flows for high-value transactions, device-binding active for new enrolments.
- TLS configuration verified — TLS 1.2 minimum, TLS 1.3 preferred, modern cipher suites only, HSTS on the backend, OCSP stapling.
- Penetration test report from the most recent quarterly pen-test against the staging build, with all findings remediated or formally accepted.
- DAST scan clean against staging deployment. (From Part 1.)
- Code signing performed in HSM with attested operation; signing logs archived in the audit-evidence vault.
- Provenance attestation (in-toto, SLSA 3) generated and archived alongside the release artefact.
- Release notes, change-log, and security-relevant changes documented; sign-off from Head of Application Security, Head of Mobile Banking, and CISO.
- Pre-release tabletop or wargame for any release that changes authentication, payment, or KYC flows.
A release that misses any of these items is not blocked because of a process rule. It is blocked because the bank does not have evidence to defend the release if it produces an incident. The checklist is the evidence chain — the way a surgical team will not start without a verified count of every instrument on the tray.
The CSAT And NDPA Mapping
The mobile-hardening layers map to specific obligations:
| Obligation | Where mobile hardening delivers |
|---|---|
| CBN CSAT — Customer-facing application security | Layers 1, 2, 3, 5 collectively. RASP, pinning, root detection, secure code-signing chain. |
| CBN CSAT — Strong customer authentication | Layer 4 — move off SMS OTP, device binding, MFA. |
| CBN CSAT — Application integrity | Tamper detection (Layer 1), signed updates (Layer 5), SBOM verification (Layer 5 + Part 1). |
| NDPA 2023 — Security of processing | Layer 1 RASP + Layer 2 pinning prevent unauthorised processing of personal data on the device or in transit. |
| NDPA 2023 — Breach response | Pin-failure telemetry + device-attestation feedback give the bank early warning of active campaigns, accelerating the 72-hour clock. |
| NCC consumer-protection guidelines | Layer 4 SIM-swap mitigation is explicitly relevant to the consumer-protection posture the NCC is building toward. |
What A Tier 1 Bank Actually Deploys
The defensible stack picture for 2026. RASP via Promon SHIELD or Guardsquare DexGuard / iXGuard, with Appdome as the no-code alternative for banks without a deep mobile-security engineering bench. Code obfuscation via ProGuard / R8 on Android, Bitcode plus DexGuard equivalents on iOS. Certificate pinning via native platform APIs with bank-controlled pin sets — OkHttp CertificatePinner on Android, NSURLSession evaluator on iOS, libsodium- or BoringSSL-backed for cross-platform layers. Root and jailbreak detection from the RASP vendor plus an in-house augmentation layer that monitors patterns specific to the Nigerian device base (specific OEM modifications, regional jailbreak tools).
Authentication runs push-OTP via the bank's own notification channel, TOTP for opt-in, biometric (Face ID, Android Biometric Prompt, WebAuthn) increasingly default for new devices. Device binding uses a cryptographic key generated per device, attested via Play Integrity API (Android) or DeviceCheck / App Attest (iOS), bound to the customer's enrolled identity. Backend integration runs a device-attestation endpoint in the AWS landing zone, RASP telemetry into Security Lake, pin-failure events into CloudTrail Lake — the integration points the AWS architecture was designed to receive.
The above is the configuration that survives the threat picture the DSI banking briefing documents. A bank running less than this is operating outside the bar its counter-parties — international card schemes, correspondent banks, international card networks — are increasingly enforcing as a precondition of continued relationship.
FAQs
Why is SPKI pinning preferred over certificate pinning, and how do you avoid locking customers out on key rotation?
SPKI pinning hashes the public key, so the certificate can be renewed without breaking pinning as long as the key is reused. To avoid lockout on rotation, the app pins at least two keys — the current production key and a backup held offline. When production rotates, the backup takes over, and the next app release pins a new backup. No customer is ever locked out.
Should we refuse to run on rooted or jailbroken devices?
For a Nigerian retail consumer app, Monitor or Degrade is the defensible landing point — root and jailbreak are common for legitimate reasons in emerging markets, and outright refusal carries a high support cost. For the corporate or treasury app, Refuse is appropriate. The decision sits with the board's risk appetite, not the security team alone.
Can we eliminate SMS OTP immediately?
No — the customer base will not tolerate it. The realistic 2026 posture is push-OTP for most customers, TOTP for digital-savvy customers, biometric or WebAuthn for opt-in, and device binding as a baseline for new enrolments. SMS OTP gets demoted from primary second factor to rare fallback over 12–18 months.
How does mobile hardening integrate with the AWS backend architecture?
Pin-failure events land in CloudTrail Lake; RASP telemetry lands in Security Lake; device attestations are verified at a dedicated endpoint in the AWS landing zone. The integration points were designed into the AWS-for-banks architecture so that mobile telemetry feeds the same evidence plane as backend events — three thousand failed pins in Lagos on a Tuesday morning becomes a visible signal, not a hidden one.
What does an examiner look for in the pre-publication checklist?
Evidence that each control was verified on the specific build being published — SAST and SCA scans clean, SBOM signed and archived, RASP active, pinning telemetry confirmed reaching the backend, HSM signing logs, in-toto provenance attestation, and tabletop sign-off for releases that touch authentication, payment, or KYC. The checklist is the evidence chain that defends the release if it produces an incident.
What This Does Not Cover
The mobile-banking app is the most-targeted surface but not the only one. The identity perimeter — IAM Identity Center, federated identity, MFA, privileged-access architecture — is its own substantial workstream and lands in Part 3 of this series. The backend the app talks to is hardened under the AWS-for-banks architecture and operational series. The branch and agent-network surfaces are out of scope here and are covered in our forthcoming agent-channel-security piece.
When the customer in Surulere downloads the next clone, what does the genuine app on her phone do that the clone cannot?
Part 3 — Identity-First Migration covers the IAM architecture that has to land before any AWS workload is provisioned. Part 1 — Securing the Application covers the build-pipeline and SDLC controls that produce the app this piece hardens.
The AWS-for-banks architecture series — the threat picture (DSI ↗), the architecture, the operational implementation — is the substrate this prequel series prepares the application surface for.
