Aller au contenu

PD-262 — iOS Anti-tampering : detection jailbreak et protection Frida

1. Contexte

L'application iOS ProbatioVault stocke des cles cryptographiques sensibles (Kmaster, enveloppes de recovery, tokens SRP). La review securite PD-174 a identifie deux vulnerabilites critiques :

  • S-01 : bypass de l'authentification biometrique via hook JavaScript (Frida/Objection)
  • S-02 : instrumentation dynamique permettant l'extraction de secrets en memoire

Le mecanisme BIOMETRY_CURRENT_SET (Keychain) protege contre le changement d'empreintes mais ne couvre pas le hooking JS. PD-262 implemente les contre-mesures anti-tampering planifiees dans le REX PD-174.

2. Objectif

Implementer un module natif iOS de detection anti-tampering qui :

  1. Detecte les environnements compromis (jailbreak, instrumentation dynamique, signature invalide)
  2. Verrouille l'application immediatement en cas de detection (fail-closed)
  3. Purge les secrets et caches sensibles en memoire et sur disque
  4. Journalise les causes de detection pour audit et analyse securite
  5. Reporte les evenements au backend en best effort

3. Decisions PO

3.1 Frequence des controles

Les controles anti-tampering sont executes : - Au cold start : check bloquant avant deverrouillage des secrets applicatifs - Au retour foreground : re-check a chaque transition background → foreground - Timer periodique : toutes les 30-60 secondes pendant la session ouverte

Justification : un check uniquement au lancement laisse un trou si Frida/Objection est attache apres demarrage.

3.2 Granularite du verrouillage

  • Lockout unique : un seul etat fonctionnel tampered = true → hard lockout
  • Causes distinguees en audit : JAILBREAK_DETECTED, FRIDA_DETECTED, CODESIGN_INVALID, DYLIB_INJECTION, SANDBOX_VIOLATION

Justification : UX et logique metier simples, securite homogene, meilleure telemetrie.

3.3 Effacement en cas de detection

Purge obligatoire immediate : - Cles derivees en memoire - Tokens session / refresh tokens - Caches crypto - Fichiers temporaires dechiffres - Artefacts de preview

Donnees persistees locales : - Conserver les blobs deja chiffres (inexploitables sans secrets) - Marquer le store local comme inaccessible tant que l'app est lockee - Pas de wipe complet automatique (destructif, difficile a justifier UX/support)

3.4 Reporting backend

  • Lockout et purge declenches localement et immediatement (pas de dependance reseau)
  • Tentative best effort d'envoi d'un evenement d'audit
  • Payload minimal : event_type, reason_code, app_version, build_number, device_id pseudonymise, timestamp, environment
  • Aucune donnee sensible, pas de dump memoire

3.5 Mode release uniquement

  • Desactive en DEBUG et simulateur
  • Active en Release / TestFlight / production
  • Activable en QA via feature flag dedie sur device reel

Justification : ne pas bloquer le dev, les tests RN, le debug natif, l'instrumentation legitime de QA.

3.6 Implementation 100% native

  • Detection, decision, purge et lockout dans le natif (Swift/Obj-C)
  • Exposition a React Native via TurboModule minimal (interrogation d'etat / signal)
  • Aucun check critique ne depend d'une logique JS modifiable a chaud

Justification : coherent avec l'origine du besoin — eviter le bypass par instrumentation JS (PD-174 S-01/S-02).

4. Perimetre fonctionnel

4.1 Detection jailbreak (multi-methodes)

Methode Description
Paths suspects Verification /Applications/Cydia.app, /usr/sbin/sshd, /usr/bin/ssh, /etc/apt, /var/lib/dpkg, Sileo, Zebra
Sandbox integrity Tentative d'ecriture dans /private/ (normalement interdit en sandbox)
Symbolic links Detection de liens symboliques suspects sur les paths systeme
Fork test Appel fork() (interdit en sandbox iOS non-jailbreak)
Dyld check Verification des dylibs chargees via _dyld_image_count() / _dyld_get_image_name()

4.2 Detection Frida/Objection

Methode Description
Port scanning Scan ports par defaut 27042, 27043 (connexion locale)
Dyld injection Detection de FridaGadget.dylib, frida-agent dans les dylibs chargees
Signatures memoire Pattern matching sur frida-agent, gum-js-loop, LIBFRIDA en memoire

4.3 Validation code signing

Methode Description
Bundle signature Verification de l'integrite de la signature du bundle au runtime
Embedded provisioning Verification coherence du profil de provisioning

4.4 Comportement post-detection

  1. Flag tampered = true positionne (irreversible pour la session)
  2. Purge immediate des secrets (cf. §3.3)
  3. Affichage ecran de lockout (non dismissable)
  4. Emission evenement audit backend (best effort)
  5. App inutilisable jusqu'a reinstallation propre

5. Hors perimetre

  • Detection root Android (projet iOS uniquement)
  • Wipe complet automatique des donnees persistees
  • Mecanisme de deblocage distant (remote unlock)
  • Detection de proxy SSL (Charles, mitmproxy) — story separee si besoin
  • Obfuscation du code Swift (complementaire mais hors scope)

6. Dependances

Dependance Story Statut
Keychain Kmaster PD-98 DONE
Biometric auth PD-107 DONE
Auto-lock PD-174 DONE (vulnerabilites S-01/S-02 identifiees)

7. Risques identifies

Risque Impact Mitigation
Faux positifs en production Lockout d'utilisateurs legitimes Tests extensifs sur devices reels, feature flag QA
Contournement par nouvelle technique Protection depassee Architecture modulaire, methodes empilees (defense in depth)
Hermes limitations (PD-97) Polyfills ou APIs indisponibles Module 100% natif, pas de dependance JS
Impact performance du timer Battery drain, CPU Intervalle 30-60s, checks legers, pas de I/O reseau dans le check

8. Learnings injectes

  • PD-174 : BIOMETRY_CURRENT_SET ne protege pas contre hook JS → anti-tampering natif obligatoire
  • PD-97 : Hermes n'a pas de WebAssembly, polyfills a valider en prod → implementation Swift pure
  • PD-39 : fail-closed obligatoire pour features securite critique → pas de mode degrade