La falla più comune nei portali è invisibile a qualunque scanner
Un portale clienti. Un utente vero, con login regolare, apre un suo documento. L’indirizzo è qualcosa come /api/documenti/4187.
Cambia il numero. 4186. E vede il contratto firmato di un’altra azienda.
È la prima voce della classifica OWASP per le API, si chiama Broken Object Level Authorization, e la troviamo in una buona parte dei portali su cui ci chiamano.
Perché nessuno scanner la trova
Perché tecnicamente non c’è nessun errore. Il programma fa esattamente quello che gli è stato chiesto: gli è stato chiesto il documento 4186, e lui restituisce il documento 4186. Non va in crash, non produce warning, risponde 200.
Uno strumento automatico cerca schemi noti: input non filtrati, versioni vecchie, configurazioni sbagliate. Non può sapere che quel documento non è di chi lo sta chiedendo, perché quell’informazione sta nel vostro modello di business, non nel codice.
Come si scrive per sbaglio
Così:
if (!utente_autenticato()) {
return null;
}
return db()->riga('SELECT * FROM documenti WHERE id = ?', [$id]);
Un controllo c’è, ed è quello che tutti si aspettano di vedere: senza login non si passa. Ma la domanda a cui l’ultima riga risponde è «esiste il documento 4186?», non «il documento 4186 è di chi lo sta chiedendo?».
Come si chiude
$utente = utente_autenticato();
if (!$utente) {
return null;
}
return db()->riga(
'SELECT * FROM documenti WHERE id = ? AND cliente_id = ?',
[$id, $utente->cliente_id]
);
La correzione non aggiunge un controllo: toglie la possibilità di dimenticarlo.
Finché l’autorizzazione è un if scritto accanto alla query, prima o poi qualcuno scriverà una query nuova senza quell’if a fianco — magari fra due anni, magari un fornitore diverso. Messa dentro la query, la domanda sbagliata non si può più formulare.
E c’è un effetto collaterale utile: chi prova un numero a caso riceve un 404, quindi non impara nemmeno che quel numero corrisponde a qualcosa.
Come si verifica sul vostro
Serve una persona che provi, con due account di prova e mezz’ora. Aprite qualcosa con il primo account, prendete l’indirizzo, e riprovate con il secondo. Se vedete il documento del primo, avete trovato.
Non serve essere tecnici per fare questa prova. Serve solo farla.
$ ls ./journal --altri
Da leggere dopo
Portale clienti: quando conviene e quando è uno spreco
Non è una questione di dimensione dell'azienda. È una questione di quante volte alla settimana rispondi alla stessa domanda.
Quanto ti costa un contatto? Se non lo sai, stai spendendo al buio
Il conto è una divisione. Il difficile non è farla: è avere i due numeri giusti, e quasi nessuno ce li ha.
Un preventivo dato prima del prototipo è una scommessa
Perché chiediamo di costruire le schermate principali prima di dire quanto costa tutto il resto — e perché conviene anche a chi paga.
