Jak działa Polityka bezpieczeństwa treści?

248

W konsoli programisty pojawia się mnóstwo błędów:

Odmowa oceny ciągu

Odmowa wykonania skryptu wbudowanego, ponieważ narusza następującą dyrektywę dotyczącą zasad bezpieczeństwa treści

Odmowa załadowania skryptu

Odmowa załadowania arkusza stylów

O co w tym wszystkim chodzi? Jak działa Polityka bezpieczeństwa treści? Jak korzystać z Content-Security-Policynagłówka HTTP?

W szczególności, jak ...

  1. ... zezwalać na wiele źródeł?
  2. ... użyć różnych dyrektyw?
  3. ... użyć wielu dyrektyw?
  4. ... obsłużyć porty?
  5. ... obsługiwać różne protokoły?
  6. ... zezwolić na file://protokół?
  7. ... używać wbudowanych stylów, skryptów i tagów <style>oraz <script>?
  8. ... pozwolić eval()?

I w końcu:

  1. Co dokładnie 'self'znaczy?
Schlaus
źródło

Odpowiedzi:

557

Content-Security-PolicyMeta-tag pozwala zmniejszyć ryzyko XSS ataków, pozwalając na określenie, gdzie zasoby mogą być ładowane z zapobiegając przeglądarkami ładowania danych z innych lokalizacjach. Utrudnia to atakującemu wstrzyknięcie złośliwego kodu do Twojej witryny.

Uderzyłem głową w ścianę z cegły, próbując zrozumieć, dlaczego popełniam błędy CSP jeden po drugim, i wydawało się, że nie było żadnych zwięzłych, jasnych instrukcji, jak to działa. Oto moja krótka próba wyjaśnienia niektórych punktów CSP, głównie skoncentrowana na rzeczach, które trudno mi rozwiązać.

Dla zwięzłości nie napiszę pełnego tagu w każdej próbce. Zamiast tego pokażę tylko contentwłaściwość, więc przykład, który mówi, content="default-src 'self'"oznacza to:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

1. Jak zezwolić na wiele źródeł?

Możesz po prostu wymienić swoje źródła po dyrektywie jako listę oddzieloną spacjami:

content="default-src 'self' https://example.com/js/"

Zauważ, że nie ma cudzysłowu wokół parametrów innych niż specjalne , takich jak 'self'. Ponadto :po dyrektywie nie ma dwukropka ( ). Tylko dyrektywa, a następnie rozdzielona spacjami lista parametrów.

Wszystko poniżej określonych parametrów jest domyślnie dozwolone. Oznacza to, że w powyższym przykładzie byłyby to prawidłowe źródła:

https://example.com/js/file.js
https://example.com/js/subdir/anotherfile.js

Te nie byłyby jednak ważne:

http://example.com/js/file.js
^^^^ wrong protocol

https://example.com/file.js
                   ^^ above the specified path

2. Jak korzystać z różnych dyrektyw, co one robią?

Najczęstsze dyrektywy to:

  • default-src domyślne zasady ładowania javascript, obrazów, CSS, czcionek, żądań AJAX itp
  • script-src określa prawidłowe źródła plików javascript
  • style-src określa prawidłowe źródła plików css
  • img-src określa prawidłowe źródła obrazów
  • connect-srcokreśla prawidłowe cele dla XMLHttpRequest (AJAX), WebSockets lub EventSource. Jeśli nastąpi próba połączenia z hostem, który nie jest tutaj dozwolony, przeglądarka wyemituje 400błąd

Są inne, ale te są najbardziej potrzebne.

3. Jak korzystać z wielu dyrektyw?

Wszystkie dyrektywy definiuje się w ramach jednego metatagu, kończąc je średnikiem ( ;):

content="default-src 'self' https://example.com/js/; style-src 'self'"

4. Jak obsługiwać porty?

Wszystko oprócz domyślnych portów musi być jawnie dozwolone poprzez dodanie numeru portu lub gwiazdki po dozwolonej domenie:

content="default-src 'self' https://ajax.googleapis.com http://example.com:123/free/stuff/"

Powyższe spowodowałoby:

https://ajax.googleapis.com:123
                           ^^^^ Not ok, wrong port

https://ajax.googleapis.com - OK

http://example.com/free/stuff/file.js
                 ^^ Not ok, only the port 123 is allowed

http://example.com:123/free/stuff/file.js - OK

Jak wspomniałem, możesz również użyć gwiazdki, aby jawnie zezwolić na wszystkie porty:

content="default-src example.com:*"

5. Jak obsługiwać różne protokoły?

Domyślnie dozwolone są tylko standardowe protokoły. Na przykład, aby zezwolić na WebSockets ws://, musisz zezwolić na to jawnie:

content="default-src 'self'; connect-src ws:; style-src 'self'"
                                         ^^^ web sockets are now allowed on all domains and ports

6. Jak zezwolić na protokół plików file://?

Jeśli spróbujesz zdefiniować to jako takie, to nie zadziała. Zamiast tego zezwolisz na to za pomocą filesystemparametru:

content="default-src filesystem"

7. Jak korzystać ze skryptów wbudowanych i definicji stylów?

O ile nie jest to wyraźnie dozwolone, nie można używać wbudowanych definicji stylów, kodu wewnątrz <script>tagów ani właściwości tagów, takich jak onclick. Pozwalacie im tak:

content="script-src 'unsafe-inline'; style-src 'unsafe-inline'"

Musisz także wyraźnie zezwolić na wstawianie obrazów zakodowanych w standardzie base64:

content="img-src data:"

8. Jak pozwolić eval()?

Jestem pewien, że wiele osób powiedziałoby, że nie, ponieważ „ewolucja jest złem” i najprawdopodobniej przyczyną zbliżającego się końca świata. Ci ludzie by się mylili. Oczywiście, możesz zdecydowanie wykopać poważne dziury w bezpieczeństwie swojej witryny za pomocą eval, ale ma ona całkowicie uzasadnione przypadki użycia. Musisz tylko być mądrym w używaniu go. Pozwalasz na to tak:

content="script-src 'unsafe-eval'"

9. Co dokładnie 'self'oznacza?

Możesz przez to 'self'rozumieć localhost, lokalny system plików lub cokolwiek na tym samym hoście. To nic nie znaczy. Oznacza źródła, które mają ten sam schemat (protokół), ten sam host i ten sam port co plik, w którym zdefiniowana jest polityka treści. Czy udostępniasz swoją witrynę przez HTTP? Nie ma dla ciebie https, chyba że wyraźnie go zdefiniujesz.

Użyłem 'self'w większości przykładów, ponieważ zwykle ma sens włączenie go, ale w żadnym wypadku nie jest to obowiązkowe. Zostaw to, jeśli nie potrzebujesz.

Ale poczekaj chwilę! Czy nie mogę po prostu content="default-src *"z niego korzystać?

Nie. Oprócz oczywistych luk w zabezpieczeniach to również nie zadziała, jak można się spodziewać. Mimo że niektórzy doktorzy twierdzą, że na to pozwala cokolwiek, to nieprawda. Nie pozwala na wstawianie ani sprawdzanie poprawności, więc aby naprawdę, naprawdę uczynić twoją witrynę bardziej podatną na atak, możesz użyć tego:

content="default-src * 'unsafe-inline' 'unsafe-eval'"

... ale ufam, że nie.

Dalsza lektura:

http://content-security-policy.com

http://en.wikipedia.org/wiki/Content_Security_Policy

Schlaus
źródło
6
Wspaniały post. Jedno: nie jest oczywiste, co się stanie, gdy określonych zostanie wiele dyrektyw; czy ustawienia style-src w przykładzie 3 mają pierwszeństwo przed default-src? itp ...
track0
30
Tak więc, aby zezwolić na wszystko, wszystko, co byłoby treściądefault-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;
Arnold Roa
8
Ważne jest, aby wiedzieć, że content="default-src * 'unsafe-inline' 'unsafe-eval'"jest to konieczne, aby niektóre aplikacje Angular działały.
flanger001
2
@Mahesh Ten „blog” jest pełen postów skopiowanych z SO. Wydaje się mało prawdopodobne, aby tylu użytkowników SO kopiowało treści z nieznanego blogera - wiem, że nie.
Schlaus
2
Krótka uwaga dotycząca connect-srci ścieżek: końcowe ukośniki są obowiązkowe, jeśli chcesz dołączyć całą podścieżkę. Np .: plik http://foo.com/files/bar.txtzostanie zablokowany, jeśli źródło jest http://foo.com/files, ale zostanie udostępnione , gdy jesthttp://foo.com/files/
Griddo
15

APACHE2 MOD_HEADERS

Możesz także włączyć Apache2 mod_headers, na Fedorze jest już domyślnie włączony, jeśli używasz Ubuntu / Debian, włącz to w następujący sposób:

# First enable headers module for Apache2, 
# then restart the Apache2 service   
a2enmod headers
apache2 -k graceful

W Ubuntu / Debian możesz skonfigurować nagłówki w pliku /etc/apache2/conf-enabled/security.conf

#
# Setting this header will prevent MSIE from interpreting files as something
# else than declared by the content type in the HTTP headers.
# Requires mod_headers to be enabled.
# 
#Header set X-Content-Type-Options: "nosniff"

#
# Setting this header will prevent other sites from embedding pages from this
# site as frames. This defends against clickjacking attacks.
# Requires mod_headers to be enabled.
#
Header always set X-Frame-Options: "sameorigin"
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Permitted-Cross-Domain-Policies "master-only"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Pragma "no-cache"
Header always set Expires "-1"
Header always set Content-Security-Policy: "default-src 'none';"
Header always set Content-Security-Policy: "script-src 'self' www.google-analytics.com adserver.example.com www.example.com;"
Header always set Content-Security-Policy: "style-src 'self' www.example.com;"

Uwaga: To jest dolna część pliku, tylko 3 ostatnie wpisy to ustawienia CSP.

Pierwszy parametr to dyrektywa, drugi to źródła, które należy umieścić na białej liście. Dodałem Google Analytics i serwer reklam, który możesz mieć. Ponadto odkryłem, że jeśli masz aliasy, np. Www.example.com i example.com skonfigurowane w Apache2, powinieneś dodać je również do białej listy.

Kod wewnętrzny jest uważany za szkodliwy, należy go unikać. Skopiuj wszystkie javascripts i css do osobnych plików i dodaj je do białej listy.

W tym momencie możesz rzucić okiem na inne ustawienia nagłówka i zainstalować mod_security

Dalsza lektura:

https://developers.google.com/web/fundamentals/security/csp/

https://www.w3.org/TR/CSP/

Erik Hendriks
źródło
2
Mogłem dodać te same dyrektywy do mojego pliku .htaccess, ponieważ nie mam możliwości edytowania konfiguracji Apache na moim współdzielonym hoście. Znalazłem doskonałe narzędzia do dostosowania tych ustawień na report-uri.io/home/tools .
Michael McGinnis,
Czy jest jakiś sposób na rozwiązanie tego za pomocą tomcat 7. Próbowałem dodać filtry i nie działałem.
Elshan
0

Nie zapomnij o font-src, który działa tak samo jak każdy inny, ale jeśli używasz czcionek załadowanych z innego źródła - upewnij się, że dodałeś go do metatagu

Michaił Andrianow
źródło