Nel mondo della sicurezza applicativa su mobile, c’è una realtà con cui prima o poi ci scontriamo: il runtime di un’app, che si può osservare e, in alcuni casi, si può anche alterare. In questo ambito, uno degli strumenti più citati e temuti è Frida. Si tratta di una suite di dynamic instrumentation che permette di interagire con un processo mentre è in esecuzione, anche senza avere accesso al codice sorgente.
Ne ho parlato in occasione di un Lunch & Learn organizzato da Imola Informatica. Nel mio intervento ho cercato di chiarire cosa fa Frida, perché è rilevante per chi, come noi, sviluppa o testa app. E soprattutto quali difese concrete possono ridurre l’impatto di tecniche di hooking e manipolazione.
Cos’è Frida
Frida è spesso descritto come un “kit” che consente di svolgere operazioni sul processo in esecuzione: dalla ricognizione (capire cosa c’è dentro: classi, metodi, librerie) fino all’hooking, vale a dire, l’intercettazione e la sostituzione di comportamenti di funzioni/method a runtime.
Dal punto di vista di un tester, questa capacità è preziosa perché permette di osservare flussi e chiamate senza ricompilare l’app, validare ipotesi, individuare debolezze (controlli lato client aggirabili, validazioni fragili, etc.).
Dal punto di vista di un attaccante, lo stesso set di capacità può diventare un acceleratore per:
- aggirare i controlli locali
- falsificare input/risposte
- manipolare la logica applicativa
- ispezionare i punti sensibili (endpoint, parametri, handling di token, etc.).
DAST vs SAST: perché Frida entra in gioco
In ambito testing, ragioniamo spesso in termini di SAST (analisi statica), cioè lavorare su sorgente o artefatti “statici”, oppure di analisi dinamica, DAST, che riguarda l’osservazione dell’app “in azione”, come black-box.
Frida si colloca nella sfera dinamica, perché opera sul runtime: quando l’app gira, si può vedere cosa sta facendo davvero, non solo cosa “dovrebbe fare” secondo il codice letto o l’architettura dichiarata.
Come riesce a fare hooking?
Oggi i sistemi mobile hanno sandbox e permessi proprio per impedire che un’app interferisca con un’altra. Per questo, l’uso classico di Frida su un dispositivo reale richiede spesso condizioni particolari, come permessi elevati o scenari equivalenti, per poter interagire con processi esterni alla sandbox.
Da un punto di vista concettuale, il flusso è uno “strumento” (lato host) che coordina l’operazione. Ma è anche un componente sul device che si collega al processo target e carica un “agent” nel processo per eseguire script e intercettare funzioni.
A livello di API, possiamo distinguere fra due livelli diversi:
- un livello alto orientato al runtime (es. VM Java su Android) utile per l’enumerazione e l’override di metodi;
- un livello più basso orientato alla memoria e agli indirizzi, più complesso ma utile quando l’alto livello è limitato (per esempio, da offuscamento o vincoli di contesto).
Cosa “dimostra” in un assessment
Se una verifica critica è solo lato client, allora un hook può alterarla e far “passare” un controllo. Questa rappresenta la dimostrazione più classica ed efficace da un punto di vista didattico. Tuttavia, non significa che “Frida rompe tutto”, ma evidenzia un principio fondamentale: il client non è un confine di sicurezza affidabile.
Se una decisione è davvero critica (autorizzazioni, pricing, privilegi, integrità di transazioni, validazioni decisive), deve avere un enforcement server-side. E il client va considerato come manipolabile.
Per difendersi: cosa funziona e cosa no
Non esiste la cura definitiva contro il dynamic instrumentation su un dispositivo controllato dall’utente, ma esistono strategie che innalzano drasticamente il costo dell’attacco e riducono i casi sfruttabili.
- Sposta la sicurezza sul server (la difesa più solida). Se l’app può essere modificata a runtime, allora:
- devono essere validate lato server le autorizzazioni, regole di business critiche, coerenza dati;
- il client può “chiedere”, ma non deve “decidere” da solo.
- Attestazione e segnali di integrità del device. Su mobile esistono meccanismi (hardware-backed dove possibile) che danno segnali utili su integrità dell’ambiente. Se il contesto è compromesso, l’app può ridurre funzionalità o invalidare sessioni sensibili spostando la decisione al backend.
- Offuscamento e hardening: non “blocca”, ma rallenta molto. È una misura di attrito, non un muro: utile perché aumenta tempi, competenze richieste e probabilità di errore per chi attacca. Questo perché l’offuscamento:
- rende meno immediata l’enumerazione e l’identificazione dei punti di hooking;
- complica la reverse engineering, soprattutto se accompagnato da tecniche di anti-tamper/anti-debug.
- Controlli di integrità in memoria (anti-tamper runtime). Alcune difese verificano che porzioni di codice/memoria non siano state alterate e, se rilevano anomalie coerenti con hooking o patching runtime, bloccano l’esecuzione.
Attenzione: queste difese sono spesso un gioco del gatto col topo, ma in scenari reali (specie per attacchi opportunistici) funzionano molto bene come deterrente. - RASP e protezioni commerciali. Le soluzioni RASP (Runtime Application Self-Protection) aggregano più tecniche: rilevazioni di strumentazione, jailbreak/root, tamper, hooking, emulator/farm detection, ecc. Possono essere efficaci, se sono:
- integrate bene
- collegate a policy server-side
- testate in modo robusto prima di andare in produzione.
Frida è importante non perché “rompe” le app, ma perché rende visibile una verità strutturale: ciò che gira sul dispositivo utente può essere osservato e, in certe condizioni, manipolato.
La risposta efficace non è inseguire il mito del “blocco perfetto”. Piuttosto, conviene progettare con un modello di minaccia realistico e spostare le decisioni critiche sul backend. Usare attestation, hardening, anti-tamper e (se serve) RASP per alzare la soglia. Fondamentale, infine, monitorare e reagire a segnali di compromissione.