(standard) Content Security Policy

Joe Medley
Joe Medley

Model zabezpieczeń internetu opiera się na zasadach dotyczących tego samego źródła. Kod z https://mybank.com powinien mieć dostęp tylko do danych https://mybank.com, a dostęp do https://evil.example.com nigdy nie powinien być dozwolony. Każde źródło jest odizolowane od reszty sieci, dzięki czemu deweloperzy mają do dyspozycji bezpieczną piaskownicę, w której mogą tworzyć i grać. Teoretycznie wszystko jest genialne. Osoby przeprowadzające atak znajdują sprytne sposoby na obalenie systemu.

Ataki cross-site scripting (XSS) omijają zasadę tego samego pochodzenia, oszukując witrynę, aby dostarczała ona złośliwy kod wraz z zamierzoną treścią. To ogromny problem, ponieważ przeglądarki ufają wszystkiemu kodowi, który pojawia się na stronie, jako że jest on legalnym elementem pochodzenia zabezpieczeń tej strony. Poradnik XSS to stary, ale reprezentatywny przegląd metod, których może użyć atakujący, aby naruszyć to zaufanie, wstrzykując złośliwy kod. Jeśli atakujący wstrzyknie jakikolwiek kod, to praktycznie koniec gry: dane sesji użytkownika zostaną skompromitowane, a informacje, które powinny być utrzymywane w tajemnicy, zostaną przekazane do złych ludzi. Oczywiście chcielibyśmy temu zapobiec.

W tym przeglądzie omawiamy zabezpieczenie, które może znacznie zmniejszyć ryzyko i wpływ ataków typu XSS w nowoczesnych przeglądarkach: Content Security Policy (CSP).

TL;DR

  • Używaj list dozwolonych, aby informować klienta, co jest dozwolone, a co nie.
  • Dowiedz się, jakie dyrektywy są dostępne.
  • Poznaj wybrane słowa kluczowe.
  • Kod wbudowany i eval() są uznawane za szkodliwe.
  • Zgłaszaj naruszenia zasad na swoim serwerze, zanim je wyegzekwujesz.

Listy dozwolonych źródeł

Problem, który wykorzystują ataki XSS, polega na tym, że przeglądarka nie jest w stanie odróżnić skryptu będącego częścią aplikacji od skryptu wstrzykniętego przez osobę trzecią w złośliwy sposób. Na przykład przycisk Google +1 u dołu tej strony wczytuje i wykonuje kod z witryny https://apis.google.com/js/plusone.js w kontekście pochodzenia tej strony. Ufamy temu kodowi, ale nie możemy oczekiwać, że przeglądarka sama zorientuje się, że kod z apis.google.com jest świetny, a kod z apis.evil.example.com prawdopodobnie nie. Przeglądarka pobiera i wykonuje dowolny kod, którego strona wymaga, niezależnie od źródła.

Zamiast ślepo ufać wszystkim elementom dostarczanym przez serwer, standard CSP definiuje nagłówek HTTP Content-Security-Policy, który umożliwia utworzenie listy zezwalającej na źródła zaufanych treści i informuje przeglądarkę, aby uruchamiała lub renderowała tylko zasoby z tych źródeł. Nawet jeśli atakujący znajdzie lukę, przez którą można wstrzyknąć skrypt, skrypt nie będzie pasować do listy dozwolonych, a więc nie zostanie wykonany.

Ponieważ ufamy, że apis.google.com dostarcza prawidłowy kod, i wierzymy, że my też, zdefiniujmy zasadę, która zezwala na wykonanie skryptu tylko wtedy, gdy pochodzi on z jednego z tych 2 źródeł:

Content-Security-Policy: script-src 'self' https://apis.google.com

Proste, prawda? Jak już pewnie wiesz, script-src to dyrektywa, która kontroluje zestaw uprawnień związanych ze skryptem na konkretnej stronie. Wskazaliśmy 'self' jako jeden prawidłowy źródło skryptu, a https://apis.google.com jako drugie. Przeglądarka pobiera i wykonuje kod JavaScript z apis.google.com przez HTTPS, a także z źródła bieżącej strony.

Błąd w konsoli: wczytywanie skryptu „http://evil.example.com/evil.js” zostało odrzucone, ponieważ narusza on tę dyrektywę Content Security Policy: script-src 'self' https://apis.google.com

Gdy ta zasada jest zdefiniowana, zamiast wczytywać skrypt z dowolnego źródła, przeglądarka po prostu wyświetla komunikat o błędzie. Gdy sprytnemu atakującemu uda się wstrzyknąć kod do Twojej witryny, zamiast oczekiwanego efektu zobaczy komunikat o błędzie.

Zasada ma zastosowanie do wielu różnych zasobów

Chociaż zasoby skryptów stanowią największe zagrożenie dla bezpieczeństwa, CSP udostępnia bogaty zestaw dyrektyw zasad, które umożliwiają dość szczegółową kontrolę nad zasobami, które mogą być wczytywane na stronie. Znasz już usługę script-src, więc jej koncepcja powinna być jasna.

Omówmy szybko pozostałe dyrektywy dotyczące zasobów. Lista poniżej przedstawia stan dyrektyw na poziomie 2. Specyfikacja poziomu 3 została opublikowana, ale jest w dużej mierze niezrealizowana w głównych przeglądarkach.

  • base-uri ogranicza adresy URL, które mogą występować w elemencie <base> strony.
  • child-src zawiera listę adresów URL procesów i zawartości wbudowanych ramek. Na przykład: child-src https://youtube.com umożliwi umieszczanie filmów z YouTube, ale nie z innych źródeł.
  • connect-src ogranicza źródła, z którymi możesz się łączyć (za pomocą XHR, WebSockets i EventSource).
  • font-src określa pochodzenie czcionek internetowych. Czcionki internetowe Google można włączyć za pomocą font-src https://themes.googleusercontent.com.
  • form-action zawiera listę prawidłowych punktów końcowych, które można przesłać z tagów <form>.
  • frame-ancestors określa źródła, które mogą osadzić bieżącą stronę. Ta dyrektywa dotyczy tagów <frame>, <iframe>, <embed><applet>. Tej dyrektywy nie można używać w tagach <meta>. Ma ona zastosowanie tylko do zasobów innych niż HTML.
  • frame-src zostało wycofane na poziomie 2, ale przywrócone na poziomie 3. Jeśli nie, nadal będzie używana wartość domyślna child-src.
  • img-src określa źródła, z których można wczytywać obrazy.
  • media-src ogranicza źródła, z których można przesyłać dźwięk i obraz.
  • object-src umożliwia kontrolowanie Flasha i innych wtyczek.
  • plugin-types ogranicza rodzaje wtyczek, które strona może wywoływać.
  • report-uri określa adres URL, na który przeglądarka wysyła zgłoszenia w przypadku naruszenia zasady bezpieczeństwa treści. Tej dyrektywy nie można używać w tagach <meta>.
  • style-src to odpowiednik script-src dla arkuszy stylów.
  • upgrade-insecure-requests nakazuje klientom użytkownika przekształcać schematy adresów URL, zamieniając HTTP na HTTPS. Ta reguła dotyczy witryn z dużą liczbą starych adresów URL, które trzeba przepisać.
  • worker-src to dyrektywa CSP poziomu 3 ograniczająca adresy URL, które mogą być wczytywane jako instancja robocza, współdzielona instancja robocza lub skrypt service worker. Od lipca 2017 roku ta dyrektywa ma ograniczone wdrożenia.

Domyślnie dyrektywy są otwarte. Jeśli nie ustawisz konkretnych zasad dla dyrektywy, np. font-src, to ta dyrektywa będzie działać domyślnie tak, jakbyś podał * jako prawidłowe źródło (np. możesz wczytywać czcionki skądkolwiek bez ograniczeń).

Możesz zmienić to domyślne działanie, podając dyrektywę default-src. Ta dyrektywa definiuje ustawienia domyślne większości dyrektyw, które nie są określone. Zasadniczo dotyczy to każdej dyrektywy, która kończy się na -src. Jeśli default-src ma wartość https://example.com i nie określisz dyrektywy font-src, możesz ładować czcionki z https://example.com i nigdzie indziej. We wcześniejszych przykładach określiliśmy tylko właściwość script-src, co oznacza, że obrazy, czcionki itd. mogą być ładowane z dowolnego źródła.

W tych dyrektywach nie jest używany element default-src. Pamiętaj, że brak ich ustawienia jest równoznaczny z zezwoleniem na wszystko.

  • base-uri
  • form-action
  • frame-ancestors
  • plugin-types
  • report-uri
  • sandbox

Możesz użyć dowolnej liczby tych dyrektyw, zależnie od potrzeb konkretnej aplikacji. Wystarczy, że wymienisz je w nagłówku HTTP, rozdzielając je średnikami. Pamiętaj, aby w pojedynczej dyrektywie podać wszystkie wymagane zasoby określonego typu. Jeśli wpiszesz coś takiego: script-src https://host1.com; script-src https://host2.com, druga dyrektywa zostanie po prostu zignorowana. Przykładowa poprawna specyfikacja obu źródeł:

script-src https://host1.com https://host2.com

Jeśli np. masz aplikację, która wczytuje wszystkie zasoby z sieci dostarczania treści (np. https://cdn.example.net), i wiesz, że nie potrzebujesz treści w ramce ani wtyczek, Twoje zasady mogą wyglądać mniej więcej tak:

Content-Security-Policy: default-src https://cdn.example.net; child-src 'none'; object-src 'none'

Szczegóły implementacji

Nagłówki X-WebKit-CSPX-Content-Security-Policy znajdziesz w różnych samouczkach w internecie. Od tej pory ignoruj nagłówki z prefiksem. Nowoczesne przeglądarki (z wyjątkiem Internet Explorera) obsługują nagłówek Content-Security-Policy bez prefiksu. Tego nagłówka powinieneś użyć.

Bez względu na to, którego nagłówka używasz, zasady są definiowane osobno dla każdej strony: musisz wysłać nagłówek HTTP z każdą odpowiedzią, którą chcesz chronić. Daje to dużą elastyczność, ponieważ możesz dostosować zasady do konkretnych stron zgodnie z ich potrzebami. Być może tylko jedna strona w Twojej witrynie ma przycisk +1, podczas gdy inne nie – możliwe, że kod przycisku będzie ładowany tylko wtedy, gdy będzie to konieczne.

Lista źródeł w każdej dyrektywie jest elastyczna. Źródła możesz określić według schematu (data:, https:) lub z różnym zakresem szczegółowości: od nazwy hosta (example.com, która pasuje do dowolnego źródła na tym hoście: dowolny schemat, dowolny port) do pełnego identyfikatora URI (https://example.com:443, który pasuje tylko do HTTPS, tylko do example.com i tylko do portu 443). Symbole wieloznaczne są akceptowane, ale tylko jako schemat, port lub w najbardziej lewej pozycji nazwy hosta: *://*.example.com:* będzie pasować do wszystkich subdomen example.com (ale nie do samej example.com), używając dowolnego schematu i dowolnego portu.

Lista źródeł może też zawierać 4 słowa kluczowe:

  • 'none', jak można się spodziewać, nie pasuje do niczego.
  • 'self' pasuje do bieżącego źródła, ale nie do jego subdomen.
  • 'unsafe-inline' umożliwia wstawianie kodu JavaScript i CSS. (Wkrótce omówimy to bardziej szczegółowo).
  • 'unsafe-eval' umożliwia stosowanie mechanizmów konwersji tekstu na kod JavaScript, takich jak eval. (To będzie też można zrobić).

Te słowa kluczowe wymagają cudzysłowów. Na przykład script-src 'self' (w cudzysłowie) autoryzuje wykonywanie kodu JavaScript z bieżącego hosta, a script-src self (bez cudzysłowu) zezwala na wykonywanie kodu JavaScript z serwera o nazwie „self” (a nie z bieżącego hosta), co prawdopodobnie nie jest tym, co masz na myśli.

Piaskownica

Jest jeszcze jedna dyrektywa, o której warto wspomnieć: sandbox. Jest on nieco inny niż inne, które analizowaliśmy, ponieważ nakłada ograniczenia na działania, które może wykonać strona, a nie na zasoby, które może wczytać. Jeśli występuje dyrektywa sandbox, strona jest traktowana tak, jakby została załadowana w ramach elementu <iframe> z atrybutem sandbox. Może to mieć na nią różny wpływ: może na przykład wymusić unikalny element źródła lub uniemożliwić przesyłanie formularzy. Temat ten wykracza poza zakres tego artykułu, ale szczegółowe informacje o prawidłowych atrybutach piaskownicy znajdziesz w sekcji „Piaskownica” specyfikacji HTML5.

Metatag

Preferowanym mechanizmem dostarczania przez dostawców usług internetowych jest nagłówek HTTP. Może jednak być przydatne ustawienie zasad na stronie bezpośrednio w sygnalizacji. Użyj do tego tagu <meta> z atrybutem http-equiv:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'"
/>

Nie można użyć tej opcji w przypadku usług frame-ancestors, report-uri i sandbox.

Kod wbudowany jest uznawany za szkodliwy

Powinno być jasne, że CSP opiera się na źródłach z listy dozwolonych, ponieważ jest to jednoznaczne polecenie przeglądarki, aby traktowała określone zestawy zasobów jako akceptowalne i odrzucała pozostałe. Listy dozwolonych oparte na źródle nie eliminują jednak największego zagrożenia związanego z atakami XSS, czyli wstrzykiwania wbudowanego skryptu. Jeśli atakujący może wstrzyknąć tag skryptu, który bezpośrednio zawiera złośliwy ładunek (<script>sendMyDataToEvilDotCom();</script>), przeglądarka nie ma mechanizmu, który pozwoliłby odróżnić go od legalnego tagu skryptu wstawionego w kodzie. CSP rozwiązuje ten problem przez całkowite zablokowanie wbudowanego skryptu – to jedyny sposób, aby mieć pewność.

Zakaz obejmuje nie tylko skrypty osadzone bezpośrednio w tagach script, ale też wbudowane w tagi script wywołania zdarzeń i adresy URL javascript:. Musisz przenieść zawartość tagów script do pliku zewnętrznego i zastąpić adresy URL javascript: oraz <a ... onclick="[JAVASCRIPT]"> odpowiednimi wywołaniami addEventListener(). Możesz na przykład przepisać taki fragment zawartości:

<script>
  function doAmazingThings() {
    alert('YOU AM AMAZING!');
  }
</script>
<button onclick="doAmazingThings();">Am I amazing?</button>

na coś takiego:

<!-- 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);
});

Przebudowany kod ma wiele zalet, które nie tylko dobrze sprawdzają się w CSP. Jest to sprawdzona metoda, niezależnie od tego, czy korzystasz z CSP. JavaScript łączy strukturę i działanie w niewłaściwy sposób. Zasoby zewnętrzne są łatwiejsze do przechowywania w pamięci podręcznej przeglądarki, są bardziej zrozumiałe dla programistów i sprzyjają kompilacji i minifikacji. Lepszy kod możesz napisać, jeśli przeniesiesz go do zasobów zewnętrznych.

Styl wbudowany jest traktowany w ten sam sposób: zarówno atrybut style, jak i tagi style powinny zostać skonsolidowane w zewnętrzne arkusze stylów, aby chronić je przed różnymi zaskakująco sprytnymi metodami wydobycia danych, z których korzysta CSS.

Jeśli musisz mieć skrypt i styl w tekście, możesz je włączyć, dodając 'unsafe-inline' jako dozwolone źródło w dyrektywie script-src lub style-src. Możesz też użyć nonce lub hasha (patrz poniżej), ale nie jest to zalecane. Zakaz skryptów wbudowanych to największa korzyść z użycia CSP pod względem bezpieczeństwa, a zakaz stylów wbudowanych również zwiększa odporność aplikacji. Wymaga to trochę wysiłku, aby mieć pewność, że wszystko będzie działać prawidłowo po przeniesieniu całego kodu offline, ale warto.

Jeśli bezwzględnie musisz go używać

CSP poziomu 2 zapewnia wsteczną zgodność ze skryptami w ciele dokumentu, umożliwiając dodawanie konkretnych skryptów do listy dozwolonych za pomocą liczby jednorazowej (numeru użytego raz) lub hasza. Chociaż może to być kłopotliwe, jest to przydatne w krytycznym momencie.

Aby użyć liczby jednorazowej, przypisz tagowi skryptu atrybut jednorazowy. Jego wartość musi być zgodna z wartością na liście zaufanych źródeł. Na przykład:

<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
  // Some inline code I can't remove yet, but need to asap.
</script>

Teraz dodaj losowy ciąg znaków do dyrektywy script-src dołączonej do słowa kluczowego nonce-.

Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

Pamiętaj, że nonce'y muszą być generowane na potrzeby każdego żądania strony i nie mogą być zgadywane.

Hasze działają w podobny sposób. Zamiast dodawać kod do tagu skryptu, utwórz hasz SHA samego skryptu i dodaj go do dyrektywy script-src. Załóżmy na przykład, że Twoja strona zawierała taki fragment kodu:

<script>
  alert('Hello, world.');
</script>

Twoje zasady powinny zawierać te informacje:

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

Pamiętaj o kilku kwestiach. Prefiks sha*- określa algorytm, który generuje ciąg znaków. W tym przykładzie użyto znacznika sha256-. CSP obsługuje również sha384- i sha512-. Podczas generowania haszu nie uwzględniaj tagów <script>. Liczy się też wielkość liter i odstępy, w tym spacje wiodące i kończące.

Wyszukiwanie w Google informacji o generowaniu haszy SHA pozwoli Ci znaleźć rozwiązania w dowolnej liczbie języków. W Chrome 40 lub nowszej wersji możesz otworzyć Narzędzia deweloperskie, a następnie ponownie załadować stronę. Na karcie Konsole będą się wyświetlać komunikaty o błędach z prawidłowym skrótem sha256 dla każdego wbudowanego skryptu.

Eval too

Nawet jeśli atakujący nie może wstrzyknąć skryptu bezpośrednio, może nakłonić Twoją aplikację do przekształcenia zwykłego tekstu w wykonalny kod JavaScript i wykonanie go w swoim imieniu. eval(), new Function() , setTimeout([string], ...) i setInterval([string], ...) to wektory, za pomocą których wstrzyknięty tekst może wykonać coś nieoczekwanie złośliwego. Domyślną reakcją CSP na to ryzyko jest całkowite zablokowanie wszystkich tych wektorów.

Ma to wiele konsekwencji dla sposobu tworzenia aplikacji:

  • Musisz przeanalizować dane JSON za pomocą wbudowanej funkcji JSON.parse, a nie funkcji eval. Natywne operacje JSON są dostępne w każdej przeglądarce od wersji IE8 i są w pełni bezpieczne.
  • Zastąp wywołania funkcji setTimeout lub setInterval funkcjami wbudowanymi zamiast ciągów znaków. Na przykład:
setTimeout("document.querySelector('a').style.display = 'none';", 10);

lepiej napisać:

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • Unikaj szablonów wbudowanych w czasie wykonywania: wiele bibliotek szablonów używa new Function(), aby przyspieszyć generowanie szablonów w czasie wykonywania. Jest to sprytne zastosowanie programowania dynamicznego, ale wiąże się z ryzykiem oceny złośliwego tekstu. Niektóre frameworki obsługują CSP, używając domyślnie niezawodnego parsowania, a w przeciwnym razie używając eval. Dobrym przykładem jest dyrektywa ng-csp narzędzia AngularJS.

Lepszym wyborem będzie jednak język szablonów, który oferuje wstępną kompilację (np. Handlebars). Wstępna kompilacja szablonów może przyspieszyć działanie aplikacji nawet bardziej niż najszybsza implementacja w czasie wykonywania, a dodatkowo jest bezpieczniejsza. Jeśli funkcja eval i jej odpowiedniki do konwertowania tekstu na JavaScript są niezbędne w Twojej aplikacji, możesz je włączyć, dodając 'unsafe-eval' jako dozwolone źródło w instrukcji script-src, ale zdecydowanie odradzamy to. Zakaz wykonywania skryptów znacznie utrudnia atakującemu wykonywanie w Twojej witrynie nieautoryzowanego kodu.

Raportowanie

Możliwość blokowania przez CSP niesprawdzonych zasobów po stronie klienta to ogromna korzyść dla użytkowników, ale przydatne byłoby też wysyłanie powiadomień do serwera, aby można było wykrywać i usuwać błędy umożliwiające wstrzyknięcie złośliwego kodu. W tym celu możesz nakazać przeglądarce POST zgłaszanie naruszeń w formacie JSON do lokalizacji określonej w dyrektywie report-uri.

Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

Te raporty będą wyglądać mniej więcej tak:

{
  "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"
  }
}

Zawiera ona wiele informacji, które pomogą Ci znaleźć konkretną przyczynę naruszenia, w tym stronę, w której wystąpiło naruszenie (document-uri), odnośnik do tej strony (pamiętaj, że w odróżnieniu od pola nagłówka HTTP klucz nie zawiera literówek), zasób, który naruszył zasady strony (blocked-uri), konkretną dyrektywę, którą naruszono (violated-directive), oraz pełne zasady strony (original-policy).

Tylko raporty

Jeśli dopiero zaczynasz korzystać z CSP, przed wdrożeniem dla użytkowników drastycznych zasad warto ocenić bieżący stan aplikacji. Krokiem do pełnego wdrożenia jest poproszenie przeglądarki o monitorowanie zasad, zgłaszanie naruszeń, ale bez egzekwowania ograniczeń. Zamiast wysyłać nagłówek Content-Security-Policy, wyślij nagłówek Content-Security-Policy-Report-Only.

Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;

Zasady określone w trybie tylko do raportowania nie blokują zasobów objętych ograniczeniami, ale wysyłają raporty o naruszeniu zasad do określonej lokalizacji. Możesz nawet wysłać oba nagłówki, egzekwując jedną zasadę i monitorując inną. To świetny sposób na ocenę wpływu zmian w CSP aplikacji: włącz raportowanie nowych zasad, monitoruj raporty o naruszeniu i naprawiaj pojawiające się błędy. Gdy będziesz zadowolony/zadowolona z wyników, zacznij stosować nowe zasady.

Rzeczywiste wykorzystanie w świecie

CSP 1 jest dość przydatny w Chrome, Safari i Firefox, ale ma bardzo ograniczone wsparcie w IE 10. Szczegółowe informacje znajdziesz na stronie caniuse.com. CSP na poziomie 2 jest dostępne w Chrome od wersji 40. Duże witryny, takie jak Twitter i Facebook, wdrożyły nagłówek (warto przeczytać studium przypadku Twittera), a standard jest już gotowy do wdrożenia w Twoich witrynach.

Pierwszym krokiem w sprawie tworzenia zasad dla aplikacji jest ocena zasobów, które faktycznie wczytujesz. Gdy uznasz, że masz już zaawansowaną wiedzę na temat tego, jak wszystko jest ze sobą powiązane w aplikacji, skonfiguruj zasady na podstawie tych wymagań. Przyjrzyjmy się kilku typom zastosowań i sprawdźmy, jak najlepiej możemy je obsługiwać w ramach zabezpieczeń CSP.

Przypadek użycia 1. Widgety mediów społecznościowych

  • Przycisk +1 Google zawiera skrypt z https://apis.google.com i wstawia <iframe>https://plusone.google.com. Aby osadzić przycisk, musisz mieć zasadę, która obejmuje oba te źródła. Minimalną zasadą jest script-src https://apis.google.com; child-src https://plusone.google.com. Trzeba też pamiętać, by fragment kodu JavaScript udostępniony przez Google został pobrany do zewnętrznego pliku JavaScript. Jeśli masz zasadę na poziomie 1, która używa wartości frame-src, na poziomie 2 musisz ją zmienić na child-src. Nie jest to już wymagane w ramach CSP poziomu 3.

  • Przycisk „Lubię to” na Facebooku można wdrożyć na kilka sposobów. Zalecamy korzystanie z wersji <iframe>, ponieważ jest ona bezpiecznie oddzielona od reszty witryny. Do prawidłowego działania wymaga dyrektywy child-src https://facebook.com. Pamiętaj, że domyślnie kod <iframe> udostępniany przez Facebooka wczytuje względny adres URL //facebook.com. Zmień to, aby wyraźnie określić HTTPS: https://facebook.com. Nie ma powodu, aby używać HTTP, jeśli nie musisz.

  • Przycisk Tweeta w Twitterze wymaga dostępu do skryptu i ramki, które są hostowane na stronie https://platform.twitter.com. (Twitter również domyślnie udostępnia adres URL bezwzględny; podczas kopiowania i wklejania kodu lokalnie należy go zmienić, aby wskazać protokół HTTPS). Wszystko będzie gotowe, gdy przeniesiesz fragment kodu JavaScript udostępniony przez Twittera do zewnętrznego pliku JavaScript.

  • Inne platformy mają podobne wymagania i można je rozwiązać w podobny sposób. Zalecamy ustawienie default-src na 'none' i obserwowanie konsoli, aby określić, które zasoby należy włączyć, aby widżety działały.

Wstawianie wielu widżetów jest proste: wystarczy połączyć dyrektywy zasad, pamiętając o połączeniu wszystkich zasobów danego typu w jedną dyrektywę. Jeśli chcesz użyć wszystkich 3 widżetów mediów społecznościowych, zasady będą wyglądać tak:

script-src https://apis.google.com https://platform.twitter.com; child-src https://plusone.google.com https://facebook.com https://platform.twitter.com

Przypadek użycia 2. Zamknięcie

Załóżmy, że prowadzisz witrynę bankową i chcesz mieć pewność, że można załadować tylko napisane przez Ciebie zasoby. W tym scenariuszu zacznij od domyślnej zasady, która blokuje absolutnie wszystko (default-src 'none'), i kontynuuj ją.

Załóżmy, że bank wczytuje wszystkie obrazy, styl i skrypt z CDN na poziomie https://cdn.mybank.net i łączy się za pomocą XHR z https://api.mybank.com/, aby pobrać różne dane. Ramki są używane, ale tylko na stronach dostępnych lokalnie w witrynie (nie pochodzą z źródeł zewnętrznych). W witrynie nie ma Flasha, czcionek ani dodatków. Najbardziej restrykcyjny nagłówek CSP, jaki możemy wysłać, to:

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'

Przypadek użycia nr 3: tylko SSL

Administrator forum dyskusyjnego o pierścionkach ślubnych chce mieć pewność, że wszystkie zasoby są wczytywane tylko przez bezpieczne kanały, ale nie pisze zbyt wiele kodu. Przepisywanie dużych fragmentów oprogramowania forum zewnętrznego, które jest wypełnione skryptem wbudowanym i ma określony styl, wykracza poza jego możliwości. Te zasady byłyby skuteczne:

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

Mimo że w sekcji default-src występuje wartość https:, dyrektywy skryptu i stylu nie dziedziczą automatycznie tego źródła. Każda dyrektywa całkowicie zastępuje wartość domyślną dla danego typu zasobu.

Przyszłość

Poziom 2 standardu Content Security Policy to Rekomendacja kandydata. Grupa robocza ds. bezpieczeństwa aplikacji internetowych W3C rozpoczęła już prace nad kolejną wersją specyfikacji, czyli poziomem 3 zasad bezpieczeństwa treści.

Jeśli interesuje Cię dyskusja na temat tych nadchodzących funkcji, przejrz archiwa listy mailingowej public-webappsec@ lub dołącz do niej.

Prześlij opinię