Skip to main content

Supabase-Fehlkonfiguration auf oct7.de

October 12, 2025 · Petition / Zivilgesellschaft · Web Application · 3 min read

Überblick

Ich war auf oct7.de unterwegs und hab über die Firefox DevTools festgestellt, dass der Supabase Anon-Key viel zu viele Berechtigungen hatte. Der Key ist öffentlich und das ist auch so gedacht, aber er sollte nur auf öffentliche Tabellen zugreifen können. Hier konnte er deutlich mehr. Heißt: Nutzerdaten wie Namen, Adressen und E-Mails waren einfach so auslesbar.

Hintergrund

Ich hab mich für die Petition angemeldet, ganz normale Seite erstmal. Aber wer mich kennt weiß: DevTools gehen immer auf. Also hab ich geschaut was der Client so macht.

Cookies, Local Storage, Bearer-Tokens, das übliche. Dabei bin ich auf den Supabase-Key gestoßen. Erstmal hab ich mir nichts dabei gedacht, bei den meisten Websites gibt es einen Anon-Key der clientseitig sichtbar ist und nur auf öffentliche Tabellen zugreifen kann.

Diesmal war es anders. Über den /rest/v1/-Endpoint, den Supabase automatisch bereitstellt, konnte ich die verfügbare API abfragen:

curl 'https://<project-ref>.supabase.co/rest/v1/' \
  -H 'apikey: <anon-key>' \
  -H 'Authorization: Bearer <anon-key>'

Zurück kam ein kompletter OpenAPI-Dump mit allen Tabellen und Endpoints. Das hätte so nicht sein sollen.

Den Spuren folgen

Ab da ging es hauptsächlich um Enumeration. Was kann der Key? Wie weit reichen die Berechtigungen? Gibt es Einschränkungen?

Kurzfassung: Der Key hatte volle Leserechte auf alle Tabellen die nicht direkt an die Supabase-Auth gekoppelt waren.

# Signaturen mit vollständigen Nutzerdaten abrufen
curl 'https://<project-ref>.supabase.co/rest/v1/signatures?select=*' \
  -H 'apikey: <anon-key>' \
  -H 'Authorization: Bearer <anon-key>'
[
	{
		"id": 1,
		"full_name": "Max Mustermann",
		"email": "[email protected]",
		"address": "Musterstraße 12, 10115 Berlin",
		"created_at": "2025-10-01T14:23:00Z"
	},
	{
		"id": 2,
		"full_name": "Erika Musterfrau",
		"email": "[email protected]",
		"address": "Beispielweg 5, 80331 München",
		"created_at": "2025-10-02T09:15:00Z"
	}
]

Erreichbare Tabellen waren unter anderem:

  • signatures mit vollständigen Nutzerdaten (Name, Adresse, E-Mail)
  • public_signatures mit weniger detaillierten Nutzerdaten
  • admin_login_attempts mit Login-Versuchen der Admins
  • donations als Spendentabelle (vermutlich auch lesbar)

Supabase gibt bei nicht existierenden Tabellen, fehlenden Berechtigungen oder leeren Tabellen immer ein leeres Array [] zurück. Ob donations also wirklich Daten hatte kann ich nicht 100% sagen. Aber wenn ich Admin-Login-Versuche lesen konnte, geh ich stark davon aus dass der Rest genauso offen war.

# Selbst Admin-Login-Versuche waren auslesbar
curl 'https://<project-ref>.supabase.co/rest/v1/admin_login_attempts?select=*&limit=5' \
  -H 'apikey: <anon-key>' \
  -H 'Authorization: Bearer <anon-key>'

Das eigentliche Problem

Eigentlich total simpel und ein Fehler den viele Entwickler irgendwann mal machen: Ein Key der sehr restriktiv sein sollte wurde zu locker konfiguriert und hatte mehr Zugriff als nötig.

Konkret fehlten Row Level Security (RLS) Policies auf den betroffenen Tabellen. Supabase setzt RLS nicht automatisch durch. Wenn man es nicht explizit aktiviert hat der Anon-Key Zugriff auf alles:

-- So hätte es konfiguriert sein sollen:
ALTER TABLE signatures ENABLE ROW LEVEL SECURITY;

-- Policy: Nur authentifizierte Nutzer sehen ihre eigenen Daten
CREATE POLICY "Nutzer sehen nur eigene Signaturen"
  ON signatures FOR SELECT
  USING (auth.uid() = user_id);

Ohne diese Policies kann jeder mit dem Anon-Key einfach SELECT * FROM signatures machen. Genau das ist hier passiert.

Auswirkungen

Ich konnte meine eigenen Signaturdaten abrufen und genauso eine große Menge an Signaturen anderer Nutzer. Offengelegt wurden:

  • Vollständiger Name
  • Adresse
  • E-Mail-Adresse

Muss man nicht groß erklären warum das ein Problem ist.

Eindämmung und Behebung

Ich hab mich direkt an die Admins gewandt und ihnen einen simplen cURL-Request als Proof of Concept geschickt, damit sie das Problem selbst sehen konnten:

# Der PoC für die Admins
curl -s 'https://<project-ref>.supabase.co/rest/v1/signatures?select=id,full_name,email&limit=3' \
  -H 'apikey: <anon-key>' \
  -H 'Authorization: Bearer <anon-key>' | python3 -m json.tool

Die haben dann mit ihrem Sysadmin geredet und die Seite runtergenommen bis alles gefixt war. Danach hab ich nochmal gegengeprüft und bestätigt dass die Tabellen nur noch leere Arrays zurückgeben. Problem gelöst.

Lessons Learned

  • Principle of Least Privilege: Keys kriegen immer nur die Berechtigungen die sie wirklich brauchen. Nicht mehr.
  • RLS ist Pflicht, nicht optional: Supabase macht es einfach eine Datenbank aufzusetzen. Aber einfach heißt nicht sicher. Ohne RLS ist der Anon-Key ein offenes Scheunentor.
  • Anon-Key ≠ geheim: Der Key ist per Design im Client sichtbar. Sicherheit passiert auf Datenbankebene über RLS-Policies, nicht durchs Verstecken vom Key.
  • DevTools nach dem Deploy checken: Ein kurzer Blick in die DevTools kann sowas sofort aufdecken bevor es jemand anderes tut.

Schlusswort

Danke fürs Lesen. Ich hoffe der Einblick hilft anderen Devs ihre Systeme besser abzusichern. Supabase ist ein geiles Tool, aber man muss halt verstehen was unter der Haube passiert.