(standard) Content Security Policy

Jan Kowalski
Joe Medley

Model zabezpieczeń internetu ma dostęp do roota w ramach zasady dotyczącej tego samego źródła. Kod z domeny https://mybank.com powinien mieć dostęp tylko do danych usługi https://mybank.com, a https://evil.example.com z pewnością nie powinien mieć dostępu do takiej usługi. Każde źródło jest odizolowane od reszty internetu, dając deweloperom bezpieczną piaskownicę, w której mogą oni tworzyć i grać. Teoretycznie to jest genialne. W praktyce hakerzy znaleźli sprytny sposób obalenia systemu.

Na przykład ataki typu cross-site scripting (XSS) omijają tę samą zasadę dotyczącą źródła, podstępem nakłaniając witrynę do dostarczenia złośliwego kodu wraz z zamierzanymi treściami. To duży problem, ponieważ przeglądarki ufają, że cały kod widoczny na stronie jest wiarygodnie częścią źródła zabezpieczeń. Ściągawka XSS zawiera stara, ale reprezentatywną analizę metod atakujących, które mogą wykorzystać do naruszenia tego zaufania przez wstrzyknięcie złośliwego kodu. Jeśli osoba przeprowadzająca atak wstrzykuje dowolny kod, oznacza to, że w ogóle się to nie uda – dane sesji użytkownika zostają przejęte, a informacje, które należy zachować w tajemnicy, zostają wydobyte do zespołu The Bad Guys. Oczywiście wolimy temu zapobiegać, 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

  • Dzięki listom dozwolonych możesz poinformować klienta, co jest dozwolone, a co nie.
  • Dowiedz się, jakie dyrektywy są dostępne.
  • Dowiedz się, jakie słowa kluczowe pobierają.
  • Kod wbudowany i element eval() są uznawane za szkodliwe.
  • Zanim wyegzekwujesz naruszenia zasad, zgłoś je na swoim serwerze.

Listy dozwolonych źródeł

Problem związany z atakami XSS polega na tym, że przeglądarka nie potrafi odróżnić skryptu należącego do aplikacji od skryptu, który został złośliwie wstrzyknięty przez inną firmę. Na przykład przycisk Google +1 u dołu strony wczytuje się i uruchamia kod z https://apis.google.com/js/plusone.js w kontekście pochodzenia strony. Ufamy temu kodowi, ale nie oczekujemy, że przeglądarka samodzielnie zdobędzie informację, że kod z adresu apis.google.com jest świetny, ale kod z apis.evil.example.com prawdopodobnie nie jest. Przeglądarka bez problemu pobiera i uruchamia każdy kod zażądany przez stronę, niezależnie od źródła.

Zamiast ślepo ufać wszystkim udostępnianym 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 uruchamiać lub renderować tylko zasoby z tych źródeł. Nawet jeśli osoba przeprowadzająca atak znajdzie lukę, przez którą wstrzyknąć skrypt, nie będzie on pasować do listy dozwolonych, w związku z czym nie zostanie wykonany.

ufamy, że apis.google.com dostarcza prawidłowy kod, i wierzymy, że tak samo zrobimy. Zdefiniujmy zasadę, która pozwala 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 pewnie się domyślasz, script-src to dyrektywa, która kontroluje zestaw uprawnień związanych ze skryptem na danej stronie. Określiliśmy 'self' jako jedno prawidłowe źródło skryptu, a https://apis.google.com jako drugie. Przeglądarka prawidłowo pobiera i uruchamia JavaScript z apis.google.com przez HTTPS, a także z źródła bieżącej strony.

Błąd konsoli: odmówiono wczytania skryptu „http://evil.example.com/evil.js”, ponieważ narusza on następującą dyrektywę Content Security Policy: script-src 'self' https://apis.google.com

Gdy ta zasada jest zdefiniowana, przeglądarka po prostu zgłasza błąd, zamiast wczytywać skrypt z innego źródła. Jeśli uda mu się wstrzyknąć kod do witryny, zamiast oczekiwano powodzenia, zobaczy komunikat o błędzie.

Zasady mają zastosowanie do wielu różnych zasobów

Zasoby skryptu są najbardziej oczywistym zagrożeniem dla bezpieczeństwa, jednak CSP udostępnia bogaty zestaw dyrektyw zasad, które umożliwiają dość szczegółową kontrolę nad zasobami, które może wczytywać strona. Znasz już nazwę script-src, więc jej opis powinien być jasny.

Omówmy pokrótce pozostałe dyrektywy dotyczące zasobów. Lista poniżej przedstawia stan dyrektyw na poziomie 2. Opublikowano specyfikację na poziomie 3, ale w dużej mierze nie została ona zaimplementowana w głównych przeglądarkach.

  • base-uri ogranicza liczbę adresów URL, które mogą się pojawiać w elemencie <base> strony.
  • child-src zawiera listę adresów URL instancji roboczych i zawartości umieszczonych 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ę połączyć (za pomocą XHR, WebSockets i EventSource).
  • font-src określa źródła, które mogą wyświetlać czcionki internetowe. Czcionki internetowe Google można włączyć za pomocą parametru font-src https://themes.googleusercontent.com.
  • form-action zawiera listę prawidłowych punktów końcowych do przesyłania z tagów <form>.
  • frame-ancestors określa źródła, w których można umieścić bieżącą stronę. Ta dyrektywa dotyczy tagów <frame>, <iframe>, <embed> i <applet>. Tej dyrektywy nie można używać w tagach <meta>. Dotyczy ona tylko zasobów innych niż HTML.
  • Aplikacja frame-src została wycofana na poziomie 2, ale została przywrócona na poziomie 3. Jeśli go nie widać, wartość nadal będzie ustawiona jako child-src.
  • img-src określa źródła, z których można ładować obrazy.
  • media-src ogranicza źródła, które mogą przesyłać wideo i dźwięk.
  • 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, pod który przeglądarka wysyła raporty po naruszeniu zasady bezpieczeństwa treści. Tej dyrektywy nie można używać w tagach <meta>.
  • style-src jest odpowiednikiem arkuszy stylów script-src.
  • upgrade-insecure-requests nakazuje klientom użytkownika przepisywanie schematów adresów URL i zmianę HTTP na HTTPS. Ta dyrektywa 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ć ładowane jako instancje robocze, udostępnione instancje robocze i skrypty service worker. Od lipca 2017 roku implementacja tej dyrektywy jest ograniczona.

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

Możesz zastąpić to domyślne działanie, określając dyrektywę default-src. Ta dyrektywa definiuje wartości domyślne dla 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 zasada default-src ma wartość https://example.com, a nie określono dyrektywy font-src, można ładować czcionki z https://example.com i nigdzie indziej. We wcześniejszych przykładach podaliśmy tylko script-src, co oznacza, że obrazy, czcionki itp. można ładować z dowolnego źródła.

Te dyrektywy nie używają parametru default-src jako wartości zastępczej. Pamiętaj, że jeśli ich nie ustawisz, jest to samo, co zezwolenie na cokolwiek.

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

W danej aplikacji możesz zastosować tyle dyrektyw, ile uznasz za potrzebne. Wymieniaj je po prostu w nagłówku HTTP, rozdzielając dyrektywami średnikami. Pamiętaj, aby wymienić wszystkie wymagane zasoby określonego typu w pojedynczej dyrektywie. Gdy napiszesz coś w rodzaju script-src https://host1.com; script-src https://host2.com, druga dyrektywa zostanie po prostu zignorowana. Kod w podanym niżej przykładzie poprawnie określałby oba źródła jako prawidłowe:

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

Jeśli na przykład masz aplikację, która wczytuje wszystkie swoje zasoby z sieci dystrybucji treści (np. https://cdn.example.net) i wiesz, że nie potrzebujesz żadnych wtyczek ani treści w ramce, jej treść 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

Nagłówki X-WebKit-CSP i X-Content-Security-Policy pojawiają się w różnych samouczkach w internecie. W przyszłości zignoruj je. 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 dla każdej strony osobno: nagłówek HTTP musisz wysyłać razem z każdą odpowiedzią, którą chcesz chronić. Zapewnia to dużą elastyczność, ponieważ pozwala dostosować zasady do konkretnych stron pod kątem ich potrzeb. Być może jeden zestaw stron w Twojej witrynie ma przycisk +1, a inne nie: możesz zezwolić na ładowanie kodu przycisku tylko wtedy, gdy to konieczne.

Lista źródeł w każdej dyrektywie jest elastyczna. Źródła możesz określać według schematu (data:, https:) lub w szczególności od samej nazwy hosta (example.com, która pasuje do dowolnego źródła na tym hoście: dowolnego schematu lub dowolnego portu) do pełnego i jednoznacznego identyfikatora URI (https://example.com:443, który odpowiada tylko HTTPS, tylko example.com i tylko port 443). Symbole wieloznaczne są akceptowane, ale tylko jako schemat, port lub w pierwszej pozycji od lewej strony nazwy hosta: *://*.example.com:* pasuje do wszystkich subdomen example.com (ale nie samej example.com), z wykorzystaniem dowolnego schematu i dowolnego portu.

Lista źródłowa może również zawierać cztery słowa kluczowe:

  • Wyrażenie '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' zezwala na wbudowany kod JavaScript i CSS. Zajmiemy się tym bardziej szczegółowo.
  • 'unsafe-eval' dopuszcza mechanizmy zamiany tekstu na JavaScript, takie jak eval. (Zajmiemy się też).

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

Piaskownica

Jeszcze jedna dyrektywa, o której warto wspomnieć: sandbox. Różni się to nieco od poprzednich, ponieważ nakłada ograniczenia na działania, które może wykonać strona, a nie na zasoby, które może ona wczytać. Jeśli występuje dyrektywa sandbox, strona jest traktowana tak, jakby została wczytana wewnątrz elementu <iframe> z atrybutem sandbox. Może to mieć szeroki wpływ na stronę: między innymi wymusić na stronie unikalne źródło i uniemożliwić przesłanie formularza. Ten artykuł wykracza poza zakres tego artykułu, ale pełne informacje o prawidłowych atrybutach piaskownicy znajdziesz w sekcji „Piaskownica” w specyfikacji HTML5.

Metatag

Mechanizm dostarczania preferowanego przez CSP to nagłówek HTTP. Przydatne może być jednak ustawienie zasady 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 ani sandbox.

Kod wbudowany jest uznawany za szkodliwy

Powinno być jasne, że CSP opiera się na źródłach z listy dozwolonych, ponieważ jest to jednoznaczny sposób informowania przeglądarki, że ma traktować określone zbiory zasobów jako akceptowane i odrzucać pozostałe. Listy dozwolonych oparte na pochodzeniu nie eliminują jednak największego zagrożenia, jakie stwarzają ataki XSS: wstrzyknięcie skryptu. Jeśli osoba przeprowadzająca atak może wstrzyknąć tag skryptu zawierający bezpośrednio złośliwy ładunek (<script>sendMyDataToEvilDotCom();</script>), przeglądarka nie jest w stanie odróżnić go od prawidłowych tagów tego typu. CSP rozwiązuje ten problem poprzez całkowite zablokowanie wbudowanego skryptu – to jedyny sposób, aby mieć pewność.

Ta blokada obejmuje nie tylko skrypty umieszczone bezpośrednio w tagach script, ale także wbudowane moduły obsługi zdarzeń i adresy URL javascript:. Musisz przenieść zawartość tagów script do pliku zewnętrznego i zastąpić adresy URL javascript: i <a ... onclick="[JAVASCRIPT]"> odpowiednimi wywołaniami addEventListener(). Możesz na przykład przepisać z adresu:

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

Przepisany kod ma wiele zalet wykraczających poza dobrą współpracę z CSP. To już sprawdzona metoda, niezależnie od tego, w jaki sposób korzystasz z tego standardu. Wbudowany kod JavaScript łączy strukturę i działanie w sposób, który nie powinien być. Zasoby zewnętrzne są łatwiejsze do buforowania przez przeglądarki, są bardziej zrozumiałe dla programistów oraz usprawniają kompilację i minifikację. Łatwiej będzie Ci pisać kod, jeśli przeniesiesz go do zasobów zewnętrznych.

Styl wbudowany jest traktowany tak samo: zarówno atrybut style, jak i tagi style należy skonsolidować w zewnętrznych arkuszach stylów, aby chronić przed różnymi zaskakująco skutecznymi metodami wydobywania danych dostępnymi w 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ć liczby jednorazowej lub skrótu (patrz poniżej), ale jest to całkowicie zabronione. Zablokowanie skryptu wbudowanego to największa korzyść z bezpieczeństwa zapewnianych przez CSP. Zablokowanie wbudowanego stylu sprawia, że Twoja aplikacja jest wzmacniana. Gdy przesuniesz cały kod poza szkło, spróbuj się postarać, by wszystko działało prawidłowo, ale warto się zastanowić nad tym kompromisem.

Jeśli musisz go używać,

CSP na poziomie 2 zapewnia zgodność wsteczną skryptów wbudowanych, umożliwiając dodawanie określonych skryptów wbudowanych do listy dozwolonych za pomocą kryptograficznej liczby jednorazowej (numeru użytego raz) lub skrótu. Może to być niewygodne, ale zawsze przydatne.

Aby użyć liczby jednorazowej, nadaj tagowi skryptu atrybut liczba jednorazowa. 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 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ą w ten sam sposób. Zamiast dodawać kod do tagu skryptu, utwórz skrót SHA samego skryptu i dodaj go do dyrektywy script-src. Załóżmy na przykład, że Twoja strona zawiera taki ciąg:

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

Zasady będą obejmować następujące dane:

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

W tym miejscu należy pamiętać o kilku kwestiach. Prefiks sha*- określa algorytm, który generuje hasz. W powyższym przykładzie użyto kolumny sha256-. CSP obsługuje też sha384- i sha512-. Podczas generowania skrótu nie uwzględniaj tagów <script>. Również wielkość liter i znaki mają znaczenie, w tym odstępy na początku i na końcu ciągu znaków.

Wyszukiwanie w Google dotyczące generowania haszów SHA prowadzi do rozwiązań w dowolnej liczbie języków. Jeśli korzystasz z Chrome w wersji 40 lub nowszej, możesz otworzyć Narzędzia deweloperskie i ponownie załadować stronę. Karta Console (Konsola) będzie zawierać komunikaty o błędach z poprawnym haszem sha256 dla każdego z wbudowanych skryptów.

Oceń też

Nawet jeśli haker nie może bezpośrednio wstrzyknąć skryptu, może podstępem nakłonić aplikację do przekonwertowania bezwładnego tekstu na wykonywalny kod JavaScript i wykonania go w jego imieniu. eval(), nowa funkcja Functions() , setTimeout([string], ...) i setInterval([string], ...) to wektory, za pomocą których wstrzykiwany tekst może zakończyć się nieoczekiwanym szkodliwym działaniem. Domyślna reakcja CSP na to ryzyko to całkowite zablokowanie wszystkich tych wektorów.

Ma to więcej niż kilka wpływu na sposób tworzenia aplikacji:

  • Musisz przeanalizować kod JSON za pomocą wbudowanego komponentu JSON.parse, zamiast polegać na eval. Natywne operacje JSON są dostępne w każdej przeglądarce od IE8 i są całkowicie bezpieczne.
  • Przepisz wszystkie wykonywane obecnie wywołania setTimeout lub setInterval za pomocą funkcji w tekście, a nie ciągów znaków. Na przykład:
setTimeout("document.querySelector('a').style.display = 'none';", 10);

lepiej zapisać w ten sposób:

setTimeout(function () {
  document.querySelector('a').style.display = 'none';
}, 10);
  • Unikaj tworzenia szablonów wbudowanych w czasie działania: wiele bibliotek szablonów bezpłatnie korzysta z elementu new Function(), aby przyspieszyć generowanie szablonów w czasie działania. Jest to sprytne zastosowanie dynamicznego programowania, ale wiąże się z ryzykiem oceny złośliwego tekstu. Niektóre platformy od razu obsługują CSP. W przypadku braku eval korzystają one z rozbudowanego parsera. Dobrym przykładem jest dyrektywa ng-csp w AngularJS.

Lepszym rozwiązaniem będzie jednak język szablonów oferujący wstępną kompilację (np. tak jest w przypadku kierownicy). Wstępne kompilowanie szablonów może sprawić, że obsługa użytkownika będzie jeszcze szybsza niż najszybsza implementacja w środowisku wykonawczym. Jest też bezpieczniejsza. Jeśli klasyfikacja e-mail i jej bracia z zamiany tekstu 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 odradzamy taki sposób. Blokowanie możliwości wykonywania ciągów znaków znacznie utrudnia atakującym wykonanie nieautoryzowanego kodu w Twojej witrynie.

Raportowanie

Możliwość blokowania niezaufanych zasobów po stronie klienta jest dla użytkowników niezwykle przydatna, ale dobrze byłoby przesłać powiadomienie z powrotem na serwer, co pozwoli na wykrywanie i eliminowanie błędów, które umożliwiają wstrzykiwanie złośliwego oprogramowania. W związku z tym poinstruuj przeglądarkę, aby POST zgłaszała naruszenia 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 te 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 on wiele informacji, które pomagają w ustaleniu konkretnej przyczyny naruszenia zasad, w tym strony, na której doszło do naruszenia (document-uri), strony odsyłającej do tej strony (uwaga: w przeciwieństwie do pola nagłówka HTTP klucz nie zawiera literówki), zasobu, który naruszył zasady strony (blocked-uri), dyrektywy, która naruszyła (violated-directive), i pełnej zasady strony (original-policy).

Tylko raportowanie

Jeśli dopiero zaczynasz korzystać z CSP, przed udostępnieniem użytkownikom drakońskich zasad warto ocenić obecny stan swojej aplikacji. Na początek możesz poprosić przeglądarkę o monitorowanie zasad i 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 będzie blokować zasobów z ograniczeniami, ale będzie wysyłać raporty o naruszeniach do wskazanej przez Ciebie lokalizacji. Możesz nawet wysłać oba nagłówki, egzekwując jedną zasadę, a drugą monitorując inną. To świetny sposób na ocenę wpływu zmian w CSP w Twojej aplikacji: włącz raportowanie dla nowej zasady, monitoruj zgłoszenia o naruszeniach i napraw wszelkie błędy. Gdy efekty będą zadowalające, zacznij egzekwować nową zasadę.

Rzeczywiste wykorzystanie w świecie

Standard CSP 1 jest dość obsługiwany w Chrome, Safari i Firefoksie, ale w przeglądarce IE 10 ma bardzo ograniczoną obsługę. Szczegóły znajdziesz na stronie caniuse.com. CSP poziomu 2 jest dostępny w Chrome od wersji 40. W dużych witrynach, takich jak Twitter czy Facebook, umieszczono nagłówek (warto przeczytać studium przypadku Twittera), a standard jest już gotowy do wdrożenia we własnych witrynach.

Pierwszym krokiem do stworzenia zasady dla aplikacji jest ocena rzeczywiście wczytywanych zasobów. Gdy już wiesz, jak elementy w Twojej aplikacji są zorganizowane, skonfiguruj zasady oparte na tych wymaganiach. Przyjrzyjmy się kilku typowym przypadkom użycia i ustalmy, jak możemy je najlepiej wspierać w obrębie bezpieczeństwa CSP.

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

  • Przycisk +1 Google zawiera skrypt z https://apis.google.com oraz <iframe> z https://plusone.google.com. Aby umieścić przycisk, musisz mieć zasadę obejmującą oba te źródła. Minimalna zasada to script-src https://apis.google.com; child-src https://plusone.google.com. Musisz też upewnić się, że fragment kodu JavaScript udostępniony przez Google został wyciągnięty z zewnętrznego pliku JavaScript. Jeśli zdarzyło Ci się stosować zasadę opartą na poziomie 1, która korzystała z tej usługi: frame-src Poziom 2 wymagał zmiany jej na child-src. Nie jest to już konieczne w przypadku CSP poziomu 3.

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

  • 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 względny URL; edytuj kod, aby określić protokół HTTPS podczas kopiowania i wklejania lokalnie). script-src https://platform.twitter.com; child-src https://platform.twitter.com będzie gotowy, jeśli tylko przeniesiesz udostępniony przez Twittera fragment kodu JavaScript do zewnętrznego pliku JavaScript.

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

Dodanie wielu widżetów jest proste: wystarczy połączyć dyrektywy dotyczące zasad, pamiętając, aby scalić wszystkie zasoby danego typu w jedną dyrektywę. Jeśli chcesz dodać wszystkie 3 widżety do mediów społecznościowych, zasada będzie 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 tylko te zasoby napisane przez Ciebie mogą zostać wczytane. W takim przypadku zacznij od zasady domyślnej, która całkowicie blokuje wszystko (default-src 'none'), a potem utwórz kolejne.

Załóżmy, że bank wczytuje wszystkie obrazy, style i skrypty z sieci CDN w domenie https://cdn.mybank.net, a potem łączy się przez XHR z kontem https://api.mybank.com/, aby pobierać różne dane. Ramki są używane, ale tylko w przypadku stron lokalnych w witrynie (a nie stron zewnętrznych). Na stronie nie ma Flasha, czcionek ani dodatków. Najbardziej restrykcyjny nagłówek CSP, który 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 na weselu chce mieć pewność, że wszystkie zasoby są ładowane tylko przez bezpieczne kanały, ale nie pisze zbyt dużo kodu. Przepisywanie dużych fragmentów oprogramowania forum zewnętrznego, które jest pełne wbudowanych skryptów i stylów, wykracza poza jego możliwości. W tym przypadku powinna zostać zastosowana ta zasada:

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

Mimo że zasada https: jest określona w zasadzie default-src, skrypt i dyrektywy dotyczące stylu nie dziedziczą tego źródła automatycznie. Każda dyrektywa całkowicie zastępuje ustawienie domyślne określonego typu zasobu.

Przyszłość

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

Jeśli chcesz dyskutować o nadchodzących funkcjach, przejrzyj archiwa list adresowych public-webappsec@ lub dołącz do nas.

Prześlij opinię