Teable: Beliebiges Dateischreiben als root über den `hash`-Parameter der Attachment-Presign-API
Ein selbst registriertes Konto schreibt über den hash-Parameter der Attachment-Presign-API beliebige Dateien als root in den Container.
Advisory-ID: TP-2026-078
Produkt: Teable (No-Code-Datenbank und Tabellenanwendung)
Schwachstellentyp: Pfad-Traversal / beliebiges Dateischreiben (CWE-22, CWE-20)
CVE: CVE-2026-104100
CVSS 3.1: 8.8 (Hoch) · CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Betroffene Versionen: <= 1.10.0
Hersteller-Advisory: GHSA-h4hg-45pv-pv8j
Behoben in: release.2026-07-20T11-53-25Z.2296
Gemeldet: 16. Juli 2026
Zusammenfassung
Teable ist eine No-Code-Datenbank mit Tabellenoberfläche. Die Presign-API für Dateianhänge übernahm ein vom Client geliefertes Feld hash ungeprüft als Dateinamen auf der Platte, und der schreibende Pfad besaß keine Verzeichnissperre. Ein selbst registrierter Nutzer, in der Standardkonfiguration genügt die offene Registrierung, konnte damit ../-Sequenzen einschleusen und beliebige Dateien im Container anlegen oder überschreiben. Da das Backend als uid 0 läuft, erfolgt das Schreiben als root, womit sich der Schritt zur Codeausführung über überschriebene Startdateien ergibt. turingpoint hat den Ablauf live verifiziert und verantwortungsvoll gemeldet.
Ursache
Das Presign-Schema deklariert hash als freies z.string().optional() ohne Format- oder Zeichenprüfung (packages/openapi/src/attachment/signature.ts:32). LocalStorage.presigned übernimmt diesen Wert unverändert als Dateinamen, filename = hash ?? token, und setzt ihn per join(dir, filename) zum Zielpfad zusammen (apps/nestjs-backend/src/features/attachments/plugins/local.ts:93,105). Der eigentliche Schreibvorgang in LocalStorage.save löst den Pfad mit resolve(distPath, rename) auf und kopiert die hochgeladene Datei per fse.copy dorthin, ohne das Ergebnis gegen das Storage-Verzeichnis zu prüfen (local.ts:199-207). Die passende Prüffunktion assertPathWithinStorage existiert im selben Modul, ist aber ausschließlich an den lesenden Pfad gebunden (local.helper.ts:6, aufgerufen in apps/nestjs-backend/src/features/attachments/attachments.service.ts:82,109) und läuft vor keinem Schreibzugriff. Weil die Selbstregistrierung und der lokale Storage-Provider Standard sind und der Backend-Prozess als uid 0 läuft, reicht ein frisch angelegtes Konto, um als root außerhalb des Upload-Verzeichnisses zu schreiben.
Proof of Concept
POST /api/attachment/signature
Cookie: <Session eines selbst registrierten Kontos>
{"type": 1, "contentType": "text/plain", "hash": "../../../../tmp/pwn"}
-> Antwort enthaelt die Upload-URL mit Token
PUT /api/attachment/upload/<token>
<Inhalt>
-> Datei wird als /tmp/pwn mit Eigentuemer root:root geschrieben
Der Server nimmt den Traversal-Namen als Dateinamen an, und weil der Schreibpfad keine Verzeichnissperre durchläuft, landet der Inhalt außerhalb des Upload-Verzeichnisses. Vorhandene Dateien werden dabei überschrieben.
Auswirkung
- Schreiben und Überschreiben beliebiger Dateien im gesamten Container-Dateisystem mit root-Rechten.
- Codeausführung über überschriebene Start-, Cron- oder Anwendungsdateien.
- Manipulation der Anwendungskonfiguration und damit Zugriff auf sämtliche Basen und Tabellen der Instanz.
- Ausfall des Dienstes durch zerstörte Laufzeit- oder Systemdateien.
Referenzen
Steckt so etwas in Ihrer Software?
Diese Schwachstelle hat unser Team im Rahmen seiner Arbeit gefunden. Lassen Sie Ihre Anwendungen von denselben Spezialisten prüfen, mit einem Penetrationstest von turingpoint.
