
NocoDB Shared-Base Links potrebbe invitare membri reali del database e sopravvivere alla revoca della condivisione
I collegamenti di base condivisa di NocoDB potrebbero invitare membri reali della base e sopravvivere alla revoca della condivisione
Ho trovato questo problema mentre esaminavo NocoDB, con una semplice domanda di sicurezza in mente:
Un link pubblico di base condivisa può superare il confine dall'accesso temporaneo condiviso all'iscrizione autenticata reale alla base?
In questo caso, la risposta è stata sì.
Una sessione di base condivisa autenticata solo da xc-shared-base-id veniva trattata come un normale visualizzatore di base ai fini ACL. Poiché i permessi del visualizzatore raggiungevano ancora gli endpoint di gestione dei membri, un utente con solo l'UUID della base condivisa poteva elencare i membri esistenti della base e invitare un indirizzo email arbitrario nella base come membro reale.
Quell'utente invitato poteva quindi riscattare l'invito tramite il normale flusso di registrazione, ottenere un account autenticato standard e mantenere l'accesso alla base anche dopo che il proprietario aveva disabilitato il link di base condivisa.
Tale problema è diventato CVE-2026-46552.
Progetto: NocoDB
Versione affetta validata: 0.301.3
Questo ha interessato NocoDB; sul suo sito ufficiale, NocoDB viene presentato come affidabile per oltre 35.000 organizzazioni, con oltre 20 milioni di download. Il sito elenca anche aziende come Accenture, Western Digital, Hyundai, Walmart, PwC, Bosch e American Express.
link pubblico di base condivisa -> xc-shared-base-id trattato come normale visualizzatore di base -> ACL del visualizzatore raggiunge gli endpoint di gestione membri -> l'attaccante elenca gli utenti della base e invita un'email arbitraria -> l'utente invitato riscatta il normale token di registrazione -> l'accesso autenticato alla base persiste nonostante la revoca del link condiviso
NocoDB è una piattaforma di collaborazione orientata ai database che espone accesso alla base tramite browser, condivisione, gestione dei metadati e flussi di lavoro di iscrizione degli utenti.
Ciò significa che il suo modello di condivisione è un vero confine di sicurezza.
La domanda importante qui non era se i link di base condivisa potessero leggere contenuti condivisi.
La vera domanda era:
Un principal di condivisione pubblica può eseguire azioni che dovrebbero appartenere solo ai membri autenticati della base?
In questo caso, poteva.
Le funzionalità di condivisione pubblica sono facili da sottovalutare.
È un errore.
Una volta che un'applicazione supporta:
il rischio principale non è solo l'esposizione dei dati.
Il rischio più forte è il collasso dei confini:
Questo era il vero problema qui.
Non era un bug nella validazione del login. Non era un problema di falsificazione del token. Non era un difetto nel reset della password.
Era un classico errore del confine di autorizzazione:
Non ho affrontato questo problema sondando a caso endpoint sperando che qualcosa di interessante rispondesse.
La via più solida era identificare prima il confine di fiducia di maggior valore.
Per NocoDB, quello era il confine tra:
Questi due stati non dovrebbero essere intercambiabili.
Un link di base condivisa dovrebbe rappresentare accesso limitato, revocabile e basato su link. Non dovrebbe essere in grado di generare nuovi principal di lunga durata all'interno della base.
È esattamente il confine che è fallito qui.
La vulnerabilità derivava da come l'accesso alla base condivisa era integrato nel normale percorso ACL.
Nel flusso frontend della base condivisa, xc-shared-base-id veniva iniettato mentre le normali intestazioni di autenticazione venivano rimosse.
Poi, nel backend, BaseViewStrategy accettava xc-shared-base-id e traduceva direttamente il link condiviso in normali roles / base_roles derivati dalla configurazione della base condivisa.
Questo era il primo problema.
Il secondo problema era che i permessi a livello di visualizzatore includevano ancora azioni di gestione dei membri.
Nel layer ACL, ProjectRoles.VIEWER poteva raggiungere:
baseUserListuserInviteQuei permessi proteggevano le normali meta rotte:
GET /api/v2/meta/bases/:baseId/usersPOST /api/v2/meta/bases/:baseId/usersQuindi una sessione di condivisione pubblica era effettivamente autorizzata a colpire endpoint di appartenenza destinati a partecipanti reali della base.
L'ultimo passo era nel flusso di invito stesso.
BaseUsersService.userInvite() controllava il potere del ruolo, poi creava:
invite_tokenE per le sessioni di base condivisa:
invited_by diventava nullperché non c'era una reale identità di invito autenticata dietro la richiesta.
Questa è l'intera catena del bug.
Perché il possesso di un link di base condivisa era sufficiente.
L'attaccante non aveva bisogno di:
xc-authLa catena di sfruttamento era semplice:
Questo converte la condivisione di link revocabile in appartenenza durevole.
La distinzione importante è la persistenza attraverso la revoca.
Non si trattava solo di:
"un visualizzatore poteva chiamare un endpoint da visualizzatore"
Il principal vulnerabile non era un normale visualizzatore autenticato.
Era una sessione di condivisione pubblica.
Questo è importante perché l'applicazione trattava un principal transitorio e limitato al link come se fosse abbastanza fidato per:
La vera domanda non era:
"Un utente condiviso può leggere dati condivisi?"
La vera domanda era:
"L'accesso di condivisione pubblica può essere convertito in accesso autenticato permanente che sopravvive alla revoca della condivisione?"
La risposta era sì.
Ecco perché questa è una vera vulnerabilità di autorizzazione, non solo un comportamento applicativo sorprendente.
Ho validato questo localmente contro:
0.301.3dac49b0122c5ee655fb8f46a1b6e42dfeec1f3adhttp://127.0.0.1:8080La riproduzione è stata semplice.
Per prima cosa, ho effettuato l'accesso come account proprietario normale, ho creato una nuova base, ho creato una tabella e ho abilitato l'accesso alla base condivisa come viewer:
PATCH /api/v2/meta/bases/<baseId>/shared
Content-Type: application/json
{
"roles": "viewer"
}
Questo ha restituito l'UUID della base condivisa.
Poi, senza inviare alcun xc-auth, ho usato solo:
xc-shared-base-id: <sharedBaseUuid>
Usando solo quell'intestazione, ho chiamato:
GET /api/v2/meta/bases/<baseId>/users
Questo ha restituito 200 OK e ha esposto i membri reali della base, inclusi gli indirizzi email.
Sempre usando solo xc-shared-base-id, ho chiamato:
POST /api/v2/meta/bases/<baseId>/users
Content-Type: application/json
{
"email": "[email protected]",
"roles": "viewer"
}
Anche questo ha restituito 200 OK.
Per la validazione locale in laboratorio senza recapito email, ho confermato direttamente nel database meta SQLite che:
nc_users_v2 conteneva l'utente invitato con un invite_token non nullonc_base_users_v2 conteneva una riga di appartenenza reale per la base di destinazioneinvited_by era NULLPoi ho riscattato l'invito tramite il normale flusso di registrazione:
POST /api/v2/auth/user/signup
Content-Type: application/json
{
"email": "[email protected]",
"password": "Password123.",
"token": "<invite_token>"
}
Usando l'xc-auth restituito, ho chiamato:
GET /api/v2/meta/bases/<baseId>/tables
Questo ha restituito 200 OK.
Infine, come proprietario, ho disabilitato il link di base condivisa:
DELETE /api/v2/meta/bases/<baseId>/shared
Dopo di che:
xc-shared-base-id falliva con 401xc-auth riusciva ancora con 200200200200200200401200Questo ha stabilito la rivendicazione centrale di sicurezza:
Un singolo invito riuscito a una base condivisa sarebbe già stato sufficiente per mostrare un errore di autorizzazione.
Ma l'intera catena di validazione contava per due ragioni.
Ha mostrato che non si trattava solo di esposizione di endpoint.
La sessione di condivisione pubblica non ha semplicemente raggiunto un'API ristretta. Ha completato l'intera catena di conversione dei privilegi:
Ha dimostrato che non era auto-revocante.
L'impatto più serio è arrivato dopo la disabilitazione del link condiviso:
Questo è ciò che ha trasformato l'accesso temporaneo al link in persistenza di accesso durevole.
Questa vulnerabilità consente a chiunque abbia un link di base condivisa di:
L'impatto principale è sulla riservatezza, perché un attaccante può mantenere un accesso in lettura duraturo ai dati della base condivisa tramite un normale account autenticato.
C'è anche un impatto sull'integrità, perché un principal di condivisione pubblica può modificare lo stato del controllo degli accessi aggiungendo nuovi membri alla base.
Questo è un risultato più forte di una normale fuga di dati. È una rottura del confine di privilegi tra condivisione anonima e appartenenza autenticata.
Questo problema è ragionevolmente classificato come un difetto di autorizzazione cross-scope con impatto sulla riservatezza.
CVSS:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
Quel vettore si adatta al comportamento centrale qui:
La direzione della correzione è semplice.
Le sessioni di base condivisa non dovrebbero ereditare funzionalità di gestione dei membri.
Come minimo:
baseUserList e userInvite da qualsiasi permesso raggiungibile tramite xc-shared-base-idGET e POST /api/v2/meta/bases/:baseId/usersQuesto problema è stato validato localmente contro NocoDB 0.301.3 al commit dac49b0122c5ee655fb8f46a1b6e42dfeec1f3ad.
Il report ha dimostrato:
xc-shared-base-id nei normali ruoli della baseAl problema è stato assegnato:
CVE-2026-46552
La lezione chiave qui è semplice:
l'accesso tramite link condiviso non è la stessa cosa dell'appartenenza fiduciosa.
Molti sistemi si mettono nei guai quando collassano queste due idee nello stesso modello di ruolo.
Un link condiviso può sembrare operativamente simile a un account di visualizzatore, ma le ipotesi di fiducia sono diverse:
Se quel principal con garanzia inferiore può eseguire azioni di gestione o creare nuove identità durevoli, il confine di condivisione è già rotto.
Questo è il vero insegnamento.
Questa vulnerabilità non riguardava l'elusione completa dell'autenticazione.
Riguardava il collasso di due livelli di fiducia che avrebbero dovuto rimanere separati.
In NocoDB, un link di base condivisa avrebbe dovuto fornire accesso temporaneo e revocabile ai contenuti condivisi. Invece, poteva essere usato per elencare membri, invitare un utente reale nella base e convertire l'accesso di condivisione pubblica in appartenenza autenticata durevole che sopravviveva alla revoca della condivisione.
Ecco perché questo è diventato CVE-2026-46552.