(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 wyłącznie do danych użytkownika https://mybank.com, a element https://evil.example.com z pewnością nigdy nie powinien mieć takiego dostępu. 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. Hakerzy znaleźli sprytne sposoby na obalenie systemu.

Ataki typu cross-site scripting (XSS) pozwalają na przykład ominąć tę samą zasadę dotyczącą źródła, podstępem nakłaniając witrynę do przesłania złośliwego kodu i zamierzonej treści. To duży problem, ponieważ przeglądarki traktują cały kod wyświetlany na stronie jako słuszny element jej zabezpieczeń. Ściągawka XSS to stara, ale reprezentatywna przekrój metod, których atakujący może użyć, aby naruszyć zaufanie przez wstrzyknięcie złośliwego kodu. Jeśli atakujący wprowadzi jakikolwiek kod, oznacza to, że wszystko jest już przegrywające: dane sesji użytkownika zostały przejęte i informacje, które należy zachować w tajemnicy, wydostają się dla The Bad Guys. Oczywiście chcielibyśmy temu zapobiec, jeśli to możliwe.

W tym omówieniu przedstawiamy ochronę, która może znacznie zmniejszyć ryzyko i wpływ ataków XSS w nowoczesnych przeglądarkach: Content Security Policy (CSP).

TL;DR

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

Listy dozwolonych źródeł

Problem wykorzystywany w ramach ataków XSS polega na tym, że przeglądarka nie może odróżnić skryptu należącego do aplikacji od skryptu, który został błędnie wstrzykiwany przez osobę trzecią. 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. Wierzymy w ten kod, ale nie możemy oczekiwać, że przeglądarka sama określi, że kod z apis.google.com jest świetny, podczas gdy kod z apis.evil.example.com – raczej nie. Przeglądarka bez problemu pobiera i wykonuje każdy kod, o który prosi strona, niezależnie od źródła.

Zamiast ślepo ufać wszystkim dostarczanym przez serwer, CSP definiuje nagłówek HTTP Content-Security-Policy, który umożliwia utworzenie listy dozwolonych źródeł zaufanych treści i informuje przeglądarkę, że ma wykonywać lub renderować zasoby tylko z tych źródeł. Nawet jeśli osoba przeprowadzająca atak znajdzie otwór, przez który można wstrzyknąć skrypt, skrypt nie pasuje do listy dozwolonych i dlatego nie zostanie wykonany.

Ufamy, że apis.google.com dostarczy prawidłowy kod i robimy to samo, więc zdefiniujmy zasadę, która zezwala na wykonywanie skryptu tylko wtedy, gdy pochodzi z jednego z tych 2 źródeł:

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

Proste, prawda? Jak się pewnie spodziewasz, script-src to dyrektywa kontrolująca zestaw uprawnień związanych ze skryptem dla konkretnej strony. Jako prawidłowe źródło skryptu określono 'self' i https://apis.google.com jako kolejne. Przeglądarka poprawnie pobiera i wykonuje JavaScript z witryny apis.google.com przez HTTPS oraz ze źródła bieżącej strony.

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

Po zdefiniowaniu tej zasady przeglądarka zgłasza błąd, zamiast wczytać skrypt z innego źródła. Gdy sprytny haker zdoła wstrzyknąć kod do Twojej witryny, wyświetli mu się komunikat o błędzie, a nie spodziewany sukces.

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

Zasoby skryptów są najbardziej oczywistym zagrożeniem bezpieczeństwa, jednak CSP zapewnia bogaty zestaw dyrektyw zasad, które dają dość szczegółową kontrolę nad zasobami, które może wczytywać strona. Znasz już usługę script-src, więc jej koncepcja powinna być jasna.

Omówmy pokrótce pozostałe dyrektywy dotyczące zasobów. Lista poniżej przedstawia stan dyrektyw od poziomu 2. Opublikowano specyfikację poziomu 3, ale w największych przeglądarkach nie została jeszcze zaimplementowana.

  • base-uri ogranicza adresy URL, które mogą występować w elemencie <base> strony.
  • child-src zawiera adresy URL instancji roboczych oraz zawartości ramek umieszczonych w witrynie. Na przykład: child-src https://youtube.com umożliwia umieszczanie filmów z YouTube, ale nie z innych źródeł.
  • connect-src ogranicza liczbę źródeł, z którymi możesz się połączyć (za pomocą XHR, WebSockets i EventSource).
  • font-src określa źródła, które mogą udostępniać czcionki internetowe. 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ą zostać umieszczone na bieżącej stronie. Ta dyrektywa odnosi się do tagów <frame>, <iframe>, <embed> i <applet>. Tej dyrektywy nie można używać w tagach <meta>. Ma ona zastosowanie tylko do zasobów innych niż HTML.
  • Licencja frame-src została wycofana na poziomie 2, ale została przywrócona na poziomie 3. Jeśli nie jest widoczna, system powraca do child-src tak jak wcześniej.
  • img-src określa źródła, z których mogą być wczytywane obrazy.
  • media-src ogranicza źródła, z których mogą być przesyłane treści wideo i audio.
  • object-src umożliwia kontrolę nad Flashem i innymi wtyczkami.
  • plugin-types ogranicza rodzaje wtyczek, które może wywoływać strona.
  • 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 arkusza stylów script-src.
  • upgrade-insecure-requests instruuje klienty użytkownika, aby przepisywać schematy adresów URL i zmieniać protokół HTTP na HTTPS. Ta dyrektywa dotyczy witryn z dużą liczbą starych adresów URL, które wymagają przepisania.
  • 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 r. ta dyrektywa ma ograniczoną liczbę implementacji.

Domyślnie dyrektywy są otwarte. Jeśli nie ustawisz konkretnej zasady dla dyrektywy, powiedzmy font-src, dyrektywa będzie działać domyślnie tak, jakby jako prawidłowe źródło została wskazana dyrektywa * (np. możesz bez ograniczeń wczytywać czcionki z dowolnego miejsca).

Możesz zastąpić to domyślne działanie, określając dyrektywę default-src. Ta dyrektywa określa wartości domyślne dla większości nieokreślonych dyrektyw. Ogólnie dotyczy to każdej dyrektywy, która kończy się -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 podanych niżej dyrektywach nie jest używany element default-src. Pamiętaj, że jeśli ich nie skonfigurujesz, będzie to równoznaczne z zezwoleniem na cokolwiek.

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

Tych dyrektyw możesz użyć nie więcej niż w konkretnej aplikacji – wystarczy wymienić każdą z nich w nagłówku HTTP, rozdzielając je średnikami. Pamiętaj, aby w jednej dyrektywie wymienić wszystkie wymagane zasoby danego typu. Jeśli napiszesz coś takiego jak script-src https://host1.com; script-src https://host2.com, druga dyrektywa zostanie po prostu zignorowana. W przykładzie poniżej oba źródła zostałyby prawidłowo określone:

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

Jeśli na przykład masz aplikację, która wczytuje wszystkie swoje zasoby z sieci dostarczania treści (np. https://cdn.example.net) i wiesz, że nie potrzebujesz żadnych treści w ramkach ani wtyczek, Twoja zasada może wyglądać mniej więcej tak:

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

Szczegóły implementacji

W różnych samouczkach w internecie zobaczysz nagłówki X-WebKit-CSP i X-Content-Security-Policy. Od tej pory należy ignorować te z prefiksami. Nowoczesne przeglądarki (z wyjątkiem IE) obsługują nagłówek Content-Security-Policy bez prefiksu. Tego nagłówka należy użyć.

Niezależnie od użytego nagłówka zasady są definiowane osobno dla każdej strony: musisz wysyłać nagłówek HTTP z każdą odpowiedzią, którą chcesz zapewnić. Zapewnia to dużą elastyczność, ponieważ umożliwia dostosowanie zasad do konkretnych stron w zależności od ich konkretnych potrzeb. 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ślać według schematu (data:, https:) lub wybierając poziom szczegółowości – tylko nazwa hosta (example.com, który pasuje do dowolnego źródła na tym hoście: dowolny schemat, dowolny port) do w pełni kwalifikowanego identyfikatora URI (https://example.com:443, który pasuje tylko do HTTPS, tylko example.com i tylko port 443). Symbole wieloznaczne są akceptowane, ale tylko jako schemat, port lub w pierwszej pozycji nazwy hosta: *://*.example.com:* będzie dopasowywać wszystkie subdomeny example.com (ale nie samą zasadę example.com) przy użyciu dowolnego schematu na dowolnym porcie.

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

  • Nazwa 'none' nie odpowiada nic.
  • 'self' pasuje do bieżącego źródła, ale nie do jego subdomen.
  • 'unsafe-inline' pozwala na wbudowane JavaScript i CSS. (Omówimy tę kwestię bardziej szczegółowo).
  • 'unsafe-eval' zezwala na mechanizmy zamiany tekstu na JavaScript, takie jak eval. (To będzie też można zrobić).

Te słowa kluczowe wymagają cudzysłowu. Na przykład dyrektywa script-src 'self' (z cudzysłowem) zezwala na wykonywanie kodu JavaScript z bieżącego hosta; script-src self (bez cudzysłowów) zezwala na kod JavaScript z serwera o nazwie „self” (a nie z bieżącego hosta), co prawdopodobnie nie jest to, o co Ci chodzi.

Piaskownica

Jest jeszcze jedna dyrektywa, o której warto wspomnieć: sandbox. Różni się ona nieco od innych, które przyglądaliśmy się naszym opiniom, ponieważ nakłada ograniczenia na czynności, które może wykonywać strona, a nie na zasoby, które może być wczytywane. Jeśli dyrektywa sandbox jest obecna, strona jest traktowana tak, jakby została wczytana wewnątrz tagu <iframe> z atrybutem sandbox. Może to mieć szeroki wpływ na działanie strony: m.in. wymuszać na niej uzyskanie unikalnego pochodzenia lub uniemożliwić przesłanie formularza. Ten artykuł 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 CSP jest nagłówek HTTP. Warto jednak ustawić zasadę na stronie bezpośrednio w znacznikach. 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 uważany 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 osoba przeprowadzająca atak może wstrzyknąć tag skryptu zawierający bezpośrednio ładunek złośliwego oprogramowania (<script>sendMyDataToEvilDotCom();</script>), przeglądarka nie ma mechanizmu odróżniania go od prawidłowego wbudowanego tagu skryptu. CSP rozwiązuje ten problem przez całkowite zablokowanie wbudowanego skryptu – to jedyny sposób, aby mieć pewność.

Blokada obejmuje nie tylko skrypty umieszczone bezpośrednio w tagach script, ale też wbudowane moduły obsługi zdarzeń i adresy URL javascript:. Musisz przenieść zawartość tagów script do zewnętrznego pliku 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 przykład na:

<!-- 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 doskonale współgrają z 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. Przeniesienie kodu do zasobów zewnętrznych napisze lepszy kod.

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ć wbudowany skrypt i styl, 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ć wartości jednorazowej lub haszu (patrz poniżej), ale nie jest to konieczne. Blokowanie wbudowanego skryptu to największe bezpieczeństwo zapewniane przez CSP, a zablokowanie stylu wbudowanego wzmacnia aplikację. Sprawdzenie, czy po przeniesieniu kodu działa prawidłowo, wymaga na początku trochę wysiłku, ale warto się na to liczyć.

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

CSP poziomu 2 zapewnia zgodność wsteczną w przypadku skryptów w tekście, umożliwiając dodawanie określonych skryptów wbudowanych do listy dozwolonych za pomocą skrótu kryptograficznego (liczba używana raz) lub hasza. Jest to uciążliwe, ale przydatne.

Aby użyć liczby jednorazowej, przypisz tagowi skryptu atrybut jednorazowy. Jego wartość musi pasować do źródła 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 liczbę jednorazową do dyrektywy script-src dołączonej do słowa kluczowego nonce-.

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

Pamiętaj, że liczby jednorazowe muszą być generowane ponownie dla każdego żądania strony i muszą być niemożliwe do odgadnięcia.

Hasze działają bardzo podobnie. 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:

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

Oto treść zasad:

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

Pamiętaj o kilku kwestiach. Prefiks sha*- określa algorytm, który generuje hasz. W przykładzie powyżej użyto sha256-. CSP obsługuje również sha384- i sha512-. Podczas generowania haszu nie uwzględniaj tagów <script>. Stosujemy też wielkie litery i spacje, w tym odstępy na początku i na końcu.

Wyszukanie w Google metody generowania haszy SHA pozwoli 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ę. Karta Console (Konsola) będzie zawierać komunikaty o błędach z prawidłowym haszem sha256 dla każdego wbudowanego skryptu.

Oceń też

Nawet jeśli atakujący nie będzie w stanie wprowadzić skryptu bezpośrednio, może podstępem nakłonić aplikację do konwersji bezwzględnego tekstu na wykonywalny JavaScript i wykonanie go w jego imieniu. eval(), nowe funkcje Functions() , setTimeout([string], ...) i setInterval([string], ...) to wektory, przez które wstrzyknięty tekst może wykonać nieoczekiwanie złośliwe oprogramowanie. Domyślną odpowiedzią CSP na to ryzyko jest całkowite zablokowanie wszystkich tych wektorów.

Ma to kilka wpływu na sposób tworzenia aplikacji:

  • Musisz przeanalizować plik JSON za pomocą wbudowanego JSON.parse, zamiast polegać na 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 setTimeout lub setInterval, które obecnie wykonujesz z funkcjami w tekście, a nie ciągami znaków. Na przykład:
setTimeout("document.querySelector('a').style.display = 'none';", 10);

lepiej napisać tak:

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • Unikaj tworzenia wbudowanych szablonów w czasie działania: wiele bibliotek szablonów swobodnie korzysta z interfejsu new Function(), aby przyspieszyć generowanie szablonów w czasie działania. To sprytne zastosowanie programowania dynamicznego, ale wiąże się z ryzykiem oceny złośliwego tekstu. Niektóre platformy od razu obsługują CSP, a w razie braku eval używany jest solidny parser. Dobrym przykładem jest dyrektywa ng-csp narzędzia AngularJS.

Lepszym wyborem byłby jednak język szablonu, który umożliwia wstępną kompilację (np. kierki za pomocą paska sterowania). Wstępne kompilowanie szablonów może przyspieszyć obsługę użytkowników niż w przypadku najszybszej implementacji i jest bezpieczniejsze. Jeśli ocena i jej ciągi tekstowe na JavaScript są niezbędne w Twojej aplikacji, możesz je włączyć, dodając 'unsafe-eval' jako dozwolone źródło w dyrektywie script-src, ale zdecydowanie to odradzamy. Zablokowanie możliwości wykonywania ciągów znaków znacznie utrudnia atakującemu wykonanie w witrynie nieautoryzowanego kodu.

Zdawanie relacji

Możliwość blokowania niezaufanych zasobów po stronie klienta po stronie klienta jest bardzo przydatna, ale warto przesłać z powrotem do serwera jakieś powiadomienie, które umożliwi wykrywanie i eliminowanie błędów, które umożliwiają wstrzykiwanie szkodliwych treści. W tym celu możesz przekierować przeglądarkę do POST zgłoszeń o naruszeniach w formacie JSON do lokalizacji określonej w dyrektywie report-uri.

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

Raporty będą wyglądały 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 on sporo informacji, które pomogą Ci zidentyfikować konkretną przyczynę naruszenia, w tym stronę, na której doszło do naruszenia (document-uri), stronę odsyłającą tej strony (pamiętaj, że w przeciwieństwie do pola nagłówka HTTP klucz nie zawiera błędu), zasób, który naruszył zasady strony (blocked-uri), konkretną dyrektywę naruszoną (violated-directive) oraz pełną treść zasad strony (original-policy).

Tylko raport

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;

Zasada określona w trybie tylko do raportowania nie blokuje zasobów z ograniczeniami, ale wysyła zgłoszenia o naruszeniach do podanej przez Ciebie 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 na CSP w Twojej aplikacji: włącz raportowanie dla nowych zasad, monitoruj zgłoszenia o naruszeniach i napraw wszelkie znalezione błędy. Gdy wszystko będzie w porządku, zacznij egzekwować nowe zasady.

Rzeczywiste wykorzystanie w świecie

Standard CSP 1 jest całkiem przydatny w Chrome, Safari i Firefoksie, ale w IE 10 jest obsługiwany w ograniczonym zakresie. Szczegółowe informacje możesz znaleźć na stronie caniuse.com. CSP poziomu 2 jest dostępny w Chrome od wersji 40. Ogromne witryny, takie jak Twitter i Facebook, wdrożyły ten nagłówek (warto przeczytać studium przypadku na Twitterze), a ten standard jest już gotowy do wdrożenia we własnych witrynach.

Pierwszym krokiem na drodze do stworzenia zasady dla aplikacji jest ocena zasobów, które rzeczywiście wczytujesz. Gdy uznasz, że już wiesz, jak umieścić różne elementy w aplikacji, skonfiguruj zasady na podstawie tych wymagań. Przyjrzyjmy się kilku typowym przypadkom użycia i zastanówmy się, jak najlepiej zaspokoić je w ramach zabezpieczeń CSP.

Przypadek użycia nr 1: widżety mediów społecznościowych

  • Przycisk +1 Google zawiera skrypt z https://apis.google.com i <iframe> z https://plusone.google.com. Aby umieścić przycisk, musisz mieć zasadę, która uwzględnia 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 obowiązująca Cię zasada dotycząca poziomu 1 za pomocą frame-srcpoziomu 2 wymagała zmiany tego poziomu na child-src. Nie jest to już konieczne na poziomie CSP 3.

  • Przycisk Podoba mi się na Facebooku ma wiele opcji implementacji. Zalecamy pozostawienie wersji <iframe>, ponieważ jest ona bezpiecznie oddzielona od reszty witryny. Do jego prawidłowego działania wymagana jest dyrektywa child-src https://facebook.com. Pamiętaj, że domyślnie kod <iframe> udostępniany przez Facebooka wczytuje względny adres URL //facebook.com. Zmień je, aby wyraźnie określić protokół HTTPS: https://facebook.com. Nie ma powodu, aby używać protokołu HTTP, jeśli nie trzeba.

  • Przycisk tweeta na Twitterze wymaga dostępu do skryptu i ramki, które są hostowane na https://platform.twitter.com. (Twitter domyślnie udostępnia też względny URL. Edytuj kod, dodając do niego protokół HTTPS, który podczas kopiowania i wklejania lokalnie). Kod script-src https://platform.twitter.com; child-src https://platform.twitter.com będzie gotowy, o ile tylko przeniesiesz fragment kodu JavaScriptu udostępniony przez Twittera do zewnętrznego pliku JavaScript.

  • Inne platformy mają podobne wymagania i można je traktować w podobny sposób. Zalecamy ustawienie default-src o wartości 'none' i zaobserwowanie w konsoli zasobów, które należy włączyć, aby widżety działały.

Stosowanie wielu widżetów jest proste: wystarczy połączyć dyrektywy dotyczące zasad, pamiętając o scaleniu wszystkich zasobów danego typu w jedną dyrektywę. Gdy chcesz zobaczyć wszystkie 3 widżety 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 nr 2: blokada

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, style i skrypt z sieci CDN na stronie https://cdn.mybank.net i łączy się przez XHR z połączeniem https://api.mybank.com/, aby pobrać różne dane. Ramki są używane, ale tylko w przypadku stron lokalnych w danej witrynie (bez źródeł zewnętrznych). Na stronie nie ma Flasha, czcionek ani rozszerzeń. 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 tematyce ślubnej chce mieć pewność, że wszystkie zasoby są ładowane tylko przez bezpieczne kanały, ale nie piszą zbyt wiele kodu. Przepisywanie dużych fragmentów oprogramowania forum innej firmy, które wypełniono po brzegi wbudowanymi skryptami i stylem, jest poza jego możliwościami. Zastosujemy następujące zasady:

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

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

Przyszłość

Content Security Policy Level 2 to rekomendacja kandydatów. Grupa robocza ds. bezpieczeństwa aplikacji internetowych W3C rozpoczęła już prace nad kolejną iteracją specyfikacji – Content Security Policy Level 3.

Jeśli chcesz wziąć udział w dyskusji na temat nowych funkcji, przejrzyj archiwa listy adresowej public-webappsec@ lub weź udział w dyskusji we własnym zakresie.

Prześlij opinię