L’IDOR (Insecure Direct Object Reference, riferimento diretto non sicuro agli oggetti) è una vulnerabilità informatica di controllo degli accessi in cui un’applicazione web espone riferimenti diretti agli oggetti interni — ID numerici di database, nomi di file, chiavi primarie — nelle URL o nei parametri, senza verificare che l’utente autenticato abbia il diritto di accedere a quell’oggetto specifico. Classificata come CWE-639, è una sottocategoria della “Broken Access Control” (A01 OWASP Top 10 2021) — la vulnerabilità web più comune per numero di occorrenze.
Esempio fondamentale
# L'utente legge il proprio documento:
GET /api/documenti/12345
→ HTTP 200 {"titolo": "Mio Contratto", "contenuto": "..."}
# L'utente modifica l'ID nell'URL:
GET /api/documenti/12346
→ HTTP 200 {"titolo": "Contratto Riservato di Mario Rossi", "contenuto": "..."}
L’applicazione autentica l’utente (verifica che sia loggato) ma non autorizza la richiesta specifica (non verifica che l’utente possa accedere al documento 12346). Un utente malintenzionato può enumerare tutti gli ID in sequenza e accedere a tutti i documenti di tutti gli altri utenti.
Varianti
IDOR su oggetti non sequenziali: anche con UUID o ID casuali il problema esiste se l’applicazione non verifica l’autorizzazione. L’oscurità dell’ID non è sicurezza.
IDOR in modifica e cancellazione: l’utente non solo legge dati altrui, ma li modifica o cancella.
DELETE /api/ordini/99887 ← cancella l'ordine di un altro utente
POST /api/messaggi/5544/archivia ← archivia il messaggio di un altro
IDOR indiretto: l’ID non è nell’URL ma in un parametro del body, in un cookie o in un header. Stessa vulnerabilità, percorso diverso.
Mass Assignment IDOR: un’API accetta aggiornamenti in bulk e l’utente include campi di altri oggetti nel payload, aggirando i controlli.
Causa radice
La causa è architetturale: l’applicazione non esegue un controllo di autorizzazione esplicito che confronti l’utente autenticato con il proprietario o i permessi dell’oggetto richiesto. Spesso il codice verifica solo if user.is_authenticated ma non if user.can_access(document_id).
Mitigazione
La mitigazione corretta è applicare un controllo di autorizzazione server-side ad ogni accesso a ogni oggetto:
# SBAGLIATO: verifica solo l'autenticazione
documento = Documento.objects.get(id=documento_id)
# CORRETTO: verifica l'autorizzazione per l'utente corrente
documento = Documento.objects.get(id=documento_id, proprietario=request.user)
# oppure
if not documento.can_be_accessed_by(request.user):
raise PermissionDenied
Complementarmente: usare riferimenti indiretti (mappare l’ID interno a un identificativo per-sessione), non esporre ID sequenziali prevedibili (usare UUID), e coprire tutti gli endpoint con test di autorizzazione automatizzati.