Una delle vulnerabilità più importanti nel mondo delle API ha un nome piuttosto tecnico:
Broken Object Level Authorization, spesso abbreviato in BOLA.
Il concetto, però, è relativamente semplice.
Un utente è autorizzato a utilizzare un endpoint, ma l'API non verifica correttamente a quale oggetto può accedere.
Un esempio semplice
Immaginiamo un'applicazione che permetta agli utenti di visualizzare i propri ordini.
L'API potrebbe utilizzare:
GET /api/orders/123
L'utente autenticato può naturalmente visualizzare il proprio ordine 123.
Il problema nasce se il server si limita a controllare:
"L'utente è autenticato?"
senza verificare:
"L'ordine 123 appartiene realmente a questo utente?"
Questa è la differenza fondamentale.
Autenticazione e autorizzazione non sono la stessa cosa
Supponiamo che Paolo abbia effettuato correttamente il login.
Il server sa quindi:
Utente autenticato: Paolo
Ma quando arriva:
GET /api/orders/456
deve verificare anche:
Ordine 456
↓
appartiene a Paolo?
Se appartiene a un altro utente, la richiesta deve essere rifiutata.
Quindi:
Autenticazione
↓
Chi sei?
Autorizzazione
↓
Cosa puoi fare?
Su quale risorsa?
Perché le API sono particolarmente interessate?
Le API utilizzano frequentemente identificatori per individuare oggetti:
/users/123
/orders/456
/documents/789
/projects/321
Gli identificatori possono essere:
123
456
789
ma anche:
UUID
stringhe
codici
VIN
slug
Il formato dell'identificatore non risolve da solo il problema.
Anche un UUID, se utilizzato senza un corretto controllo di autorizzazione, non garantisce che l'accesso sia legittimo.
OWASP considera BOLA uno dei rischi principali delle API e sottolinea che il controllo deve verificare l'autorizzazione dell'utente sulla specifica risorsa richiesta.
Non basta rendere gli ID difficili da indovinare
Cambiare:
/orders/123
in:
/orders/550e8400-e29b-41d4-a716-446655440000
può rendere l'identificatore meno prevedibile.
Ma non sostituisce l'autorizzazione.
La domanda rimane:
L'utente può accedere a questa risorsa?
Il server deve rispondere a questa domanda indipendentemente dal formato dell'ID.
Un esempio con documenti
Immaginiamo una piattaforma di gestione documentale:
GET /api/documents/abc123
Un utente è autorizzato ad accedere ai propri documenti.
Il server dovrebbe verificare qualcosa concettualmente simile a:
utente autenticato
+
documento richiesto
↓
verifica autorizzazione
↓
accesso consentito?
Non dovrebbe semplicemente:
ID documento
↓
query database
↓
restituzione documento
senza verificare il proprietario o il ruolo dell'utente.
Il problema può riguardare anche le operazioni di modifica
BOLA non riguarda soltanto la lettura.
Può coinvolgere anche:
GET
PUT
PATCH
DELETE
Ad esempio, un utente potrebbe essere autorizzato a modificare il proprio profilo, ma non quello di un altro utente.
Oppure potrebbe poter cancellare i propri documenti ma non quelli appartenenti a un'altra organizzazione.
Quindi il controllo deve essere applicato a ogni operazione rilevante.
Come si manifesta in un'API?
Una struttura come questa:
/api/users/{id}
/api/orders/{id}
/api/documents/{id}
non è di per sé vulnerabile.
È semplicemente un pattern molto comune.
Il problema nasce quando il server utilizza {id} per recuperare una risorsa senza verificare correttamente il rapporto tra:
utente
+
risorsa
+
azione richiesta
Questo è il motivo per cui la semplice presenza di ID negli URL non dovrebbe essere segnalata automaticamente come vulnerabilità.
Perché è difficile da rilevare automaticamente?
Un controllo esterno può individuare endpoint come:
/api/orders/{id}
ma per confermare BOLA è normalmente necessario comprendere anche il modello di autorizzazione.
Bisogna sapere, ad esempio:
Account A → Ordine A
Account B → Ordine B
e verificare che:
Account A → Ordine B
venga correttamente rifiutato.
Questa è una delle ragioni per cui alcuni problemi di sicurezza API non possono essere determinati soltanto attraverso una scansione anonima.
Cosa dovrebbe fare lo sviluppatore?
La verifica dell'autorizzazione dovrebbe essere effettuata lato server.
L'API non dovrebbe fidarsi del fatto che il client abbia inviato un identificatore valido.
Inoltre, è utile avere test automatici che verifichino scenari come:
Utente A → risorsa A ✓
Utente A → risorsa B ✗
Admin → risorsa A ✓
Utente normale → funzione amministrativa ✗
BOLA e controllo degli accessi
BOLA è un esempio molto concreto di una regola generale:
Non basta verificare chi sta effettuando una richiesta. Bisogna verificare cosa può fare con quella specifica risorsa.
Questo diventa particolarmente importante in applicazioni multiutente.
Per esempio:
SaaS
E-commerce
CRM
Cloud storage
Gestionale
Social network
Piattaforme B2B
tutte queste applicazioni possono avere oggetti associati a utenti o organizzazioni differenti.
Una checklist per gli sviluppatori
Per gli endpoint che utilizzano identificatori di oggetti:
- [ ] l'utente è autenticato quando necessario;
- [ ] viene verificato il permesso sulla specifica risorsa;
- [ ] il controllo avviene lato server;
- [ ] il controllo viene applicato a lettura e modifica;
- [ ] gli identificatori non vengono considerati una misura di sicurezza;
- [ ] esistono test per utenti con ruoli differenti;
- [ ] le risposte non rivelano dati appartenenti ad altri utenti.
BOLA e MiHakero
BOLA rappresenta anche un buon esempio dei limiti e delle possibilità di un controllo esterno.
Una piattaforma può individuare endpoint, parametri e strutture API che meritano attenzione.
La conferma di un problema di autorizzazione, però, può richiedere una conoscenza più profonda dell'applicazione e dei suoi utenti.
Per questo un buon processo di sicurezza dovrebbe distinguere tra:
Endpoint individuato
↓
Possibile superficie sensibile
↓
Controllo di autorizzazione
↓
Vulnerabilità confermata
La sicurezza API non consiste quindi soltanto nel proteggere gli endpoint.
Consiste nel fare in modo che ogni utente possa accedere soltanto agli oggetti che gli spettano.