SaaSFort
CSP Security-Header Trusted Types XSS OWASP Reifegradmodell

Ein CSP-Reifegradmodell: fünf Stufen, und wo die meisten SaaS stehenbleiben

Fast jedes SaaS hat eine Content-Security-Policy. Fast keines kommt über Stufe zwei hinaus. Hier ist die Leiter und was jede Sprosse tatsächlich bringt.

ST
SaaSFort Team
· 4 Min. Lesezeit

Content-Security-Policy ist der mächtigste Header, den ein Browser bietet, und zugleich derjenige, der am häufigsten in einer Form ausgerollt wird, die fast keinen Schutz liefert.

Der Grund: “hat eine CSP” ist im Fragebogen binär und in der Realität ein Kontinuum. Hier ist die Leiter, was jede Stufe verhindert, und wo der Abbruch passiert.

Stufe 0: keine CSP

Keine Richtlinie. Jedes eingeschleuste Skript wird ausgeführt.

Häufiger als vermutet auf authentifizierten Anwendungs-Subdomains, weil die Marketingseite die Sicherheitsprüfung bekam und app. nicht.

Stufe 1: eine CSP mit unsafe-inline

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'

Das ist die Stufe, die die meisten Deployments erreichen und auf der sie bleiben. Sie besteht eine Header-Vorhandensein-Prüfung und verhindert praktisch nichts, denn unsafe-inline erlaubt jedes Inline-Skript, und genau das erzeugt eine Injektion.

Enthält Ihre Richtlinie unsafe-inline in script-src, stehen Sie auf Stufe 1, gleich wie lang der Rest des Headers ist. Behandeln Sie dieses Schlüsselwort als das Wichtigste, das es zu finden und zu entfernen gilt.

Stufe 2: eine Positivliste ohne unsafe-inline

Content-Security-Policy: script-src 'self' https://cdn.example.com https://analytics.example.com

Echter Schutz gegen trivial eingeschleustes Inline-Skript. Zwei strukturelle Probleme.

Die Positivliste wächst. Jeder neue Dienstleister ergänzt eine Domain, und niemand entfernt eine, sodass sie in Richtung “halbes Internet erlaubt” driftet.

Positivlisten sind über ihre eigenen Einträge umgehbar. Ein erlaubtes CDN, das beliebige Nutzerinhalte hostet, oder eine erlaubte Domain mit einem JSONP-Endpunkt oder einem veralteten Framework mit bekanntem Gadget wird zum Ausführungspfad. Das ist gut dokumentiert und der Grund, warum Positivlisten nicht mehr empfohlen werden.

Stufe 3: Nonce plus strict-dynamic

Content-Security-Policy:
  script-src 'nonce-{zufall}' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none'; base-uri 'self'

Die derzeit empfohlene Form. Jede Antwort trägt einen frischen Nonce; nur Skripte mit diesem Nonce werden ausgeführt. strict-dynamic lässt diese vertrauenswürdigen Skripte eigene Abhängigkeiten laden, ohne dass eine Domainliste gepflegt werden muss, wodurch die Richtlinie aufhört zu wachsen.

Das abschließende https: und 'unsafe-inline' sind bewusste Rückfälle für ältere Browser, die strict-dynamic nicht kennen. Browser, die es kennen, ignorieren beide. Das wirkt in einem Review alarmierend und ist korrekt.

Die begleitenden Direktiven zählen auf dieser Stufe:

  • object-src 'none' entfernt Ausführungspfade über Plugins.
  • base-uri 'self' verhindert, dass eine <base>-Injektion sämtliche relativen URLs der Seite entführt.
  • frame-ancestors 'none' behandelt Clickjacking genauer als X-Frame-Options.

Stufe 3 zu erreichen erfordert einen Nonce in Ihrer Template-Schicht, was bei einer gewachsenen Anwendung echte Arbeit bedeutet. Es ist die lohnendste Sprosse dieser Leiter.

Stufe 4: Trusted Types

  require-trusted-types-for 'script';
  trusted-types sanitizer default;

Die Stufen 1 bis 3 steuern, woher Skripte kommen. Keine davon adressiert DOM-XSS, bei dem gar kein Skript geladen wird: Eine Zeichenkette, der die Anwendung bereits vertraut, wird an innerHTML oder ein Äquivalent übergeben und wird zu Code.

Trusted Types lässt diese Senken Zeichenketten verweigern. Der einzige Weg, dorthin zu schreiben, führt über eine benannte Richtlinie, die Sie deklariert haben, wodurch sich “sind alle vierhundert Zuweisungen sicher” in “sind diese drei Richtlinien korrekt” verwandelt.

Beide Direktiven zählen. require-trusted-types-for aktiviert die Durchsetzung; trusted-types legt die Menge erzeugbarer Richtlinien fest, sodass ein kompromittiertes Drittanbieter-Skript keine eigene erzeugen kann. Durchsetzung ohne Positivliste ist ein unvollständiges Deployment.

Der vollständige Rollout-Weg, inklusive Report-only.

Stufe 5: Berichte, und die Integritätsschicht daneben

Eine Richtlinie ohne Berichte ist eine Richtlinie, die Sie nicht pflegen können, denn Verstöße bleiben still und Sie erfahren von Ausfällen durch Nutzer.

  report-to csp-endpoint;
Reporting-Endpoints: csp-endpoint="https://example.com/_reports/csp"

Nutzen Sie report-to mit einem Reporting-Endpoints-Header. report-uri ist veraltet, wird aber weiterhin breit unterstützt, sodass es sinnvoll ist, während der Umstellung beide zu senden.

Auf dieser Stufe lohnt es auch, zu benennen, was CSP strukturell nicht kann: Sie schützt nicht vor serverseitigen Schwachstellen und nicht vor einer Lieferkettenkompromittierung einer Skriptquelle, die Sie bereits erlauben. Das Skript kommt von einer erlaubten Herkunft mit gültigem Nonce, und CSP hat keine Meinung zu seinem Inhalt. Diese Lücke deckt Subresource Integrity mit seinem Durchsetzungs-Header ab, keine CSP-Direktive.

Die Leiter auf einen Blick

StufeFormVerhindert
0Kein HeaderNichts
1unsafe-inline vorhandenPraktisch nichts
2PositivlisteNaive Injektion; über erlaubte Herkünfte umgehbar
3Nonce + strict-dynamicAusführung eingeschleuster Skripte
4+ Trusted TypesDOM-XSS an der Senke
5+ Berichte, + SRI-DurchsetzungDrift und Manipulation durch Dritte

Ihre Stufe mit einem Befehl bestimmen

curl -sI https://ihredomain.de | grep -i content-security-policy

Dann der Reihe nach: Steht unsafe-inline in script-src? Gibt es einen Nonce? Ist strict-dynamic vorhanden? Ist require-trusted-types-for vorhanden? Gibt es einen Berichtsendpunkt?

Prüfen Sie Ihre Anwendungs-Subdomain getrennt von der Marketingseite. Sie stehen häufig auf unterschiedlichen Stufen, und diejenige mit den Kundendaten ist oft die niedrigere.

Kurzfassung

Header-Vorhandensein ist kein Kontrollmechanismus. unsafe-inline in script-src setzt Sie auf Stufe 1, gleich was die Richtlinie sonst sagt.

Stufe 3 ist die lohnendste Sprosse. Stufe 4 adressiert eine ganze Angriffsklasse, die die ersten drei nicht berühren.

Artikel teilen
LinkedIn Post

Von der Theorie zur Praxis

Scannen Sie Ihre Domain kostenlos. Erste Ergebnisse in unter 10 Sekunden — ohne Registrierung.

Kostenlosen Scan starten

Weiterlesen