La mancanza di un controllo di sicurezza su un endpoint di collezione GET ha permesso a chiunque possedesse un account CoopCycle di base di estrarre l'intero elenco degli indirizzi di ogni negozio in un'istanza condivisa, esponendo nomi, indirizzi stradali e codici postali di innumerevoli clienti. La falla è stata corretta entro due giorni e si esorta gli utenti ad aggiornare all'ultima versione rilasciata.

Come è avvenuta la fuga

CoopCycle – una piattaforma logistica open-source utilizzata dalle cooperative di consegna cibo – definisce la sua API con il framework PHP API Platform. In questo framework, ogni operazione (POST, GET, ecc.) deve essere associata a un'espressione di sicurezza; se l'espressione viene omessa, il framework esegue il codice senza alcun controllo di autorizzazione.

Gli sviluppatori hanno protetto la richiesta POST che crea o aggiorna l'elenco degli indirizzi di un negozio con l'espressione standard is_granted('edit', object). Questo funziona perché la richiesta si rivolge a un'unica entità negozio, fornendo al framework un "oggetto" concreto da valutare.

La richiesta GET che legge la stessa risorsa si rivolge a una collezione: /api/stores/{id}/addresses. Una collezione non ha un singolo oggetto, quindi la stessa espressione is_granted('edit', object) non può essere applicata. Poiché gli sviluppatori hanno omesso la riga di sicurezza, il framework ha fornito i dati degli indirizzi a qualsiasi utente autenticato, indipendentemente dal tenant.

Su un'istanza CoopCycle condivisa, un utente malintenzionato potrebbe semplicemente iterare attraverso gli ID dei negozi, inviare richieste GET all'endpoint ed estrarre gli indirizzi di residenza di ogni cliente memorizzato nel sistema. Non erano richiesti privilegi extra oltre a un normale account.

Perché il bug è sopravvissuto

Il problema non è stato una semplice svista. Il modello di sicurezza dichiarativo di API Platform manca di un modo semplice per esprimere che "l'utente deve appartenere allo stesso tenant di ogni oggetto nella collezione". La riga di codice mancante si trovava esattamente dove il framework rendeva l'autorizzazione macchinosa.

Aggravando la situazione, la suite di test del progetto dichiarava effettivamente che la risposta GET contenente tutti gli indirizzi fosse il comportamento previsto. In altre parole, i test automatizzati passavano perché i fixture utilizzati nei test consentivano l'accesso cross-tenant, mascherando di fatto la vulnerabilità. Una suite di test "verde", in questo caso, ha dato un falso senso di sicurezza.

Chi vince e chi perde

  • Clienti: Le loro informazioni personali identificabili (PII) – nomi completi e indirizzi di residenza – sono state esposte a chiunque sulla piattaforma. Anche se i dati non sono stati pubblicati pubblicamente, la violazione ha compromesso la privacy di diverse cooperative.
  • Cooperative che utilizzano CoopCycle: La fiducia nella capacità della piattaforma di salvaguardare i dati dei tenant è stata scossa. Ogni cooperativa che non si fosse ancora aggiornata affrontava il rischio di una continua esposizione.
  • I manutentori di CoopCycle: La loro rapida risposta – una patch entro due giorni e l'aggiunta di test di regressione – ha limitato la finestra di sfruttamento e ha dimostrato una gestione responsabile dell'open-source. L'incidente, tuttavia, evidenzia la necessità di processi di revisione della sicurezza più rigorosi, specialmente riguardo ai default gestiti dai framework.

Cosa dovrebbero cercare sviluppatori e auditor

  • Asimmetria delle operazioni: Se una POST (o qualsiasi operazione di mutazione) su un percorso è protetta, ma la corrispondente GET è aperta, la discrepanza è un segnale di allarme. La POST rivela l'intento degli sviluppatori di proteggere la risorsa.
  • Endpoint di collezione: Tutto ciò che restituisce un elenco anziché un singolo elemento spesso esce dai consueti pattern di sicurezza. Verificare che i controlli di autorizzazione siano aggiunti esplicitamente per le letture massive.
  • Realismo della suite di test: Assicurarsi che i fixture riflettano i reali confini di tenancy. Un test superato che convalida la fuga di dati cross-tenant è un segnale di avvertimento, non una luce verde.

La correzione e i prossimi passi

Dopo la segnalazione della vulnerabilità, il team core di CoopCycle ha aggiunto l'espressione di sicurezza mancante all'operazione di collezione GET e ha introdotto test di regressione che impongono l'isolamento dei tenant sia per gli endpoint di singoli elementi che per quelli di collezione. La patch è stata rilasciata in una versione successiva del software.

Gli utenti di CoopCycle dovrebbero:

  1. Verificare di utilizzare una versione recente del software.
  2. Esaminare eventuali estensioni o plugin personalizzati che potrebbero introdurre lacune simili a livello di collezione.
  3. Eseguire nuovamente le scansioni di sicurezza concentrandosi sulle asimmetrie di lettura/scrittura su tutte le rotte API.

In sintesi

I framework che rendono la sicurezza dichiarativa possono nascondere lacune pericolose quando gli sviluppatori si affidano a pattern che funzionano solo per singoli oggetti. Un semplice controllo — la parte di lettura di un endpoint ha la stessa protezione della parte di scrittura? — può rivelare una classe di perdite cross-tenant che altrimenti rimarrebbero nascoste dietro suite di test superate con successo.