Das Sicherheitsmodell des Web basiert auf der Richtlinie für denselben Ursprung. Code von https://mybank.com
sollte nur auf die Daten von https://mybank.com
zugreifen dürfen. https://evil.example.com
sollte auf keinen Fall Zugriff erhalten.
Jede Quelle wird vom Rest des Webs isoliert, sodass Entwickler eine sichere Sandbox zum Entwickeln und Testen haben. Theoretisch ist das eine brillante Idee. In der Praxis haben Angreifer jedoch clevere Möglichkeiten gefunden, das System zu unterwandern.
Bei Cross-Site-Scripting-Angriffen (XSS) wird beispielsweise die Richtlinie zum gleichen Ursprung umgangen, indem eine Website dazu gebracht wird, schädlichen Code zusammen mit den beabsichtigten Inhalten zu senden. Das ist ein großes Problem, da Browser allen Code, der auf einer Seite angezeigt wird, als legitimen Teil des Sicherheitsursprungs dieser Seite vertrauen. Das XSS-Cheatsheet ist ein alter, aber repräsentativer Querschnitt der Methoden, mit denen Angreifer dieses Vertrauen durch Einschleusen von schädlichem Code missbrauchen können. Wenn ein Angreifer irgendeinen Code einschleust, ist es so gut wie vorbei: Nutzersitzungsdaten werden manipuliert und Informationen, die geheim gehalten werden sollten, werden an die Bösen gesendet. Das möchten wir natürlich nach Möglichkeit vermeiden.
In dieser Übersicht wird eine Abwehrmaßnahme hervorgehoben, mit der das Risiko und die Auswirkungen von XSS-Angriffen in modernen Browsern erheblich reduziert werden können: die Content Security Policy (CSP).
Kurzfassung
- Mithilfe von Zulassungslisten können Sie dem Client mitteilen, was zulässig ist und was nicht.
- Hier finden Sie Informationen zu den verfügbaren Richtlinien.
- Erkundigen Sie sich nach den Keywords, die sie akzeptieren.
- Inline-Code und
eval()
gelten als schädlich. - Melden Sie Richtlinienverstöße an Ihren Server, bevor Sie sie erzwingen.
Zulassungslisten für Quellen
Das Problem, das bei XSS-Angriffen ausgenutzt wird, besteht darin, dass der Browser nicht zwischen Script unterscheiden kann, das Teil Ihrer Anwendung ist, und Script, das von einem Dritten böswillig eingefügt wurde. Die Google +1-Schaltfläche unten auf dieser Seite lädt beispielsweise Code von https://apis.google.com/js/plusone.js
im Kontext der Quelle dieser Seite und führt ihn aus. Wir vertrauen diesem Code, aber wir können nicht erwarten, dass der Browser selbst herausfindet, dass Code von apis.google.com
großartig ist, während Code von apis.evil.example.com
wahrscheinlich nicht so gut ist. Der Browser lädt und führt jeden Code herunter, den eine Seite anfordert, unabhängig von der Quelle.
Anstatt alles, was ein Server bereitstellt, als vertrauenswürdig einzustufen, wird über die CSP der HTTP-Header Content-Security-Policy
definiert, mit dem Sie eine Zulassungsliste mit vertrauenswürdigen Inhalten erstellen können. So erhält der Browser die Anweisung, nur Ressourcen aus diesen Quellen auszuführen oder zu rendern. Selbst wenn ein Angreifer eine Lücke findet, über die er ein Script einschleusen kann, entspricht das Script nicht der Zulassungsliste und wird daher nicht ausgeführt.
Da wir davon ausgehen, dass apis.google.com
gültigen Code liefert, und wir uns selbst auch vertrauen, definieren wir eine Richtlinie, die die Ausführung von Scripts nur dann zulässt, wenn sie aus einer dieser beiden Quellen stammen:
Content-Security-Policy: script-src 'self' https://apis.google.com
Wie Sie wahrscheinlich schon vermutet haben, ist script-src
eine Anweisung, mit der eine Reihe von scriptbezogenen Berechtigungen für eine bestimmte Seite gesteuert wird. Wir haben 'self'
als eine gültige Scriptquelle und https://apis.google.com
als eine andere angegeben. Der Browser lädt JavaScript von apis.google.com
über HTTPS sowie vom Ursprung der aktuellen Seite herunter und führt es aus.
Wenn diese Richtlinie definiert ist, gibt der Browser einfach einen Fehler aus, anstatt das Script aus einer anderen Quelle zu laden. Wenn es einem cleveren Angreifer gelingt, Code in Ihre Website einzuschleusen, wird er statt des erwarteten Erfolgs mit einer Fehlermeldung konfrontiert.
Die Richtlinie gilt für eine Vielzahl von Ressourcen
Scriptressourcen sind zwar die offensichtlichsten Sicherheitsrisiken, aber CSP bietet eine Vielzahl von Richtlinien, mit denen die Ressourcen, die auf einer Seite geladen werden dürfen, ziemlich genau gesteuert werden können. Da Sie script-src
bereits kennen, sollte Ihnen das Konzept bereits klar sein.
Sehen wir uns kurz die restlichen Ressourcenrichtlinien an. Die folgende Liste zeigt den Status der Anweisungen auf Ebene 2. Eine Spezifikation für Level 3 wurde veröffentlicht, ist aber in den gängigen Browsern weitgehend nicht implementiert.
- Mit
base-uri
werden die URLs eingeschränkt, die im<base>
-Element einer Seite erscheinen können. - Unter
child-src
sind die URLs für Worker und eingebettete Frame-Inhalte aufgeführt. Beispiel: Mitchild-src https://youtube.com
können Videos von YouTube, aber nicht von anderen Quellen eingebettet werden. connect-src
schränkt die Ursprünge ein, zu denen Sie eine Verbindung herstellen können (über XHR, WebSockets und EventSource).- Mit
font-src
werden die Ursprünge angegeben, von denen Webschriften bereitgestellt werden können. Die Webschriften von Google können überfont-src https://themes.googleusercontent.com
aktiviert werden. - In
form-action
sind gültige Endpunkte für die Einreichung von<form>
-Tags aufgeführt. - Mit
frame-ancestors
werden die Quellen angegeben, in die die aktuelle Seite eingebettet werden kann. Diese Anweisung gilt für<frame>
-,<iframe>
-,<embed>
- und<applet>
-Tags. Diese Direktive kann nicht in<meta>
-Tags verwendet werden und gilt nur für nicht-HTML-Ressourcen. frame-src
wurde auf Ebene 2 eingestellt, aber auf Ebene 3 wiederhergestellt. Ist das nicht der Fall, wird wie bisher aufchild-src
zurückgegriffen.- Mit
img-src
werden die Ursprünge definiert, von denen Bilder geladen werden können. - Mit
media-src
werden die Ursprünge eingeschränkt, die für die Bereitstellung von Video und Audio zulässig sind. - Mit
object-src
können Sie Flash und andere Plug-ins steuern. - Mit
plugin-types
können Sie einschränken, welche Arten von Plug-ins auf einer Seite aufgerufen werden dürfen. - Mit
report-uri
wird eine URL angegeben, an die ein Browser Berichte sendet, wenn eine Richtlinie zur Inhaltssicherheit verletzt wird. Diese Direktive kann nicht in<meta>
-Tags verwendet werden. style-src
ist das Pendant vonscript-src
für Stylesheets.upgrade-insecure-requests
weist User-Agents an, URL-Schemas umzuschreiben und HTTP in HTTPS zu ändern. Diese Direktive gilt für Websites mit einer großen Anzahl alter URLs, die umgeschrieben werden müssen.worker-src
ist eine CSP-Richtlinie der 3. Ebene, die die URLs einschränkt, die als Worker, freigegebener Worker oder Dienst-Worker geladen werden können. Stand Juli 2017 gibt es nur wenige Implementierungen dieser Richtlinie.
Standardmäßig sind Richtlinien weit offen. Wenn Sie für eine Richtlinie, z. B. font-src
, keine bestimmte Richtlinie festlegen, verhält sich diese Richtlinie standardmäßig so, als hätten Sie *
als gültige Quelle angegeben. Sie können dann beispielsweise Schriftarten von überall und ohne Einschränkungen laden.
Sie können dieses Standardverhalten überschreiben, indem Sie eine default-src
-Richtlinie angeben. Mit dieser Anweisung werden die Standardwerte für die meisten Anweisungen definiert, die Sie nicht angeben. Generell gilt dies für alle Anweisungen, die auf -src
enden. Wenn default-src
auf https://example.com
festgelegt ist und Sie keine font-src
-Anweisung angeben, können Sie Schriftarten nur von https://example.com
laden. In unseren früheren Beispielen haben wir nur script-src
angegeben. Das bedeutet, dass Bilder, Schriftarten usw. von jeder Quelle geladen werden können.
Bei den folgenden Anweisungen wird default-src
nicht als Fallback verwendet. Denken Sie daran, dass das Nichtfestlegen von Regeln dem Zulassen von allem entspricht.
base-uri
form-action
frame-ancestors
plugin-types
report-uri
sandbox
Sie können so viele oder so wenige dieser Anweisungen verwenden, wie für Ihre spezifische Anwendung sinnvoll ist. Listen Sie sie einfach im HTTP-Header auf und trennen Sie die Anweisungen durch Semikolons. Geben Sie alle erforderlichen Ressourcen eines bestimmten Typs in einer einzelnen Richtlinie an. Wenn Sie beispielsweise script-src https://host1.com; script-src https://host2.com
eingeben, wird die zweite Anweisung einfach ignoriert. Mit einem Beispiel wie dem folgenden werden beide Ursprünge korrekt als gültig angegeben:
script-src https://host1.com https://host2.com
Wenn Sie beispielsweise eine Anwendung haben, die alle Ressourcen aus einem Content Delivery Network (z. B. https://cdn.example.net
) lädt, und wissen, dass Sie keine geframeten Inhalte oder Plug-ins benötigen, könnte Ihre Richtlinie so aussehen:
Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'
Implementierungsdetails
X-WebKit-CSP
- und X-Content-Security-Policy
-Header werden in verschiedenen Webanleitungen verwendet. Ignorieren Sie diese Header mit Präfix in Zukunft. Moderne Browser (mit Ausnahme von IE) unterstützen den Content-Security-Policy
-Header ohne Präfix. Diese Überschrift sollten Sie verwenden.
Unabhängig vom verwendeten Header wird die Richtlinie auf Seitenebene definiert: Sie müssen den HTTP-Header mit jeder Antwort senden, die geschützt werden soll. Das bietet eine große Flexibilität, da Sie die Richtlinie für bestimmte Seiten an ihre spezifischen Anforderungen anpassen können. Vielleicht gibt es auf einigen Seiten Ihrer Website eine Schaltfläche „+1“, auf anderen aber nicht. In diesem Fall können Sie festlegen, dass der Code für die Schaltfläche nur bei Bedarf geladen wird.
Die Quellenliste in jeder Richtlinie ist flexibel. Sie können Quellen nach Schema (data:
, https:
) oder nach Spezifität angeben, z. B. nur nach Hostnamen (example.com
, entspricht jedem Ursprung auf diesem Host: beliebiges Schema, beliebiger Port) oder nach einem vollständig qualifizierten URI (https://example.com:443
, entspricht nur HTTPS, nur example.com
und nur Port 443). Platzhalter sind zulässig, aber nur als Schema, Port oder an der äußersten linken Position des Hostnamens: *://*.example.com:*
würde mit allen Subdomains von example.com
(aber nicht mit example.com
selbst) über jedes Schema und jeden Port übereinstimmen.
Die Quellenliste akzeptiert auch vier Keywords:
'none'
stimmt, wie zu erwarten, mit nichts überein.'self'
stimmt mit dem aktuellen Ursprung überein, aber nicht mit seinen Subdomains.'unsafe-inline'
unterstützt Inline-JavaScript und Inline-CSS. (Wir gehen gleich noch genauer darauf ein.)'unsafe-eval'
erlaubt Text-zu-JavaScript-Mechanismen wieeval
. (Wir kommen auch darauf zurück.)
Diese Keywords müssen in einfache Anführungszeichen gesetzt werden. Mit script-src 'self'
(in Anführungszeichen) wird beispielsweise die Ausführung von JavaScript vom aktuellen Host autorisiert. script-src self
(ohne Anführungszeichen) erlaubt JavaScript von einem Server namens „self
“ (und nicht vom aktuellen Host), was wahrscheinlich nicht Ihre Absicht war.
Sandbox-Technologie
Es gibt noch eine weitere Direktive, die es wert ist, erwähnt zu werden: sandbox
. Sie unterscheidet sich ein wenig von den anderen, die wir uns angesehen haben, da sie Einschränkungen für Aktionen auf der Seite und nicht für Ressourcen auf der Seite vorsieht. Wenn die sandbox
-Anweisung vorhanden ist, wird die Seite so behandelt, als wäre sie in einem <iframe>
mit einem sandbox
-Attribut geladen worden. Das kann eine Vielzahl von Auswirkungen auf die Seite haben, z. B. die Erzwingung eines eindeutigen Ursprungs der Seite und die Verhinderung der Formulareinreichung. Dies geht etwas über den Rahmen dieses Artikels hinaus, aber vollständige Details zu gültigen Sandbox-Attributen finden Sie im Abschnitt „Sandboxing“ der HTML5-Spezifikation.
Das Meta-Tag
Der bevorzugte Bereitstellungsmechanismus der CSP ist ein HTTP-Header. Es kann jedoch hilfreich sein, eine Richtlinie für eine Seite direkt im Markup festzulegen. Verwenden Sie dazu ein <meta>
-Tag mit einem http-equiv
-Attribut:
<meta
http-equiv="Content-Security-Policy"
content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>
Diese Funktion kann nicht für frame-ancestors
, report-uri
oder sandbox
verwendet werden.
Inline-Code gilt als schädlich
CSP basiert auf Zulassungslisten, da dies eine eindeutige Möglichkeit ist, dem Browser anzuweisen, bestimmte Ressourcen als akzeptabel zu behandeln und den Rest abzulehnen. Herkunftsbasierte Zulassungslisten lösen jedoch nicht die größte Bedrohung durch XSS-Angriffe: Inline-Script-Injection.
Wenn ein Angreifer ein Script-Tag einschleusen kann, das direkt eine schädliche Nutzlast (<script>sendMyDataToEvilDotCom();</script>
) enthält, kann der Browser es nicht von einem legitimen Inline-Script-Tag unterscheiden. CSP löst dieses Problem, indem Inline-Script vollständig verboten wird. Das ist die einzige Möglichkeit, sicherzugehen.
Dieses Verbot gilt nicht nur für Scripts, die direkt in script
-Tags eingebettet sind, sondern auch für Inline-Ereignishandler und javascript:
-URLs. Sie müssen den Inhalt der script
-Tags in eine externe Datei verschieben und javascript:
-URLs und <a ... onclick="[JAVASCRIPT]">
durch entsprechende addEventListener()
-Aufrufe ersetzen. Sie könnten beispielsweise Folgendes umschreiben:
<script>
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>
in etwa so:
<!-- amazing.html -->
<script src="amazing.js"></script>
<button id="amazing">Am I amazing?</button>
<div style="clear:both;"></div>
// amazing.js
function doAmazingThings() {
alert('YOU AM AMAZING!');
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('amazing').addEventListener('click', doAmazingThings);
});
Der neu geschriebene Code bietet eine Reihe von Vorteilen, die über die gute Kompatibilität mit CSP hinausgehen. Er ist unabhängig von der Verwendung von CSP bereits eine Best Practice. Inline-JavaScript vermischt Struktur und Verhalten genau so, wie es nicht sein sollte. Externe Ressourcen sind für Browser leichter im Cache zu speichern, für Entwickler leichter verständlich und eignen sich gut für die Kompilierung und Minimierung. Sie schreiben besseren Code, wenn Sie den Code in externe Ressourcen verschieben.
Inline-Stile werden auf die gleiche Weise behandelt: Sowohl das style
-Attribut als auch style
-Tags sollten in externen Stylesheets zusammengefasst werden, um sich vor einer Vielzahl von erstaunlich ausgeklügelten Methoden zur Datenextraktion zu schützen, die durch CSS ermöglicht werden.
Wenn Sie Inline-Script und ‑Stil benötigen, können Sie sie aktivieren, indem Sie 'unsafe-inline'
als zulässige Quelle in einer script-src
- oder style-src
-Anweisung hinzufügen. Sie können auch einen Nonce oder einen Hash verwenden (siehe unten), sollten es aber besser nicht tun.
Das Verbot von Inline-Scripts ist der größte Sicherheitsgewinn, den CSP bietet. Das Verbot von Inline-Styles erhöht ebenfalls die Sicherheit Ihrer Anwendung. Es ist ein wenig Aufwand erforderlich, um sicherzustellen, dass alles richtig funktioniert, nachdem der gesamte Code außerhalb der Codezeile verschoben wurde. Dieser Aufwand lohnt sich aber.
Wenn Sie es unbedingt verwenden müssen
CSP Level 2 bietet Abwärtskompatibilität für Inline-Scripts, da Sie der Zulassungsliste bestimmte Inline-Scripts entweder mit einer kryptografischen Nonce (einmalig verwendete Zahl) oder einem Hash hinzufügen können. Das ist zwar etwas umständlich, kann aber in einer Notsituation nützlich sein.
Wenn Sie ein Einmalpasswort verwenden möchten, geben Sie Ihrem Script-Tag das Attribut „nonce“ hinzu. Der Wert muss mit einem Wert in der Liste der vertrauenswürdigen Quellen übereinstimmen. Beispiel:
<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
// Some inline code I can't remove yet, but need to asap.
</script>
Fügen Sie nun der script-src
-Anweisung, die dem Keyword nonce-
angehängt ist, den Nonce hinzu.
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
Nonce-Werte müssen für jede Seitenanfrage neu generiert werden und dürfen nicht erraten werden können.
Hashes funktionieren in etwa auf die gleiche Weise. Anstatt dem Script-Tag Code hinzuzufügen, erstellen Sie einen SHA-Hash des Scripts selbst und fügen Sie ihn der script-src
-Anweisung hinzu.
Angenommen, Ihre Seite enthält Folgendes:
<script>
alert('Hello, world.');
</script>
Ihre Richtlinie würde Folgendes enthalten:
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
Hier sind einige Punkte zu beachten. Das Präfix sha*-
gibt den Algorithmus an, mit dem der Hash generiert wird. Im obigen Beispiel wird sha256-
verwendet. Der CSP unterstützt auch sha384-
und sha512-
. Fügen Sie beim Generieren des Hashwerts keine <script>
-Tags hinzu. Auch Groß- und Kleinschreibung sowie Leerzeichen, einschließlich vorangestellter oder nachgestellter Leerzeichen, spielen eine Rolle.
Wenn Sie in Google nach dem Generieren von SHA-Hashes suchen, finden Sie Lösungen in einer Vielzahl von Sprachen. In Chrome 40 und höher können Sie die Entwicklertools öffnen und dann die Seite neu laden. Der Tab „Console“ enthält Fehlermeldungen mit dem korrekten SHA256-Hash für jedes Ihrer Inline-Scripts.
Eval auch
Selbst wenn ein Angreifer kein Script direkt einschleusen kann, kann er Ihre Anwendung dazu bringen, inaktiven Text in ausführbares JavaScript umzuwandeln und im eigenen Namen auszuführen. eval()
, new Function() , setTimeout([string], ...)
und setInterval([string], ...)
sind alle Vektoren, über die eingefügter Text zu einer unerwarteten schädlichen Ausführung führen kann. Die Standardreaktion des CSP auf dieses Risiko besteht darin, alle diese Vektoren vollständig zu blockieren.
Das hat einige Auswirkungen auf die Entwicklung von Anwendungen:
- Sie müssen JSON über die integrierte
JSON.parse
parsen und nicht aufeval
zurückgreifen. Native JSON-Vorgänge sind in allen Browsern seit IE8 verfügbar und absolut sicher. - Ersetzen Sie alle
setTimeout
- odersetInterval
-Aufrufe, die Sie derzeit verwenden, durch Inline-Funktionen anstelle von Strings. Beispiel:
setTimeout("document.querySelector('a').style.display = 'none';", 10);
sollte besser so geschrieben werden:
setTimeout(function () {
document.querySelector('a').style.display = 'none';
}, 10);
- Vermeiden Sie Inline-Vorlagen zur Laufzeit: Viele Vorlagenbibliotheken verwenden
new Function()
großzügig, um die Vorlagenerstellung zur Laufzeit zu beschleunigen. Das ist eine praktische Anwendung der dynamischen Programmierung, birgt aber das Risiko, schädlichen Text zu bewerten. Einige Frameworks unterstützen CSP standardmäßig und greifen bei fehlendereval
auf einen robusten Parser zurück. Die ng-csp-Richtlinie von AngularJS ist ein gutes Beispiel dafür.
Eine bessere Wahl wäre jedoch eine Vorlagensprache, die eine Vorkompilierung bietet (z. B. Handlebars). Wenn Sie Ihre Vorlagen vorkompilieren, kann die Nutzererfahrung sogar schneller sein als bei der schnellsten Laufzeitimplementierung. Außerdem ist sie sicherer. Wenn eval und seine Text-zu-JavaScript-Geschwister für Ihre Anwendung unerlässlich sind, können Sie sie aktivieren, indem Sie 'unsafe-eval'
als zulässige Quelle in einer script-src
-Richtlinie hinzufügen. Wir raten jedoch dringend davon ab. Wenn die Ausführung von Strings verboten ist, wird es für Angreifer viel schwieriger, nicht autorisierten Code auf Ihrer Website auszuführen.
Berichte
Die Möglichkeit von CSPs, nicht vertrauenswürdige Ressourcen clientseitig zu blockieren, ist ein großer Vorteil für Ihre Nutzer. Es wäre jedoch sehr hilfreich, wenn eine Art Benachrichtigung an den Server gesendet würde, damit Sie alle Fehler identifizieren und beheben können, die eine schädliche Injection überhaupt erst ermöglichen. Dazu können Sie den Browser anweisen, POST
-Verstoßberichte im JSON-Format an einen in einer report-uri
-Richtlinie angegebenen Speicherort zu senden.
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
Diese Berichte sehen in etwa so aus:
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
Dieser enthält viele Informationen, die Ihnen helfen, die genaue Ursache des Verstoßes zu ermitteln, einschließlich der Seite, auf der der Verstoß aufgetreten ist (document-uri
), des Verweis-URLs dieser Seite (im Gegensatz zum HTTP-Header-Feld ist der Schlüssel hier nicht falsch geschrieben), der Ressource, die gegen die Richtlinie der Seite verstößt (blocked-uri
), der spezifischen Richtlinie, gegen die verstoßen wurde (violated-directive
) und der vollständigen Richtlinie für die Seite (original-policy
).
Nur Berichterstellung
Wenn Sie gerade erst mit CSP beginnen, sollten Sie den aktuellen Status Ihrer Anwendung bewerten, bevor Sie eine strenge Richtlinie für Ihre Nutzer einführen.
Als Schritt auf dem Weg zu einer vollständigen Bereitstellung können Sie den Browser bitten, eine Richtlinie zu überwachen, Verstöße zu melden, die Einschränkungen jedoch nicht durchzusetzen. Senden Sie stattdessen einen Content-Security-Policy-Report-Only
-Header.Content-Security-Policy
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
Die im Modus „Nur melden“ angegebene Richtlinie blockiert eingeschränkte Ressourcen nicht, sendet aber Verstoßberichte an den angegebenen Speicherort. Sie können sogar beide Header senden, um eine Richtlinie durchzusetzen und gleichzeitig eine andere zu überwachen. So können Sie die Auswirkungen von Änderungen am CSP Ihrer Anwendung bewerten: Aktivieren Sie die Berichterstellung für eine neue Richtlinie, überwachen Sie die Verstoßberichte und beheben Sie alle auftretenden Fehler. Wenn Sie mit der Wirkung zufrieden sind, können Sie die neue Richtlinie erzwingen.
Praxisbeispiele
CSP 1 ist in Chrome, Safari und Firefox recht gut nutzbar, wird aber in IE 10 nur sehr eingeschränkt unterstützt. Weitere Informationen finden Sie unter caniuse.com. CSP-Level 2 ist seit Chrome-Version 40 verfügbar. Große Websites wie Twitter und Facebook haben die Kopfzeile bereits implementiert (die Fallstudie von Twitter ist lesenswert). Der Standard ist also bereit, auf Ihren eigenen Websites eingesetzt zu werden.
Der erste Schritt zum Erstellen einer Richtlinie für Ihre Anwendung besteht darin, die tatsächlich geladenen Ressourcen zu bewerten. Sobald Sie der Meinung sind, dass Sie die Funktionsweise Ihrer App verstanden haben, können Sie eine Richtlinie basierend auf diesen Anforderungen einrichten. Sehen wir uns einige gängige Anwendungsfälle an und überlegen wir, wie wir sie am besten innerhalb der sicheren Grenzen von CSP unterstützen können.
Anwendungsfall 1: Widgets für soziale Medien
Die +1-Schaltfläche von Google enthält ein Script von
https://apis.google.com
und ein eingebettetes<iframe>
vonhttps://plusone.google.com
. Sie benötigen eine Richtlinie, die beide Ursprünge enthält, um die Schaltfläche einzubetten. Eine minimale Richtlinie wärescript-src https://apis.google.com; child-src https://plusone.google.com
. Außerdem muss das von Google bereitgestellte JavaScript-Snippet in eine externe JavaScript-Datei kopiert werden. Wenn Sie eine Level-1-Richtlinie mitframe-src
hatten, mussten Sie sie aufgrund von Level 2 inchild-src
ändern. Das ist bei CSP-Level 3 nicht mehr erforderlich.Die Facebook-Magie-Schaltfläche kann auf verschiedene Weise implementiert werden. Wir empfehlen, die
<iframe>
-Version zu verwenden, da sie sich in einer sicheren Sandbox vom Rest Ihrer Website getrennt befindet. Für die ordnungsgemäße Funktion ist einechild-src https://facebook.com
-Anweisung erforderlich. Hinweis: Standardmäßig lädt der von Facebook bereitgestellte<iframe>
-Code eine relative URL,//facebook.com
,. Ändern Sie das, um HTTPS explizit anzugeben:https://facebook.com
. Es gibt keinen Grund, HTTP zu verwenden, wenn es nicht nötig ist.Die Tweet-Schaltfläche von Twitter benötigt Zugriff auf ein Script und einen Frame, die beide auf
https://platform.twitter.com
gehostet werden. Twitter stellt ebenfalls standardmäßig eine relative URL bereit. Bearbeiten Sie den Code, um HTTPS anzugeben, wenn Sie ihn lokal kopieren und einfügen.script-src https://platform.twitter.com; child-src https://platform.twitter.com
funktioniert dann problemlos, wenn du das von Twitter bereitgestellte JavaScript-Snippet in eine externe JavaScript-Datei verschiebst.Andere Plattformen haben ähnliche Anforderungen und können auf ähnliche Weise angegangen werden. Wir empfehlen, einfach eine
default-src
von'none'
festzulegen und in der Konsole zu prüfen, welche Ressourcen Sie aktivieren müssen, damit die Widgets funktionieren.
Das Einfügen mehrerer Widgets ist ganz einfach: Kombinieren Sie einfach die Richtlinienanweisungen und denken Sie daran, alle Ressourcen eines bestimmten Typs in einer einzigen Richtlinie zusammenzuführen. Wenn Sie alle drei Social-Media-Widgets verwenden möchten, würde die Richtlinie so aussehen:
script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com
Anwendungsfall 2: Lockdown
Angenommen, Sie betreiben eine Banking-Website und möchten dafür sorgen, dass nur die von Ihnen selbst erstellten Ressourcen geladen werden können. In diesem Szenario beginnen Sie mit einer Standardrichtlinie, die absolut alles blockiert (default-src 'none'
), und bauen dann darauf auf.
Angenommen, die Bank lädt alle Bilder, den Stil und das Script von einem CDN unter https://cdn.mybank.net
und stellt über XHR eine Verbindung zu https://api.mybank.com/
her, um verschiedene Daten abzurufen. Frames werden verwendet, aber nur für Seiten, die lokal auf der Website sind (keine Drittanbieterquellen). Auf der Website gibt es kein Flash, keine Schriftarten und keine Extras. Der strengste CSP-Header, den wir senden können, ist dieser:
Content-Security-Policy: default-src 'none'; script-src https://cdn.mybank.net; style-src https://cdn.mybank.net; img-src https://cdn.mybank.net; connect-src https://api.mybank.com; child-src 'self'
Anwendungsfall 3: Nur SSL
Der Administrator eines Forums für Trauringe möchte dafür sorgen, dass alle Ressourcen nur über sichere Kanäle geladen werden. Er schreibt aber nicht viel Code und ist nicht in der Lage, große Teile der Forumsoftware von Drittanbietern, die bis zum Rand mit Inline-Script und Stil gefüllt ist, neu zu schreiben. Die folgende Richtlinie würde angewendet:
Content-Security-Policy: default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'
Auch wenn https:
in default-src
angegeben ist, wird diese Quelle nicht automatisch von den Script- und Style-Direktiven übernommen. Jede Anweisung überschreibt die Standardeinstellung für diesen bestimmten Ressourcentyp vollständig.
Die Zukunft
Content Security Policy Level 2 ist eine mögliche Empfehlung. Die Arbeitsgruppe für Webanwendungssicherheit des W3C hat bereits mit der Arbeit an der nächsten Iteration der Spezifikation begonnen: Content Security Policy Level 3.
Wenn Sie an der Diskussion zu diesen anstehenden Funktionen interessiert sind, lesen Sie die Mailingliste „public-webappsec@“ oder nehmen Sie selbst daran teil.