
NocoDB Shared-Base-Links könnten echte Basis-Mitglieder einladen und die Widerrufung von Freigaben überleben
NocoDB Shared-Base-Links können echte Base-Mitglieder einladen und den Widerruf der Freigabe überleben
Ich habe dieses Problem gefunden, während ich NocoDB überprüft habe, mit einer einfachen Sicherheitsfrage im Kopf:
Kann ein öffentlicher Shared-Base-Link die Grenze von temporärem gemeinsamem Zugang zur echten authentifizierten Base-Mitgliedschaft überschreiten?
In diesem Fall war die Antwort ja.
Eine Shared-Base-Sitzung, die nur durch xc-shared-base-id authentifiziert war, wurde für ACL-Zwecke als normaler Base-Viewer behandelt. Da Viewer-Berechtigungen immer noch Member-Management-Endpunkte erreichten, konnte ein Benutzer mit nur der Shared-Base-UUID vorhandene Base-Mitglieder aufzählen und eine beliebige E-Mail-Adresse als echtes Mitglied in die Base einladen.
Dieser eingeladene Benutzer konnte dann die Einladung über den normalen Anmeldevorgang einlösen, ein standardmäßig authentifiziertes Konto erhalten und den Base-Zugang behalten, selbst nachdem der Besitzer den Shared-Base-Link deaktiviert hatte.
Dieses Problem wurde zu CVE-2026-46552.
Projekt: NocoDB
Bestätigte betroffene Version: 0.301.3
Dies betraf NocoDB, auf seiner offiziellen Website wird NocoDB als vertrauenswürdig von 35.000+ Organisationen und mit 20+ Millionen Downloads präsentiert. Die Website listet auch Unternehmen wie Accenture, Western Digital, Hyundai, Walmart, PwC, Bosch und American Express.
public shared-base link -> xc-shared-base-id treated as normal base viewer -> viewer ACL reaches member-management endpoints -> attacker lists base users and invites arbitrary email -> invited user redeems normal signup token -> durable authenticated base access survives shared-link revocation
NocoDB ist eine datenbankorientierte Kollaborationsplattform, die browserbasierten Base-Zugriff, Freigabe, Metadatenverwaltung und Benutzermitgliedschafts-Workflows bereitstellt.
Das bedeutet, dass sein Freigabemodell eine echte Sicherheitsgrenze ist.
Die wichtige Frage hier war nicht, ob Shared-Base-Links gemeinsam genutzte Inhalte lesen können.
Die eigentliche Frage war:
Kann ein öffentlicher Freigabe-Prinzipal Aktionen ausführen, die nur authentifizierten Base-Mitgliedern gehören sollten?
In diesem Fall konnte er.
Öffentliche Freigabefunktionen werden leicht unterschätzt.
Das ist ein Fehler.
Sobald eine Anwendung Folgendes unterstützt:
ist das Hauptrisiko nicht nur die Datenpreisgabe.
Das stärkere Risiko ist der Grenzzusammenbruch:
Das war das eigentliche Problem hier.
Dies war kein Fehler in der Anmeldevalidierung. Es war kein Token-Fälschungsproblem. Es war kein Passwort-Reset-Fehler.
Es war ein klassischer Autorisierungsgrenzfehler:
Ich bin nicht so vorgegangen, dass ich zufällig Endpunkte abgefragt und gehofft habe, dass etwas Interessantes antwortet.
Der stärkere Weg war, zuerst die wertvollste Vertrauensgrenze zu identifizieren.
Für NocoDB war das die Grenze zwischen:
Diese beiden Zustände sollten nicht austauschbar sein.
Ein Shared-Base-Link soll einen abgegrenzten, widerrufbaren, linkbasierten Zugriff darstellen. Er sollte keine neuen langlebigen Prinzipale innerhalb der Base erzeugen können.
Das ist genau die Grenze, die hier versagt hat.
Die Schwachstelle entstand dadurch, wie Shared-Base-Zugriff in den normalen ACL-Pfad integriert wurde.
Im Shared-Base-Frontend-Flow wurde xc-shared-base-id injiziert, während normale Auth-Header entfernt wurden.
Dann akzeptierte BaseViewStrategy im Backend xc-shared-base-id und übersetzte den geteilten Link direkt in normale roles / base_roles, die aus der Shared-Base-Konfiguration abgeleitet wurden.
Das war das erste Problem.
Das zweite Problem war, dass Viewer-Level-Berechtigungen immer noch Member-Management-Aktionen beinhalteten.
In der ACL-Ebene konnte ProjectRoles.VIEWER Folgendes erreichen:
baseUserListuserInviteDiese Berechtigungen schützten normale Meta-Routen:
GET /api/v2/meta/bases/:baseId/usersPOST /api/v2/meta/bases/:baseId/usersEine öffentliche Freigabesitzung durfte also effektiv Mitgliedschafts-Endpunkte ansprechen, die für echte Base-Teilnehmer vorgesehen waren.
Der letzte Schritt war im Einladungsfluss selbst.
BaseUsersService.userInvite() überprüfte die Rollenmacht und erstellte dann:
invite_tokenUnd für Shared-Base-Sitzungen:
invited_by zu nullweil es keine echte authentifizierte Einladenden-Identität hinter der Anfrage gab.
Das ist die gesamte Fehlerkette.
Weil der Besitz eines Shared-Base-Links ausreichte.
Der Angreifer brauchte nicht:
xc-authDie Ausnutzungskette war geradlinig:
Das verwandelt widerrufbares Link-Sharing in dauerhafte Mitgliedschaft.
Der wichtige Unterschied ist die Persistenz über den Widerruf hinweg.
Es ging nicht nur darum:
„Ein Viewer könnte einen Viewer-Endpunkt aufrufen“
Der anfällige Prinzipal war kein normaler authentifizierter Viewer.
Es war eine öffentliche Freigabesitzung.
Das ist wichtig, weil die Anwendung einen flüchtigen, linkgebundenen Prinzipal so behandelte, als wäre er vertrauenswürdig genug, um:
Die eigentliche Frage war nicht:
„Kann ein geteilter Benutzer geteilte Daten lesen?“
Die eigentliche Frage war:
„Kann öffentlicher Freigabezugriff in dauerhaften authentifizierten Zugriff umgewandelt werden, der den Widerruf der Freigabe überlebt?“
Die Antwort war ja.
Deshalb ist dies eine echte Autorisierungsschwachstelle und nicht nur überraschendes Anwendungsverhalten.
Ich habe dies lokal validiert gegen:
0.301.3dac49b0122c5ee655fb8f46a1b6e42dfeec1f3adhttp://127.0.0.1:8080Die Reproduktion war geradlinig.
Zuerst meldete ich mich als normaler Besitzer an, erstellte eine neue Base, erstellte eine Tabelle und aktivierte den Shared-Base-Zugriff als viewer:
PATCH /api/v2/meta/bases/<baseId>/shared
Content-Type: application/json
{
"roles": "viewer"
}
Das gab die Shared-Base-UUID zurück.
Dann, ohne xc-auth zu senden, verwendete ich nur:
xc-shared-base-id: <sharedBaseUuid>
Mit nur diesem Header rief ich auf:
GET /api/v2/meta/bases/<baseId>/users
Das gab 200 OK zurück und legte echte Base-Mitglieder offen, einschließlich E-Mail-Adressen.
Mit immer noch nur xc-shared-base-id rief ich auf:
POST /api/v2/meta/bases/<baseId>/users
Content-Type: application/json
{
"email": "[email protected]",
"roles": "viewer"
}
Das gab ebenfalls 200 OK zurück.
Für die lokale Laborvalidierung ohne E-Mail-Zustellung bestätigte ich direkt in der SQLite-Meta-Datenbank, dass:
nc_users_v2 den eingeladenen Benutzer mit einem nicht-null invite_token enthieltnc_base_users_v2 eine echte Mitgliedschaftszeile für die Ziel-Base enthieltinvited_by war NULLDann löste ich die Einladung über den normalen Anmeldevorgang ein:
POST /api/v2/auth/user/signup
Content-Type: application/json
{
"email": "[email protected]",
"password": "Password123.",
"token": "<invite_token>"
}
Mit dem zurückgegebenen xc-auth rief ich auf:
GET /api/v2/meta/bases/<baseId>/tables
Das gab 200 OK zurück.
Schließlich deaktivierte ich als Besitzer den Shared-Base-Link:
DELETE /api/v2/meta/bases/<baseId>/shared
Danach:
xc-shared-base-id schlug fehl mit 401xc-auth hatte immer noch Erfolg mit 200200200200200200401200Das stellte den zentralen Sicherheitsanspruch fest:
Eine einzige erfolgreiche Shared-Base-Einladung hätte bereits ausgereicht, um einen Autorisierungsfehler zu zeigen.
Aber die vollständige Validierungskette war aus zwei Gründen wichtig.
Es zeigte, dass dies nicht nur eine Endpunkt-Exposition war.
Die öffentliche Freigabesitzung erreichte nicht nur eine eingeschränkte API. Sie vollendete die vollständige Privilegien-Konvertierungskette:
Es bewies, dass dies nicht selbstwiderrufend war.
Die ernstere Auswirkung trat nach der Deaktivierung des Freigabelinks ein:
Das ist es, was temporären Linkzugriff in dauerhafte Zugriffspersistenz verwandelte.
Diese Schwachstelle erlaubt jedem mit einem Shared-Base-Link, Folgendes zu tun:
Die primäre Auswirkung ist die Vertraulichkeit, da ein Angreifer dauerhaften Lesezugriff auf Shared-Base-Daten über ein gewöhnliches authentifiziertes Konto aufrechterhalten kann.
Es gibt auch eine Integritätsauswirkung, da ein öffentlicher Freigabe-Prinzipal den Zugriffskontrollzustand ändern kann, indem er neue Mitglieder zur Base hinzufügt.
Das ist ein schwerwiegenderes Ergebnis als gewöhnlicher Datenverlust. Es ist ein Bruch der Privilegiengrenze zwischen anonymem Teilen und authentifizierter Mitgliedschaft.
Dieses Problem wird vernünftigerweise als bereichsübergreifender Autorisierungsfehler mit Vertraulichkeitsauswirkung klassifiziert.
CVSS:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
Dieser Vektor passt zum Kernverhalten hier:
Die Richtung der Behebung ist geradlinig.
Shared-Base-Sitzungen sollten keine Member-Management-Fähigkeiten erben.
Mindestens:
baseUserList und userInvite aus allen Berechtigungen entfernen, die über xc-shared-base-id erreichbar sindGET und POST /api/v2/meta/bases/:baseId/users aufrufen könnenDieses Problem wurde lokal gegen NocoDB 0.301.3 auf Commit dac49b0122c5ee655fb8f46a1b6e42dfeec1f3ad validiert.
Der Bericht demonstrierte:
xc-shared-base-id in normale Base-RollenDas Problem wurde zugewiesen:
CVE-2026-46552
Die Kernlektion ist einfach:
Shared-Link-Zugriff ist nicht dasselbe wie vertrauenswürdige Mitgliedschaft.
Viele Systeme geraten in Schwierigkeiten, wenn sie diese beiden Ideen in dasselbe Rollenmodell zusammenfassen.
Ein geteilter Link mag betrieblich ähnlich wie ein Viewer-Konto aussehen, aber die Vertrauensannahmen sind unterschiedlich:
Wenn dieser Prinzipal mit geringerer Sicherheit Management-Aktionen durchführen oder neue dauerhafte Identitäten erzeugen kann, ist die Freigabegrenze bereits gebrochen.
Das ist die eigentliche Lehre.
Diese Schwachstelle handelte nicht davon, die Authentifizierung vollständig zu umgehen.
Es ging darum, zwei Vertrauensebenen zusammenzuführen, die getrennt hätten bleiben sollen.
In NocoDB sollte ein Shared-Base-Link temporären, widerrufbaren Zugriff auf gemeinsam genutzte Inhalte bieten. Stattdessen konnte er verwendet werden, um Mitglieder aufzulisten, einen echten Benutzer in die Base einzuladen und öffentlichen Freigabezugriff in dauerhafte authentifizierte Mitgliedschaft umzuwandeln, die den Widerruf der Freigabe überlebte.
Deshalb wurde dies zu CVE-2026-46552.