Model zabezpieczeń w internecie opiera się na zasadzie takiego samego pochodzenia. 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 internetu, co zapewnia deweloperom bezpieczną piaskownicę do tworzenia i testowania. W teorii to świetne rozwiązanie. W praktyce atakujący znaleźli sprytne sposoby na obejście 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 legalną częścią pochodzenia zabezpieczeń tej strony. Poradnik dotyczący XSS to stary, ale reprezentatywny przegląd metod, których może użyć atakujący, aby naruszyć to zaufanie, wstrzykując szkodliwy kod. Jeśli atakujący wstrzyknie jakikolwiek kod, gra jest praktycznie skończona: dane sesji użytkownika są zagrożone, a informacje, które powinny być utrzymywane w tajemnicy, są wykradane przez złoczyńców. 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.
- dowiedzieć się, jakie słowa kluczowe są przez nie używane;
- Kod wbudowany i
eval()
są uznawane za szkodliwe. - Zgłaszaj naruszenia zasad na serwerze przed ich egzekwowaniem.
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 osoby trzecie w złośliwy sposób. Na przykład przycisk Google +1 na dole tej strony wczytuje i wykonuje kod z poziomu 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 z siebie 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 żąda strona, 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ą mógłby 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
To 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 oraz z źródła bieżącej strony.
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 sukcesu zobaczy komunikat o błędzie.
Zasady dotyczą wielu różnych zasobów
Chociaż zasoby skryptów stanowią największe zagrożenie dla bezpieczeństwa, CSP zapewnia bogaty zestaw dyrektyw zasad, które umożliwiają dość szczegółową kontrolę nad zasobami, które mogą być wczytywane na stronie. Widziałeś już script-src
, więc powinieneś rozumieć tę koncepcję.
Omówmy szybko pozostałe dyrektywy dotyczące zasobów. Lista poniżej przedstawia stan dyrektyw na poziomie 2. Specyfikacja na poziomie 3 została opublikowana, ale jest w dużej mierze niezrealizowana w głównych przeglądarkach.
base-uri
ogranicza adresy URL, które mogą się pojawiać w elemencie<base>
na stronie.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 liczbę źródeł, 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 do przesłania 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>
i<applet>
. Nie można jej używać w tagach<meta>
. Dotyczy ona tylko 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ślnachild-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 będzie wysyłać raporty w przypadku naruszenia zasad bezpieczeństwa treści. Tej dyrektywy nie można używać w tagach<meta>
.style-src
to odpowiednikscript-src
dla arkuszy stylów.upgrade-insecure-requests
nakazuje klientom użytkownika przepisywanie schematów adresów URL, zastępując HTTP przez HTTPS. Ta reguła dotyczy witryn z dużą liczbą starych adresów URL, które trzeba przepisać.worker-src
to dyrektywa CSP poziomu 3, która ogranicza adresy URL, które mogą być wczytywane jako worker, worker współdzielony lub worker usługi. Od lipca 2017 roku ta dyrektywa ma ograniczone wdrożenia.
Domyślnie dyrektywy są szeroko otwarte. Jeśli nie ustawisz konkretnych zasad dla dyrektywy, np. font-src
, to domyślnie będzie ona działać 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
, a nie określisz dyrektywy font-src
, możesz wczytywać czcionki tylko z https://example.com
. W poprzednich przykładach podano tylko script-src
, co oznacza, że obrazy, czcionki itp. mogą być wczytywane z dowolnego źródła.
W tych dyrektywach nie jest używany znak default-src
jako wartość domyślna. 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ć 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
znajdziesz w różnych samouczkach w internecie. Od tej pory ignoruj nagłówki z prefiksem. Nowoczesne przeglądarki (z wyjątkiem IE) obsługują nagłówek Content-Security-Policy
bez prefiksu. Tego nagłówka powinieneś użyć.
Bez względu na używany nagłówek zasady są definiowane osobno dla każdej strony: musisz wysłać nagłówek HTTP razem z każdą odpowiedzią, którą chcesz chronić. Zapewnia to dużą elastyczność, ponieważ możesz dostosować zasady do konkretnych stron na podstawie ich konkretnych potrzeb. Może jeden zestaw stron w Twojej witrynie ma przycisk +1, a inne nie: możesz zezwolić na wczytywanie kodu przycisku tylko wtedy, gdy jest 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:*
pasuje do wszystkich subdomen example.com
(ale nie do samej example.com
), używając dowolnego schematu na dowolnym porcie.
Lista źródeł obsługuje też 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, np.eval
. (wrócimy do tego później).
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: na przykład może spowodować, że strona będzie miała unikalny adres, a użytkownicy nie będą mogli przesyłać 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. Aby to zrobić, użyj 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 go używać w przypadku kart frame-ancestors
, report-uri
i sandbox
.
Kod wbudowany jest uznawany za szkodliwy
Należy pamiętać, że CSP opiera się na listach dozwolonych źródeł, ponieważ jest to jednoznaczny sposób na przekazanie przeglądarce instrukcji, aby traktowała określone zestawy zasobów jako akceptowalne, a pozostałe odrzucała. Zestawienia dozwolonych adresów domenowych nie rozwiązują jednak największego zagrożenia związanego z atakami XSS, czyli wstrzykiwania kodu 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, całkowicie zakazując skryptów wbudowanych:
to jedyny sposób na pewność.
Zakaz obejmuje nie tylko skrypty osadzone bezpośrednio w tagach script
, ale też 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:
oraz <a ... onclick="[JAVASCRIPT]">
odpowiednimi wywołaniami addEventListener()
. Możesz na przykład przepisać te informacje z:
<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);
});
Zastąpiony kod ma wiele zalet, które wykraczają poza współpracę z CSP. Jest to już sprawdzona metoda niezależnie od tego, czy używasz CSP. Wstawianie kodu JavaScript w ciele elementu powoduje mieszanie struktury i zachowania w sposób, którego nie należy stosować. Zasoby zewnętrzne są łatwiejsze do załadowania do pamięci podręcznej w przeglądarce, bardziej zrozumiałe dla programistów i sprzyjające kompilacji oraz minifikacji. Lepszy kod możesz napisać, jeśli przeniesiesz go do zasobów zewnętrznych.
Styl w źródle jest traktowany w ten sam sposób: zarówno atrybut style
, jak i tagi style
powinny być konsolidowane w zewnętrznych arkuszach stylów, aby chronić przed różnymi zadziwiająco sprytnymi metodami wydobywania danych, które umożliwia CSS.
Jeśli musisz mieć skrypt i styl w źródle, możesz go 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 koniecznie musisz użyć
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ć nonce, nadaj tagowi skryptu atrybut nonce. 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ć ponownie generowane w przypadku każdego żądania strony i nie mogą być przewidywalne.
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, że na Twojej stronie znajduje się ten tekst:
<script>
alert('Hello, world.');
</script>
Zasady te powinny zawierać:
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
Należy jednak pamiętać 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 też sha384-
i sha512-
. Podczas generowania hasha 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 nowszym 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ś nieoczekiwanego. 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 funkcjieval
. Natywne operacje JSON są dostępne we wszystkich przeglądarkach od IE8 i są całkowicie bezpieczne. - Zastąp wywołania funkcji
setTimeout
lubsetInterval
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ąceval
. Przykładem jest dyrektywa ng-csp w 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 poinstruować przeglądarkę, aby POST
zgłosiła naruszenia w formacie JSON do lokalizacji określonej w instrukcji 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 rygorystycznych zasad dla użytkowników warto sprawdzić aktualny stan aplikacji.
Aby wdrożyć tę funkcję w pełni, możesz poprosić przeglądarkę o monitorowanie zasad i zgłaszanie naruszeń, ale nie egzekwowanie 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 drugą. To świetny sposób na ocenę wpływu zmian w CSP aplikacji: włącz raportowanie nowych zasad, monitoruj raporty o naruszeniu zasad i naprawiaj pojawiające się błędy. Gdy będziesz zadowolony z wyników, zacznij stosować nowe zasady.
Praktyczne zastosowanie
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ż zarysowany obraz 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 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>
zhttps://plusone.google.com
. Aby osadzić przycisk, musisz mieć zasadę, która obejmuje oba te źródła. Minimalne zasady toscript-src https://apis.google.com; child-src https://plusone.google.com
. Musisz też zadbać o to, aby fragment kodu JavaScript udostępniony przez Google został wyodrębniony do zewnętrznego pliku JavaScript. Jeśli masz zasadę na poziomie 1, która używa wartościframe-src
, na poziomie 2 musisz ją zmienić nachild-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 odizolowana od reszty witryny. Do prawidłowego działania wymaga dyrektywychild-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.script-src https://platform.twitter.com; child-src https://platform.twitter.com
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 stronę banku i chcesz mieć pewność, że wczytywane są tylko te zasoby, które zostały napisane przez Ciebie. W tym scenariuszu zacznij od domyślnej zasady, która blokuje absolutnie wszystko (default-src 'none'
), i na tej podstawie twórz kolejne zasady.
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 3: tylko SSL
Administrator forum dyskusyjnego o pierścionkach zaręczynowych 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
podano wartość https:
, dyrektywy skryptu i stylu nie dziedziczą automatycznie tego źródła. Każda dyrektywa całkowicie zastępuje domyślne ustawienia 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.