Як працює Політика безпеки вмісту?


248

Я отримую купу помилок у консолі розробника:

Відмовилися оцінювати рядок

Відмовилися виконувати вбудований скрипт, оскільки він порушує наступну директиву щодо політики безпеки вмісту

Відмовилися завантажити сценарій

Відмовилися завантажити таблицю стилів

Про що це все? Як працює Політика безпеки вмісту? Як використовувати Content-Security-Policyзаголовок HTTP?

Зокрема, як ...

  1. ... дозволити кілька джерел?
  2. ... використовувати різні директиви?
  3. ... використовувати декілька директив?
  4. ... обробляти порти?
  5. ... обробляти різні протоколи?
  6. ... дозволити file://протокол?
  7. ... використовувати вбудовані стилі, сценарії та теги <style>і <script>?
  8. ... дозволити eval()?

І, нарешті:

  1. Що саме 'self'означає?

Відповіді:


557

Content-Security-PolicyМета-тег дозволяє зменшити ризик XSS атак, дозволяючи визначити , де ресурси можуть бути завантажені з, запобігаючи браузери від завантаження даних з будь-яких інших місць. Це ускладнює зловмиснику введення зловмисного коду на ваш сайт.

Я вдарився головою об цегляну стіну, намагаючись зрозуміти, чому я отримую помилки CSP одна за одною, і, схоже, немає чітких чітких чітких інструкцій про те, як це працює. Тож ось моя спроба пояснити деякі моменти CSP коротко, в основному концентруючись на речах, які мені було важко вирішити.

Для стислості я не буду писати повний тег у кожному зразку. Натомість я покажу лише contentвластивість, тому зразок, який говорить, content="default-src 'self'"означає це:

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

1. Як дозволити кілька джерел?

Ви можете просто перерахувати джерела після директиви як список, розділений пробілом:

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

Зауважте, що немає жодних лапок навколо інших параметрів, крім спеціальних , наприклад 'self'. Крім того, :після директиви немає двокрапки ( ). Просто директива, а потім розділений пробілом список параметрів.

Все, що нижче вказаних параметрів, дозволено неявно. Це означає, що у наведеному вище прикладі це були б дійсні джерела:

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

Вони, однак, не відповідають дійсності:

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

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

2. Як використовувати різні директиви, що вони роблять?

Найпоширеніші директиви:

  • default-src політика за замовчуванням для завантаження javascript, зображень, CSS, шрифтів, запитів AJAX тощо
  • script-src визначає дійсні джерела для файлів javascript
  • style-src визначає дійсні джерела для файлів css
  • img-src визначає дійсні джерела для зображень
  • connect-srcвизначає дійсні цілі для XMLHttpRequest (AJAX), WebSockets або EventSource. Якщо буде зроблено спробу з'єднання з хостом, який тут не дозволений, браузер буде імітувати 400помилку

Є й інші, але це ті, які вам, швидше за все, знадобляться.

3. Як використовувати декілька директив?

Ви визначаєте всі свої директиви всередині одного метатега, припиняючи їх крапкою з комою ( ;):

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

4. Як обробляти порти?

Все, окрім портів за замовчуванням, потрібно дозволити явно, додавши номер порту чи зірочку після дозволеного домену:

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

Вищезазначене призведе до:

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

Як я вже згадував, ви також можете використовувати зірочку, щоб явно дозволити всі порти:

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

5. Як поводитися з різними протоколами?

За замовчуванням дозволені лише стандартні протоколи. Наприклад, щоб дозволити WebSockets, ws://вам доведеться це дозволити:

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

6. Як дозволити файловий протокол file://?

Якщо ви спробуєте визначити це як таке, воно не вийде. Замість цього ви дозволите це за допомогою filesystemпараметра:

content="default-src filesystem"

7. Як використовувати вбудовані сценарії та визначення стилів?

Якщо явно не дозволено, ви не можете використовувати визначення стилів вбудованого стилю, код всередині <script>тегів або властивості тегів, як-от onclick. Ви дозволяєте їм так:

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

Вам також доведеться чітко дозволити закодовані вбудовані зображення base64:

content="img-src data:"

8. Як дозволити eval()?

Я впевнений, що багато людей скажуть, що ви цього не зробите, оскільки "eval - це зло" і, швидше за все, це причина для майбутнього кінця світу. Ці люди помиляються. Звичайно, ви можете однозначно пробити основні дірки в безпеці вашого сайту за допомогою eval, але це абсолютно дійсні випадки використання. Ви просто повинні бути розумними щодо його використання. Ви дозволяєте це так:

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

9. Що саме 'self'означає?

Ви можете мати 'self'на увазі localhost, локальну файлову систему або щось на тому ж хості. Це не означає жодного з них. Це означає джерела, які мають ту саму схему (протокол), той самий хост і той же порт, що і файл, в якому визначена політика щодо вмісту. Обслуговуєте свій сайт через HTTP? Тоді для вас немає https, якщо ви не встановите це чітко.

Я використовував 'self'у більшості прикладів, оскільки зазвичай має сенс включати його, але це аж ніяк не обов'язково. Залиште це, якщо він вам не потрібен.

Але зачекай хвилинку! Чи не можу я просто користуватися цим content="default-src *"і закінчуватися?

Ні. Крім очевидних вразливих місць безпеки, це також не працюватиме так, як ви очікували. Хоча деякі документи стверджують, що це дозволяє все, це неправда. Це не дозволяє вбудовувати чи оцінювати, тому, щоб дійсно зробити ваш сайт надзвичайно вразливим, ви використовуєте це:

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

... але я вірю, що ви цього не зробите.

Подальше читання:

http://content-security-policy.com

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


6
Чудовий пост. Одне: не очевидно, що відбувається, коли вказано кілька директив; чи мають параметри style-src у прикладі 3 перевагу над типовим src? тощо ...
track0

30
Отже, щоб дозволити всьому все, про що буде вміст,default-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;
Арнольд Роа

8
Важливо знати, що content="default-src * 'unsafe-inline' 'unsafe-eval'"необхідно, щоб деякі програми Angular працювали.
flanger001

2
@Mahesh Цей "блог" переповнений публікаціями, скопійованими з SO. Навряд чи так багато користувачів SO копіюватимуть вміст від невідомого блогера - я знаю, що я цього не зробив.
Шлаус

2
Коротка примітка щодо connect-srcта шляхи: косої косої риси є обов'язковим, якщо ви хочете включити цілий підпуть. Напр .: файл http://foo.com/files/bar.txtбуде заблокований, якщо джерело є http://foo.com/files, але подається, коли він єhttp://foo.com/files/
Griddo

15

APACHE2 MOD_HEADERS

Ви також можете активувати Apache2 mod_headers, у Fedora це вже включено за замовчуванням, якщо ви використовуєте Ubuntu / Debian включити його так:

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

У Ubuntu / Debian ви можете налаштувати заголовки у файлі /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;"

Примітка. Це нижня частина файлу, лише останні 3 записи - це настройки CSP.

Перший параметр - директива, другий - джерела, що підлягають переліку білого списку. Я додав аналітику Google і рекламний сервер, який у вас може бути. Крім того, я з’ясував, що якщо у вас є псевдоніми, наприклад, www.example.com та example.com, налаштовані в Apache2, вам слід також додати їх до білого списку.

Вбудований код вважається шкідливим, вам слід уникати цього. Скопіюйте всі javascripts та css в окремі файли та додайте їх у білий список.

Поки ви перебуваєте на цьому, ви можете поглянути на інші параметри заголовка та встановити mod_security

Подальше читання:

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

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


2
Мені вдалося додати ті самі директиви до мого файлу .htaccess, оскільки я не маю можливості редагувати конфігурації Apache на своєму спільному хості. Я знайшов чудові інструменти для коригування цих параметрів у report-uri.io/home/tools .
Майкл МакГінніс

Чи є спосіб вирішити цю проблему за допомогою tomcat 7. Я спробував додати фільтри і не працював.
Ельшан

0

Не забувайте про шрифт-src, він працює так само, як і будь-який інший, але якщо ви використовуєте шрифти, завантажені з іншого походження, обов'язково додайте його до метатега

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.