Aktive Inhalte auf Websites – z. B. Ja­va­Script, CSS, ActiveX – stellen ein Si­cher­heits­ri­si­ko für In­ter­net­nut­zer und Betreiber von Websites dar. Denn sie können durch so­ge­nann­tes Cross-Site-Scripting ma­ni­pu­liert werden. Damit In­ter­net­sei­ten trotzdem ohne Bedenken in vollem Umfang genutzt werden können, hat man eine Content-Security-Policy (CSP) ein­ge­führt. Der Si­cher­heits­stan­dard soll gegen schäd­li­che Angriffe schützen und wird in­zwi­schen von den meisten Web­brow­sern un­ter­stützt. Das Si­cher­heits­kon­zept schützt sowohl Websites als auch In­ter­net­nut­zer. Aber was steckt dahinter und wie funk­tio­niert CSP?

SSL-Zer­ti­fi­kat kaufen
Sichern Sie sich Ihr SSL-Zer­ti­fi­kat
  • Ver­schlüs­selt die Website-Kom­mu­ni­ka­ti­on
  • Ver­hin­dert Si­cher­heits­war­nun­gen
  • Ver­bes­sert die Google-Plat­zie­rung

Ent­wick­lung der Content-Security-Policy

Die Content-Security-Policy hat ihre Ursprünge im Jahr 2004 – damals noch unter dem Namen „Content-Rest­ric­tion“. Grund für die Be­mü­hun­gen waren zu­neh­men­de Si­cher­heits­lü­cken bei In­ter­net­skrip­ten. Besonders das Cross-Site-Scripting (XSS), eine kri­mi­nel­le Methode, um Schadcode in eine Website ein­zu­schleu­sen, stellt ein großes Risiko für Anwender dar. Dabei rufen die Nutzer zwar eine ver­trau­ens­wür­di­ge Website auf, dort läuft al­ler­dings ein Skript, das schäd­li­che Daten aus einer fremden Quelle lädt. Die Cy­ber­kri­mi­nel­len nutzen dazu z. B. Si­cher­heits­lü­cken in Kom­men­tar­funk­tio­nen der Website. So können sie Zugang zu per­sön­li­chen Computern erlangen, ohne dass sich die In­ter­net­nut­zer dessen überhaupt bewusst sind. Die Webmaster bemerken meist ebenso wenig, dass der fremde Code ein­ge­schleust wurde.

Um dieses Problem zu beheben, hat die Mozilla Foun­da­ti­on die Ent­wick­lung der CSP vor­an­ge­trie­ben. Der Vorteil hinter dem Si­cher­heits­stan­dard ist, dass im Browser Regeln auf­ge­stellt werden können, welche Skripte die Software laden darf und welche nicht. Dazu setzt die Content-Security-Policy auf HTTP-Header.

Fakt

Die Mozilla Foun­da­ti­on ist die Or­ga­ni­sa­ti­on hinter der Ent­wick­lung des Firefox-Browsers. Die Non-Profit-Or­ga­ni­sa­ti­on kümmert sich um die Aus­rich­tung der Projekte von Mozilla und um In­no­va­tio­nen rund um das Internet. Gegründet wurde die Foun­da­ti­on von ehe­ma­li­gen Mit­ar­bei­tern von Netscape, die einen der ersten Web­brow­ser ent­wi­ckelt hatten.

Wie funk­tio­niert die Content-Security-Policy?

Bei der Kom­mu­ni­ka­ti­on im Internet tauschen Client und Server Daten über das Hypertext Transfer Protocol (HTTP) aus. Ein wichtiger Be­stand­teil der Requests und Responses sind HTTP-Header-Felder: In diesen werden Parameter und Argumente über­mit­telt, die für den Austausch der beiden Ge­sprächs­teil­neh­mer (Server und Client) wichtig sind. Sie werden grund­sätz­lich in Anfrage- und Ant­wort­fel­der auf­ge­teilt und können z. B. In­for­ma­tio­nen über Zei­chen­satz, Sprache und Cookies be­inhal­ten. CSP wird als Antwort-Head­er­feld rea­li­siert. Das bedeutet, dass der Server die In­for­ma­tio­nen liefert und der Browser diese ver­ar­bei­tet. Der Content-Security-Policy-Header wird vom Webmaster erstellt und auf jeder Un­ter­sei­te der Website eingefügt, auf der der Si­cher­heits­stan­dard gelten soll. Als Betreiber der Website haben Sie so die Mög­lich­keit, un­ter­schied­li­che Si­cher­heits­vor­keh­run­gen für jede einzelne Seite fest­zu­le­gen. Un­kom­pli­zier­ter rea­li­sie­ren Sie das Si­cher­heits­kon­zept, indem Sie .htaccess-Dateien erstellen, die in den gleichen (oder hier­ar­chisch höheren) Ordnern wie die ent­spre­chen­den Webpages liegen, oder indem Sie CSP direkt in die Server-Kon­fi­gu­ra­ti­on verankern.

Hinweis

Wenn Sie als In­ter­net­nut­zer über­prü­fen möchten, ob Ihr Browser eine Content-Security-Policy un­ter­stützt, können Sie den CSP-Browser-Test aufrufen. Dieser versucht Skripts und Bilder aus fremden (un­schäd­li­chen) Quellen zu laden und zeigt Ihnen, ob dies er­folg­reich war. Ihr Browser ist dann sicher, wenn er die fremden Quellen nicht lädt, also die CSP versteht und anwendet.

Im Sinne einer Content-Security-Policy und um Cross-Site-Scripting zu ver­hin­dern, sollten Webmaster sämtliche Skripte in ge­son­der­te Dateien auslagern, statt sie direkt im Quellcode der Homepage ein­zu­bet­ten. Die CSP funk­tio­niert dann nach dem Prinzip einer Whitelist: Im Header werden die Quellen genannt, aus denen Skripte und Daten geladen werden dürfen. Sollte ein fremdes Skript unerkannt in den HTML-Code der Seite ein­ge­schleust worden sein und nun versuchen, externe Daten zu laden, muss der Browser des Nutzers dieses verbieten. Stan­dard­mä­ßig blockiert eine CSP alle Skripte, die sich direkt im Code befinden (Inline-Skripte). So werden sowohl die Website als auch der In­ter­net­nut­zer – und vor allem dessen sensible Daten – geschützt.

Ma­ni­pu­la­tio­nen durch Cross-Site-Scripting sind für Cy­ber­kri­mi­nel­le relativ leicht durch­zu­füh­ren. Fast jede Seite im World Wide Web besitzt ein Ein­ga­be­feld: z. B. Kom­men­tar­funk­ti­on, Such­leis­te oder Log-in-Feld. Statt einfachem Text können dort auch Skripte eingefügt werden. Wenn der Server nicht ent­spre­chend ab­ge­si­chert ist, im­ple­men­tie­ren Kri­mi­nel­le auf diesem Weg Phishing-In­ter­faces, bringen die gesamte Website zum Erliegen oder erlangen durch Schad­soft­ware die Kontrolle über den Web­brow­ser des Nutzers. CSP (oder richtiger: das ent­spre­chen­de Head­er­feld) teilt dem Web­brow­ser mit, aus welchen Quellen er Daten laden darf. Ist die Policy im Code der Website im­ple­men­tiert, wird der Versuch, über XSS ein­ge­schleus­ten Code abzurufen, mit einer Feh­ler­mel­dung be­ant­wor­tet.

Über die Content-Security-Policy können Webmaster aber auch viele weitere Ein­stel­lun­gen vornehmen, bei­spiel­wei­se durch diese Di­rek­ti­ven:

  • base-uri: Be­schränkt die URLs, die im <base>-Element der Webpage auf­tau­chen dürfen.
  • child-src: Legt fest, aus welchen Quellen Daten in Frames auf­tau­chen dürfen, z. B. bei ein­ge­bet­te­ten Videos von Dritt­an­bie­tern.
  • connect-src: Be­schränkt die Quellen, mit denen sich die Seite verbinden kann, z. B. über Links.
  • font-src: Bestimmt die Quellen, aus denen Schrift­ar­ten geladen werden dürfen.
  • form-action: Stellt eine Liste von gültigen End­punk­ten in For­mu­la­ren bereit.
  • frame-ancestors: Legt fest, welche Domains die Seite in Frames und iFrames einbauen dürfen.
  • img-src: Be­schränkt die Quellen, aus denen Bilder geladen werden dürfen.
  • media-src: Legt fest, aus welchen Quellen Audio- und Video-Formate geladen werden dürfen.
  • object-src: Definiert die Kontrolle über Flash und andere Plug-ins.
  • plugin-types: Limitiert die Arten von Plug-ins.
  • report-uri: Spe­zi­fi­ziert eine URL, an die Berichte geschickt werden, wenn gegen die Si­cher­heits­maß­nah­men verstoßen wurde.
  • script-src: Bestimmt, welche Quellen für Ja­va­Script erlaubt sind.
  • style-src: Funk­tio­niert wie script-src, wird al­ler­dings bei Style­sheets an­ge­wen­det.
  • upgrade-insecure-requests: Legt fest, dass unsichere Seiten mit HTTP wie HTTPS-Seiten behandelt werden.
  • sandbox: Ver­schiebt die be­tref­fen­de Seite in eine Sandbox, in der u. a. Formulare, Pop-ups und Skripte verboten sind.

Diese Di­rek­ti­ven gelten nur, wenn sie aus­drück­lich gesetzt sind. Ansonsten stehen sie stan­dard­mä­ßig offen und stellen somit eine Si­cher­heits­lü­cke dar. Mit der default-src lässt sich dies al­ler­dings ändern: Hier können Sie den stan­dard­mä­ßi­gen Zustand aller Di­rek­ti­ven festlegen, die mit -src enden. Statt diese offen zu lassen, stellen Sie z. B. ein, dass nur Daten aus Ihrer eigenen Website geladen werden dürfen, es sei denn, Sie haben es im HTTP-Header einer einzelnen Webpage anders fest­ge­legt. In ge­son­der­ten Di­rek­ti­ven fügen Sie dann noch weitere Quellen hinzu.

In das Header-Feld können Sie beliebig viele Di­rek­ti­ven eintragen. Möchten Sie mehrere Di­rek­ti­ven aufnehmen, trennen Sie diese durch Se­mi­ko­lons. Außerdem müssen Sie als Webmaster alle Quellen innerhalb einer Direktive angeben. Mehr­ma­li­ge Nennungen von gleichen Di­rek­ti­ven mit zu­sätz­li­chen Quellen wie im folgenden Beispiel sind nicht zulässig:

script-src beispiel1.local; script-src beispiel2.local

In diesem Fall ist nur die erste Quelle relevant, die zweite würde vom Client ignoriert. Statt­des­sen müssen Sie beide Quellen in einer Direktive notieren:

script-src beispiel1.local beispiel2.local

Sollten Sie für eine Page oder die komplette Website bestimmte In­halts­ty­pen gar nicht brauchen, können Sie in die ent­spre­chen­den Di­rek­ti­ven den Wert 'none' in den Header eintragen – so legen Sie fest, dass gar keine Quellen geladen werden dürfen. Sie können auch den Wert 'self' verwenden – damit bestimmen Sie, dass der Browser nur Inhalte aus der gleichen Quelle nachladen darf. Beide Werte müssen Sie immer in einfachen An­füh­rungs­zei­chen notieren, ansonsten werden none und self als Domains in­ter­pre­tiert. Um eine Content-Security-Policy zu de­fi­nie­ren, gibt es un­ter­schied­li­che Header-Mög­lich­kei­ten:

  • Content-Security-Policy
  • X-Webkit-CSP
  • X-Content-Security-Policy

Nicht alle Browser un­ter­stüt­zen auch jede Benennung. Das W3C (das Gremium, um Standards im Web fest­zu­le­gen) schlägt al­ler­dings Content-Security-Policy vor. Deshalb haben sich in­zwi­schen alle modernen Browser diesem Si­cher­heits­stan­dard angepasst (die anderen beiden Versionen gelten als veraltet). Um si­cher­zu­ge­hen, dass Sie einen möglichst großen Teil von In­ter­net­nut­zern (auch die­je­ni­gen mit ver­al­te­ten Browser-Versionen) mit Ihrer CSP erreichen, ist es durchaus ratsam, alle Head­er­fel­der ein­zu­bau­en. Kann ein ent­spre­chen­der Web­brow­ser nichts mit dem Content-Security-Policy-Header anfangen, wird er diesen einfach igno­rie­ren und die Website ohne Probleme dar­stel­len – der zu­sätz­li­che Schutz ist für die be­tref­fen­den Nutzer dann al­ler­dings nicht gegeben. Für ge­wöhn­lich werden Sie HTTP-Header sei­ten­über­grei­fend für Ihre gesamte Domain setzen. Für Un­ter­ver­zeich­nis­se können Sie die .htaccess-Datei verwenden. Mithilfe des CSP-Si­cher­heits­stan­dards legen Sie dann Son­der­re­geln für einzelne Un­ter­sei­ten fest. Wenn Sie bei­spiels­wei­se auf einer Seite einen Social-Media-Button im­ple­men­tiert haben, auf der nächsten aber nicht, ist es sinnvoll, auch nur auf der ersten Seite den Zugang zur fremden Quelle zu erlauben. Quellen lassen sich als Adressen, in ihrer Art oder auch als Wildcards eingeben. Folgende Eingaben sind also zulässig:

  • script-src https://example.com:443 – Skripte sind nur von dieser Domain per HTTPS zulässig.
  • script-src 'none' – Skripte dürfen nicht geladen werden.
  • script-src 'self' – Skripte dürfen aus demselben Ursprung wie die aktuelle Seite geladen werden, nicht aber von Sub­do­mains.
  • script-src https: – Skripte dürfen von jeglicher Domain geladen werden, solange sie mit HTTPS beginnt.
  • script-src example.com – Skripte dürfen von dieser Domain geladen werden.
  • script-src *.example.com – Skripte von dieser Domain und von allen Sub­do­mains sind zulässig.
  • img-src data: – Bilder dürfen über Data-URLs geladen werden.

Eine Content-Security-Policy legt grund­le­gend fest, dass Skripte nur aus Dateien geladen werden dürfen, nicht direkt aus dem Code der Website. Möchten Sie dies umgehen, können Sie den Befehl script-src 'unsafe-inline' verwenden. Es sollte Ihnen aber bewusst sein, dass Sie damit wiederum eine Si­cher­heits­lü­cke schaffen. Der Si­cher­heits­stan­dard verbietet überdies die Funktion eval (). Ei­gent­lich kann man mit diesem Befehl Text in Ja­va­Script-Code umwandeln – doch auch das stellt ein Si­cher­heits­ri­si­ko dar. Wer diese Funktion dennoch braucht, kann sie mit script-src 'unsafe-eval' wieder ak­ti­vie­ren.

Tipp

Über einen Umweg können Sie unsafe-inline doch sichern. Durch Hash-Werte oder Nonce-Source schließen Sie diese Si­cher­heits­lü­cke wei­test­ge­hend.

Wenn Skripte nicht mehr im Code direkt auf­tau­chen dürfen, müssen Sie für jedes Skript eine eigene Datei anlegen. Die Funktion des Skripts wird in eine .js-Datei aus­ge­la­gert. Im Code der Website wird nur noch auf diese verwiesen:

<script src='beispiel.js'></script>

Was das Skript schließ­lich macht, steht in der beispiel.js. Auch Style-Elemente müssen Sie in ge­son­der­te Style­sheets auslagern. Wenn Sie als Webmaster also eine Internet-Security-Policy einführen möchten, reicht es nicht, den Header ein­zu­fü­gen. Sie müssen auch den Quellcode Ihrer Website über­prü­fen und anpassen.

Hinweis

Sie möchten wissen, wie sicher Ihre eigene Website ist? Mozilla stellt einen einfach zu nutzenden Test bereit: Ob­ser­va­to­ry by Mozilla vergibt nach Abschluss eines Scans eine Note und teilt Ihnen mit, an welchen Punkten Sie Ihre Website sicherer machen sollten.

Content-Security-Policy: Ein Beispiel

An einem Beispiel zeigen wir nun, wie Sie einen Content-Security-Policy-Header rea­li­sie­ren können und erklären, was mit dem Header erreicht wird.

  • Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri "https://example.org/report.html";
  • X-Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri "https://example.org/report.html";
  • X-WebKit-CSP: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri https://example.org;

Sie sehen, dass jede CSP-Variante im Header auftaucht, damit sich möglichst viele Browser an­spre­chen lassen. Innerhalb der je­wei­li­gen Header-Namen ist der Inhalt identisch: Quellen werden nach­ein­an­der auf­ge­führt und die Di­rek­ti­ven sind mit einem Semikolon von­ein­an­der getrennt. Die Syntax ist also immer die gleiche. Tat­säch­lich ändert sich nur der Name des Felds, weshalb Sie den Inhalt auch einfach du­pli­zie­ren können.

Zunächst legen wir fest, dass – sollte es nicht anders in einer Direktive hin­ter­legt sein – Daten aus keiner Quelle geladen werden sollen (default-src). Damit schließen wir eine Si­cher­heits­lü­cke. Sie sollten default-src immer als erstes de­fi­nie­ren. So ver­hin­dern Sie, dass durch eine eventuell ver­ges­se­ne Direktive eine Lücke in Ihrer Content-Security-Policy verbleibt.

Hinweis

Wenn trotz der Content-Security-Policy Inhalte inkorrekt in die eigene Webseite ein­ge­bun­den werden, zeigt bei­spiels­wei­se der Mozilla-Firefox folgende Feh­ler­mel­dung dem Besucher an:

Blockiert von der In­halt­si­cher­heits­richt­li­nie (CSP)

Diese Webseite hat eine In­halt­si­cher­heits­richt­li­nie (Content Security Policy), die ver­hin­dert, dass die Webseite auf diese Weise ein­ge­bun­den wird.

Firefox hat diese Webseite daran gehindert, auf diese Weise geladen zu werden, weil die Webseite eine In­halt­si­cher­heits­richt­li­nie (Content Security Policy) hat, die dies nicht erlaubt.

Als nächstes de­fi­nie­ren wir die Quelle, aus denen Skripte geladen werden dürfen (script-src). Im Beispiel legen wir fest, dass der Browser nur Skripte von der gleichen Quelle und von example.com inklusive aller Sub­do­mains lädt (die Wildcard vergeben Sie durch *.). Des Weiteren bestimmen wir, dass Clients auch Style­sheets nur aus der eigenen Quelle laden dürfen (style-src). Auch Bilder sind nur aus der eigenen Quelle und als Data-URL erlaubt (img-src). Schrift­ar­ten dürfen gemäß unseres Content-Security-Policy-Headers nur noch vom eigenen Ursprung und aus dem Angebot von Google geladen werden. Schließ­lich geben wir im Beispiel noch einen Ort an, an den Meldungen geschickt werden, falls jemand versucht, gegen den Si­cher­heits­stan­dard zu verstoßen (report-uri).

Sie bemerken, dass wir bei weitem nicht alle Di­rek­ti­ven in den Header auf­ge­nom­men haben. Das ist auch gar kein Problem: Im an­ge­nom­me­nen Fall brauchen wir keine weiteren White­lists, und durch die default-src sind alle anderen Quellen aus­ge­schal­tet.

Tipp

Im Internet sind mehrere Content-Security-Policy-Ge­ne­ra­to­ren verfügbar. Mit Angeboten wie Report URI erstellen Sie CSP-Header-Felder leicht und zu­ver­läs­sig.

Zum Hauptmenü