SQL Injection nello sviluppo mobile: cos'è, metodi di attacco e protezione

Autore: IT Sectr Pubblicato: 2026-04-06 Tempo di lettura: 9 min

SQL Injection è un tipo di attacco al database di un'applicazione in cui un attaccante inietta codice SQL malizioso nei parametri di query, ottenendo accesso non autorizzato ai dati o la possibilità di modificarli. Secondo OWASP (2025), SQL Injection rimane una delle vulnerabilità critiche in grado di portare a un compromesso completo del database. L'iniezione di codice SQL consente all'attaccante di leggere, modificare ed eliminare record e, in alcuni casi, di ottenere l'accesso al sistema operativo del server.

Punti chiave

  • SQL Injection — iniezione di codice SQL tramite parametri utente, alterando la logica della query al database
  • Parametrizzazione delle query — il metodo di protezione principale: separare il codice SQL dai dati usando prepared statements
  • Tipi di attacchi — iniezione classica (tramite WHERE), Blind SQLi (inferenze logiche), UNION-based (lettura di altre tabelle)
  • Error-based SQLi — estrazione di dati tramite messaggi di errore del database
  • Framework ORM — riducono il rischio SQLi se usati correttamente, ma non lo eliminano completamente

Cos'è SQL Injection?

SQL Injection è una vulnerabilità che si verifica quando un'applicazione costruisce query SQL tramite concatenazione di stringhe con dati utente. Un attaccante passa una stringa appositamente costruita in un parametro di query che modifica la struttura del comando SQL. Invece di essere dati, la stringa iniettata diventa parte del codice SQL, consentendo all'attaccante di eseguire query arbitrarie contro il database. Secondo il Rapporto sulle violazioni dei dati di Verizon (2025), SQL Injection è presente nell'8% di tutte le violazioni dei dati investigate.

Perché SQL Injection è ancora rilevante?

Nonostante sia una vulnerabilità ben nota (prima menzione alla fine degli anni '90), SQL Injection si trova ancora nelle applicazioni moderne. Il motivo è l'errore umano: gli sviluppatori scrivono codice con concatenazione di stringhe, il codice legacy non viene rifattorizzato e i framework ORM vengono usati in modo errato (ad esempio, query raw con interpolazione di stringhe). Secondo Veracode (2026), circa il 14% di tutte le applicazioni scansionate contiene almeno una vulnerabilità SQLi.

Cosa può fare un attaccante?

Un'iniezione SQL riuscita offre all'attaccante un'ampia gamma di capacità: leggere qualsiasi tabella del database, inclusi hash di password e dati personali degli utenti; modificare ed eliminare record; eseguire operazioni amministrative (DROP TABLE, TRUNCATE); e in alcune configurazioni, l'esecuzione remota di comandi tramite xp_cmdshell (MSSQL) o INTO OUTFILE (MySQL). Le conseguenze vanno dalla fuga di dati utente alla perdita totale del controllo del sistema.

Tipi di iniezioni SQL

Le iniezioni SQL sono classificate in base al metodo di estrazione dei dati dal database. La scelta del metodo dipende da come l'applicazione gestisce i risultati delle query e i messaggi di errore. La classificazione OWASP identifica tre tipi principali: In-band (dati estratti attraverso lo stesso canale), Inferential/Blind (inferenze logiche) e Out-of-band (dati trasmessi attraverso un altro canale).

TipoMetodo di estrazioneComplessitàFrequenza
In-band (classico)Direttamente attraverso il risultato della queryBassaAlta
Blind SQLiInferenze logiche dalle risposte del serverAltaMedia
Out-of-bandAttraverso un canale esterno (DNS, HTTP)MediaBassa

In-band SQL Injection (Classica)

Il tipo più comune. Un attaccante inietta codice SQL in un parametro di query e il risultato dell'iniezione è direttamente visibile nella risposta del server. Due sottotipi: Error-based (attraverso messaggi di errore del DB) e UNION-based (attraverso l'operatore UNION SELECT). Error-based utilizza le informazioni dai messaggi di errore, come un errore di sintassi MySQL che può rivelare il nome della tabella o la struttura della query. UNION-based consente di combinare i risultati di query legittime con dati di altre tabelle del database.

Blind SQL Injection (Cieca)

Utilizzata quando l'applicazione non mostra i risultati della query o i messaggi di errore. Un attaccante pone domande sì/no inviando query con condizioni logiche e analizzando le differenze nelle risposte del server (ad esempio, tempo di risposta o contenuto della pagina). Time-based Blind SQLi utilizza funzioni di ritardo (SLEEP, WAITFOR DELAY) per confermare le condizioni — se la pagina impiega più tempo a caricare, la condizione è vera. Questo metodo è molto lento — l'estrazione di un singolo record può richiedere ore.

python
# Esempio di Blind SQL Injection (basata sul tempo)
# Se SQLi è vulnerabile, SLEEP(2) viene eseguito se la condizione è soddisfatta
import requests
import time

payload = "' OR IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',SLEEP(2),0) -- "
url = "http://example.com/user?id=1" + payload

start = time.time()
response = requests.get(url)
elapsed = time.time() - start

# Se la risposta arriva dopo >2 secondi — la prima lettera della password è 'a'
print(f"Time: {elapsed:.2f}s - First letter is 'a'" if elapsed > 2 else "First letter is not 'a'")

Out-of-band SQL Injection

I dati vengono trasmessi non attraverso la risposta HTTP ma tramite canali alternativi: query DNS, richieste HTTP a un server esterno, SMTP. Utilizzata quando l'applicazione non restituisce i risultati della query né mostra errori. MySQL supporta la funzione LOAD_FILE(), che può attivare una query DNS, e MSSQL ha xp_dirtree per inviare dati a un server SMB remoto. Out-of-band SQL Injection è efficace ma richiede configurazione aggiuntiva del server attaccante e funzioni DB specifiche.

Come funziona l'iniezione SQL?

Il meccanismo di SQL Injection si basa sul fatto che SQL utilizza virgolette per i letterali di stringa. Se un'applicazione inserisce l'input utente direttamente in una query SQL senza escapparlo, un attaccante può “chiudere” la stringa e aggiungere codice SQL arbitrario. Ad esempio, nella query SELECT * FROM users WHERE name = '$input', inserire ' OR '1'='1 la trasforma in SELECT * FROM users WHERE name = '' OR '1'='1', che restituisce tutti gli utenti.

Esempio classico: Bypass dell'autenticazione

Consideriamo un modulo di login con la query SELECT * FROM users WHERE username = '$user' AND password = '$pass'. Se un attaccante inserisce admin' -- nel campo nome utente e lascia la password vuota, la query risultante diventa SELECT * FROM users WHERE username = 'admin' -- ' AND password = ''. I caratteri -- commentano il resto della query, disattivando il controllo della password. Il server restituisce il record dell'utente admin e l'attaccante accede senza conoscere la password.

python
# Esempio di SQL Injection — Bypass dell'autenticazione
# CODICE VULNERABILE: concatenazione diretta di stringhe
def login_vulnerable(username, password):
    query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
    cursor.execute(query)
    return cursor.fetchone() is not None

# username = "admin' --" annulla il controllo della password
# VERSIONE SICURA: query parametrizzata
def login_secure(username, password):
    query = "SELECT * FROM users WHERE username = %s AND password = %s"
    cursor.execute(query, (username, password))
    return cursor.fetchone() is not None

UNION-based: Lettura di altre tabelle

L'operatore UNION SELECT consente di combinare i risultati di due query SELECT. Se un attaccante trova un parametro vulnerabile, aggiunge UNION SELECT con una query da un'altra tabella. Esempio: ' UNION SELECT username, password FROM admins --. La condizione di successo è che il numero di colonne in entrambe le query deve corrispondere. Il numero di colonne viene determinato tramite ORDER BY (inserendo ' ORDER BY 1--, poi 2, 3... fino a un errore). Conoscendo il numero di colonne, l'attaccante inserisce UNION SELECT con lo stesso numero di campi.

SQL Injection nelle applicazioni mobili

Le applicazioni mobili affrontano SQL Injection sia lato server (API) che lato client — nei database locali (SQLite, Realm). Mentre la SQLi lato server nelle API mobili è simile alle applicazioni web, i database locali creano un vettore aggiuntivo. Se un'applicazione memorizza dati in SQLite ed esegue query con concatenazione di stringhe, i dati maliziosi che entrano nel database locale tramite l'API possono attivare SQLi durante l'elaborazione successiva.

SQL Injection in SQLite su Android/iOS

Il database locale SQLite su un dispositivo è anch'esso vulnerabile a SQL Injection se l'applicazione costruisce query concatenando stringhe. I Content Providers su Android e Core Data su iOS utilizzano la parametrizzazione per impostazione predefinita, ma le query raw richiedono l'attenzione dello sviluppatore. SQLite non supporta query multiple separate da punto e virgola, il che limita le opzioni dell'attaccante ma non protegge dalla lettura dei dati tramite condizioni WHERE. Utilizzare sempre selectionArgs in Android e NSPredicate con parametri in iOS.

SQL Injection tramite API dell'applicazione mobile

L'API con cui un'applicazione mobile comunica è vulnerabile come qualsiasi server web. Gli sviluppatori mobili spesso assumono che SQLi sia solo un problema del backend, ma la vulnerabilità si verifica all'endpoint dell'API che accetta parametri dal client. La separazione delle responsabilità non protegge: se lo sviluppatore backend ha dimenticato di parametrizzare la query, l'app mobile dell'utente diventa un vettore d'attacco. Richiedere al backend l'uso di ORM o prepared statements.

kotlin
// Esempio di SQL Injection in SQLite locale su Android
// CODICE VULNERABILE: concatenazione diretta
fun getUserVulnerable(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = $userId", null
    )
}

// VERSIONE SICURA: parametrizzazione tramite selectionArgs
fun getUserSecure(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = ?",
        arrayOf(userId)
    )
}

Metodi di prevenzione di SQL Injection

La protezione contro SQL Injection si basa su un principio semplice: non fidarsi mai dell'input utente nelle query SQL. L'unico metodo affidabile è la parametrizzazione delle query (prepared statements), dove il codice SQL e i dati vengono passati separatamente. Tutti gli altri metodi — escaping, validazione, WAF — sono livelli di sicurezza aggiuntivi ma non sostituiscono la parametrizzazione. Secondo OWASP (2025), la parametrizzazione previene il 100% degli attacchi SQL Injection.

Prepared Statements (Query parametrizzate)

Utilizzando prepared statements, la query SQL viene prima compilata dal server DB senza dati, e poi i valori dei parametri vengono passati separatamente. Il database tratta i parametri come dati, non come codice eseguibile. Anche se un attaccante passa ' OR '1'='1, il database lo interpreta come un valore stringa, non come codice SQL. I prepared statements sono supportati da tutti i linguaggi e framework moderni: PDO in PHP, PreparedStatement in Java, cursor.execute in Python.

Framework ORM e Query Builder

Gli ORM moderni (Hibernate, Entity Framework, SQLAlchemy, Room) utilizzano automaticamente la parametrizzazione durante l'esecuzione delle query, a meno che lo sviluppatore non passi a query raw. Tuttavia, gli ORM non proteggono completamente: costrutti come @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true) in JPA richiedono il passaggio di parametri tramite parametri nominati, non per concatenazione. I Query Builder (Knex, jOOQ) parametrizzano anch'essi le query per impostazione predefinita se non vengono utilizzati metodi raw.

Escaping di stringhe (non raccomandato come metodo principale)

L'escaping di caratteri speciali (mysql_real_escape_string) è un metodo obsoleto che non protegge da tutti i tipi di SQL Injection. Il problema: l'escaping dipende dalla codifica e può essere bypassato utilizzando codifiche multibyte (ad esempio, GBK nei sistemi asiatici). Utilizzare l'escaping solo in codice legacy dove la parametrizzazione è impossibile, e sempre in combinazione con una rigorosa validazione del tipo di input.

MetodoEfficaciaRaccomandazione
Prepared Statements100%Obbligatorio per tutte le query
ORM (uso corretto)99%Raccomandato
Escaping di stringhe70% (dipende dalla codifica)Solo legacy
Validazione input (white-list)50% (solo numeri)Aggiuntivo
WAF (Web Application Firewall)60%Aggiuntivo

Principio del minimo privilegio per il DB

L'account dell'applicazione dovrebbe avere i privilegi minimi necessari: SELECT, INSERT, UPDATE, DELETE — solo sulle tabelle di cui l'applicazione ha effettivamente bisogno. Vietare l'uso di DROP, TRUNCATE, CREATE per l'account dell'applicazione. Questo limita i danni anche in caso di iniezione SQL riuscita: l'attaccante non potrà eliminare tabelle o eseguire operazioni amministrative.

Strumenti per rilevare iniezioni SQL

I test regolari di SQL Injection dovrebbero far parte del pipeline di sviluppo sicuro. Una combinazione di analisi statica, scansione dinamica e test di penetrazione manuali offre i migliori risultati. Secondo il Rapporto sulla cybersecurity di Synopsys (2025), gli scanner automatizzati trovano fino al 70% delle vulnerabilità SQLi, ma gli attacchi Blind complessi richiedono test manuali.

  • sqlmap — lo strumento più popolare per il rilevamento e lo sfruttamento automatico di SQL Injection
  • OWASP ZAP — uno scanner DAST gratuito con moduli di scansione attiva di SQLi
  • Burp Suite Scanner — uno strumento professionale con rilevamento automatico di SQL Injection
  • SonarQube — analisi statica del codice per vulnerabilità, inclusi i pattern SQLi
  • CodeQL — analisi semantica del codice per trovare iniezioni SQL nel codice sorgente

Per le applicazioni mobili, anche l'analisi di SQLite locale è importante: verificare tutte le chiamate rawQuery, le query ContentProvider e le query Room con rawQuery. Strumenti: Android Studio Lint (rileva SQLi in SQLite), MobSF (Mobile Security Framework) per l'analisi statica e dinamica automatica di APK/IPA. Si raccomanda anche di testare gli endpoint API tramite sqlmap con intercettazione proxy del traffico dell'applicazione mobile.

Domande frequenti

Qual è la differenza tra SQL Injection e NoSQL Injection?

SQL Injection attacca i database relazionali tramite query SQL. NoSQL Injection colpisce i database non relazionali (MongoDB, Couchbase) attraverso i loro operatori di query ($gte, $ne, $where). In MongoDB, l'iniezione è possibile se l'applicazione costruisce un documento BSON da una stringa JSON. I meccanismi di protezione sono simili: parametrizzazione e validazione dei tipi.

Come rilevare SQL Injection nel codice da soli?

Trovare tutti i punti in cui le query SQL sono formate tramite concatenazione di stringhe con dati utente. Cercare pattern come "SELECT ... WHERE id = " + userId o f"UPDATE ... SET name = '{name}'". Ogni riga di questo tipo è una potenziale iniezione SQL. Sostituirle tutte con query parametrizzate o prepared statements.

L'ORM protegge automaticamente da SQL Injection?

I framework ORM proteggono automaticamente solo se si utilizzano i loro metodi Query Builder e parametri nominati. Se si utilizzano query raw (nativeQuery in JPA, rawQuery in Room), la protezione non funziona — è necessario passare i parametri tramite espressioni preparate, non tramite concatenazione di stringhe.

Cos'è Second-Order SQL Injection?

Second-Order SQL Injection è un attacco in cui dati maliziosi vengono memorizzati nel database come sicuri, ma poi utilizzati in un'altra query senza escaping. Ad esempio, un attaccante si registra con un nome utente come ' OR '1'='1. I dati vengono salvati come stringa — non c'è attacco al momento della registrazione. Ma se un'altra query utilizza il nome utente in SQL senza parametrizzazione, l'iniezione si attiva.

NoSQL Injection può essere più pericoloso di SQL Injection?

NoSQL Injection può essere potenzialmente più pericoloso a causa della minore consapevolezza degli sviluppatori. Gli sviluppatori conoscono SQL Injection e la maggior parte usa ORM, ma pochi conoscono NoSQL Injection. In MongoDB, una query malformata può restituire tutti i documenti di una collezione. La protezione è la stessa — prepared statements (parametrizzazione BSON) e rigorosa validazione dell'input.

Riepilogo

  • SQL Injection — un attacco che inietta codice SQL tramite parametri utente non escapati nelle query al DB
  • Tipi principali — In-band (classica), Blind (cieca, basata sul tempo), Out-of-band (tramite canale esterno)
  • Parametrizzazione delle query — l'unico metodo 100% affidabile di protezione contro SQL Injection
  • Mito dell'ORM — l'ORM protegge solo quando si usano metodi integrati; le query raw con concatenazione rimangono vulnerabili
  • Principio del minimo privilegio — limitare i privilegi dell'account DB minimizza i danni in caso di attacco riuscito
  • Test regolari — sqlmap, OWASP ZAP, SonarQube dovrebbero far parte del pipeline CI/CD
  • SQLite locale — le applicazioni mobili devono anch'esse parametrizzare le query al database locale

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche