СP РАЗРЕШЕНИЯ И CONTENT SECURITY POLICY НА САЙТЕ

Время на прочтение

Content Security Policy (CSP) — это механизм безопасности веб-приложений, который используется для сокращения рисков, связанных с атаками, такими как внедрение скриптов (XSS) и выполнение нежелательного кода (инъекция). C SP позволяет веб-разработчикам указывать браузерам, из каких источников разрешено загружать ресурсы, такие как скрипты, стили, изображения, шрифты и другие элементы.

С помощью CSP можно определить набор допустимых источников для каждого типа ресурса, а браузеры будут блокировать попытки загрузки ресурсов из недопустимых источников. Например, вы можете настроить CSP таким образом, чтобы разрешить загрузку скриптов только из определенного домена или разрешить загрузку стилей только из локального файла.

Это помогает предотвратить атаки, основанные на выполнении вредоносного кода из внешних источников, а также уменьшает риски, связанные с подделкой источников, перехватом данных и другими видами атак. C SP является эффективным инструментом для укрепления безопасности веб-приложений и защиты пользователей от различных видов уязвимостей.

Содержание
  1. Что дальше?
  2. Окей, мы разобрались с тем что такое CSP, но с чего начать, а самое главное как мы будем тестировать, работает этот механизм или нет?
  3. Я попробую пошагово рассказать свой опыт настройки этого механизма, и что я для этого использовал.
  4. Мое приложение использует стек:
  5. Так же есть прямой доступ к конфигу webpack с конфигурацией сборки.
  6. Nginx Шаг 1
  7. Nginx Шаг 2
  8. Nginx Шаг 3
  9. Nginx Шаг 4
  10. Nginx Шаг 5
  11. Настройка frontend приложения
  12. Nginx Шаг 6
  13. Nginx Шаг 7
  14. Threats
  15. Mitigating cross-site scripting
  16. Смягчение атак с перехватом пакетов
  17. Использование CSP
  18. Указание вашей политики
  19. Написание политики
  20. Примеры: общие случаи использования
  21. Пример 1
  22. Пример 2
  23. Пример 3
  24. Пример 4
  25. Пример 5
  26. Проверка вашей политики
  27. Включение отчетности
  28. Синтаксис отчета о нарушении
  29. Образец протокола нарушения
  30. Совместимость с браузером
  31. Примечания о совместимости
  32. См. также
  33. Содержание
  34. Язык политики и синтаксис
  35. Примеры определений политики
  36. предок C, но A все еще
  37. Список исходных выражений
  38. Ключевые слова исходного выражения
  39. Синтаксис формальной политики
  40. Синтаксис отчета о нарушении
  41. Образец отчета о нарушении
  42. Ни один встроенный скрипт не будет выполняться
  43. Код не будет создан из строк
  44. Нет данных: URI, если это не разрешено посредством явной политики
  45. Привязки XBL должны исходить из chrome: или ресурса: URI
  46. Конфликт report-uri ценности
  47. Векторы утечки данных
  48. Процедура уточнения политики
  49. Прояснение политики
  50. Обработка ошибок синтаксического анализа
  51. Ненормативные соображения на стороне клиента
  52. Поведение HTTP-сервера
ЭЦП:  Как установить сертификат в КриптоПро

Что дальше?

Окей, мы разобрались с тем что такое CSP, но с чего начать, а самое главное как мы будем тестировать, работает этот механизм или нет?

Я попробую пошагово рассказать свой опыт настройки этого механизма, и что я для этого использовал.

Мое приложение использует стек:

Так же есть прямой доступ к конфигу webpack с конфигурацией сборки.

При локальной разработке у меня используется сервер на node.js "start": "node scripts/start.js"

Но для нашего тестирования CSP нам потребуется настраивать заголовки на сервере, и самым популярным решением является поднять локально сервер на nginx вместо нашего скрипта.

Nginx Шаг 1

В зависимости от вашей os, команды по установке и запуску nginx могут немного отличаться. Так как я использую mac os, я устанавливал nginx через brew ( https://brew.sh
)

После того как мы установили nginx, у нас есть доступ к базовой конфигурации.

Для Mac Os nginx лежит по адресу /usr/local/etc/nginx
либо /opt/homebrew/etc/nginx/nginx.conf
базовый конфиг nginx.conf

Первое что я хотел сделать — чтобы nginx, для начала, просто отдавал мою статику.

Поэтому мой базовый конфиг для локальной работы выглядел так:

   
worker_processes  1;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       3000;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }


        error_page   403 404 500 502 503 504  /index.html;

        location = / {
            root   html;
        }
    }

    include servers/*;
}  
  

В данном случае наш сервер должен отдавать статику по адресу http://localhost:3000/

Теперь можем запустить nginx командой sudo nginx

Если мы перейдем по адресу http://localhost:3000/
то должны увидеть что то вроде этого:

СP РАЗРЕШЕНИЯ И CONTENT SECURITY POLICY НА САЙТЕ

Nginx Шаг 2

Теперь нам нужно сбилдить нашу статику и положить ее в usr/local/var/www
или /opt/homebrew/var/www

В моем проекте это делается командой yarn run build

На выходе получаем папку static
, берем ее внутренности и перемещаем в usr/local/var/www

После этого перезапускаем nginx
командой sudo nginx -s stop && sudo nginx

Теперь на http://localhost:3000
мы должны увидеть наше приложение

P. S Этот шаг нужно повторять каждый раз, когда вы обновляете код своего приложения, если хотите проверить результат

Nginx Шаг 3

Далее будет не лишним настроить протокол https
, чтобы наш сайт открывался по https://localhost:3000

Для этого нам нужно сгенерировать ssl сертификат. В терминале переходим в папку, в которую сгенерируем 2 новых файла. Лично мне удобно открыть WebStorm со своим проектом, и использовать встроенный терминал.

Вводим в терминал команду openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem

После выполнения команды жмем enter чтобы скипать шаги до шага Common name
.

На этом моменте для Common name
вводим 127.0.0.1

чтобы установить сертификат в корневом хранилище сертификатов вашей ОС или в браузере, чтобы он был надежным.

В корне проекта появиться два файла cert.pem key.pem

Далее нам нужно перенести эти два файла в папку /usr/local/etc/ca-certificates
или /opt/homebrew/etc/ca-certificates

И в конфиге nginx добавить следующие поля ниже поля server_name

P. S Опять же путь до файлов может отличаться

   
ssl_certificate /usr/local/etc/ca-certificates/cert.pem;

ssl_certificate_key /usr/local/etc/ca-certificates/key.pem;  
  

Так же требуется добавить приписку ssl
для поля listen

Получиться примерно так:

   

worker_processes  1;



events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    
    keepalive_timeout  65;

    server {
        listen       3000 ssl;
        server_name  localhost;

        
        ssl_certificate /usr/local/etc/ca-certificates/cert.pem;

        
        ssl_certificate_key /usr/local/etc/ca-certificates/key.pem;

        location / {
            root   html;
            index  index.html index.htm;
        }


        error_page   403 404 500 502 503 504  /index.html;

        location = / {
            root   html;
        }
    }

    include servers/*;
}  
  

Перезапускаем nginx командой sudo nginx -s stop && sudo nginx

Теперь сайт должен открываться на https://localhost:3000

Nginx Шаг 4

По идее сейчас все готово для того чтобы внедрять политику CSP.

Для того чтобы ее настраивать нам нужно понимать как она работает.

А работает она с помощью заголовка Content-Security-Policy, мы будем описывать правила, которые браузер должен будет соблюдать, а если какое-либо действие пользователя будет не по правилам — браузер откажется это выполнять.

Настройка начинается с того, что сначала мы запрещаем все, а потом начинаем добавлять исключения.

Начнем с правила script-src
оно определяет допустимые источники JavaScript.

В nginx  добавляем заголовок со следующим значением:

add_header Content-Security-Policy "script-src 'self' 'unsafe-inline'";

В коде это выглядит так:

   

worker_processes  1;



events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    
    keepalive_timeout  65;

    server {
        listen       3000 ssl;
        server_name  localhost;

        
        ssl_certificate /usr/local/etc/ca-certificates/cert.pem;

        
        ssl_certificate_key /usr/local/etc/ca-certificates/key.pem;

        location / {
			add_header Content-Security-Policy "script-src 'self' 'unsafe-inline'";
            root   html;
            index  index.html index.htm;
        }


        error_page   403 404 500 502 503 504  /index.html;

        location = / {
            root   html;
        }
    }

    include servers/*;
}  
  

Перезапускаем nginx командой sudo nginx -s stop && sudo nginx

И перезагружаем наш сайт. Если у вас есть сторонние источники, например метрика, рекапча и тд, то вы увидите ошибку в консоли подобную этой и белую страницу

СP РАЗРЕШЕНИЯ И CONTENT SECURITY POLICY НА САЙТЕ

Это говорит нам о том, что у нас есть источник который не описан в политике csp, и поэтому браузер его не загружает, давайте добавим источник в список разрешенных.

Перезапускаем nginx командой sudo nginx -s stop && sudo nginx

Обновляем страницу и видим что ошибка пропала. По такой же схеме, у вас может быть много ошибок, и далее вам нужно просто внести ресурсы в белый список.

Nginx Шаг 5

Казалось бы мы настроили первое правило script-src
— но нет. В нашем правиле есть ключевое слово 'unsafe-inline'
который означает что мы разрешаем использование всех встроенных скриптов. Использование этого ключевого слова считается небезопасным.

Давайте попробуем удалить это ключевое слово, и посмотреть что будет:

СP РАЗРЕШЕНИЯ И CONTENT SECURITY POLICY НА САЙТЕ

Высокая вероятность того что вы получите такую ошибку выше, и скорее всего подобных ошибок будет +- около 10, а то и больше, в зависимости от того сколько встроенных скриптов вы используете.

Так что же тут случилось, откуда тут вообще взялась эта ошибка?

Так как мы отказались от ключевого слово 'unsafe-inline'
— то мы отказались и от использования встроенных скриптов. Теперь же нам нужно научиться “помечать” какие встроенные скрипты являются безопасными.

Хорошей практикой считается добавлять для наших встроенных скриптов атрибут nonce
, и указывать в нем динамический хеш, тем самым валидируя скрипты. Этот динамический хеш будет генерироваться нашим сервером nginx. Таким образом, если встроенный скрипт не будет иметь хеш, или он будет не совпадать — то nginx откажется его подгружать, тем самым мы себя обезопасим от разных атак.

Настройка хеша, включает в себя изменение кода как со стороны frontend так и со стороны nginx.

Для начала начнем со стороны frontend. В целом, описанные ниже шаги можно применить на большинство фреймворков и библиотек, так как основные настройки делаются в корневом index.js и в webpack конфиге.

Настройка frontend приложения

Сама настройка заключается в том, что мы должны добавить атрибут nonce="CSP_NONCE"
ко всем встроенным скриптам. Само значение CSP_NONCE
на самом деле может быть любым. Это значение нужно для того, чтобы бы в будущем наш nginx находил это значение в статических файлах js, html и заменял на динамический хеш.

Начнем с простого, зайдем в наш index.html файл, и добавим этот атрибут ко всем подключаемым скриптам, стилям и шрифтам. К примеру у меня есть следующие скрипт и шрифт, в которые я добавляю атрибут:

   
<link nonce="**CSP_NONCE**" rel="preconnect" href="https://fonts.googleapis.com" />

<script nonce="**CSP_NONCE**" type="text/javascript">
    window.dataLayer=window.dataLayer||[];
</script>  
  

Добавляем в наш index.html следующую запись

   <meta property="csp-nonce" content="**CSP_NONCE**" />  
  

На эту запись могут ориентироваться некоторые UI библиотеки, например Material UI

Так же добавляем в index.html следующий скрипт

   <script type="text/javascript" nonce="**CSP_NONCE**">
    window.__webpack_nonce__ = "**CSP_NONCE**";
</script>  
  

Тут мы глобально задаем новую переменную webpack_nonce
на которую будут ориентироваться некоторые скрипты и библиотеки.

Как правило в этом месте описаны настройки для различных плагинов eslint, html.

Нам нужно установить плагин html-webpack-inject-attributes-plugin

Подключить его вверху конфига:

     
  

И добавить следующую запись последним элементов массива plugins

   plugins: [
	// ...any plugins
	new HtmlWebpackInjectPlugin({
    nonce: "**CSP_NONCE**",
	}),
]  
  

Так как использую react, у меня есть скрипт scripts/build.js
, который запускается командой yarn run build
, этот файл используется для сборки приложения в production

У вас может быть точно такой же файл, либо какой то другой аналогичный скрипт. В него нужно добавить следующую запись:

   process.env.INLINE_RUNTIME_CHUNK = "false";  
  

Открываем наш корневой index.js, и в самый вверх добавляем запись:

   // eslint-disable-next-line no-undef
__webpack_nonce__ = window.__webpack_nonce__;  
  

По идее все эти шаги должны привести к тому, что каждый ваш встроенный скрипт, стиль, включая динамические, будет иметь атрибут nonce=» CSP_NONCE
» :

Nginx Шаг 6

После того как мы добавили nonce=» CSP_NONCE
» ко всем встроенным скриптам и стилям, нужно расширить конфигурацию nginx, и добавить:

Два поля в раздел location
:

sub_filter **CSP_NONCE** $request_id;

Поле sub_filter_once
указывает следует ли искать каждую строку для замены один раз.

Поле sub_filter
задает строку для замены и строку замены.

То есть мы находим строку **CSP_NONCE**
в нашей статике, и заменяем ее на значение переменной $request_id

Из заголовка удаляем строку unsafe-inline
которая разрешала нам использование всех встроенных скриптов, и добавляем 'nonce-$request_id'
и 'strict-dynamic'

'strict-dynamic'
— указывает, что доверие, явно предоставляемое скрипту, присутствующему в разметке, путем сопровождения его одноразовым значением или хэшем, должно распространяться на все скрипты, загруженные этим корневым скриптом.

Теперь наш каждый встроенный скрипт будет помечен динамических хешем, тем самым подтверждая что это наш скрипт и его можно загружать.

    

worker_processes  1;



events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    
    keepalive_timeout  65;

    server {
        listen       3000 ssl;
        server_name  localhost;

        
        ssl_certificate /usr/local/etc/ca-certificates/cert.pem;

        
        ssl_certificate_key /usr/local/etc/ca-certificates/key.pem;

        location / {
			add_header Content-Security-Policy "script-src 'self' 'nonce-$request_id' 'strict-dynamic' https://www.google.com/recaptcha/";
			sub_filter_once off;
            sub_filter **CSP_NONCE** $request_id;
            root   html;
            index  index.html index.htm;
        }


        error_page   403 404 500 502 503 504  /index.html;

        location = / {
            root   html;
        }
    }

    include servers/*;
}  
  

После перезапуска nginx, у нас должны пропасть ошибки из консоли.

Nginx Шаг 7

Теперь продолжим добавлять различные директивы, например style-src
со значением self

Перезапускаем nginx, обновляем страницу, и смотрим ошибки в консоли.

Скорее всего самые первые ошибки будут указывать на ресурсы, которых нет в white list.

Добавляем ресурс и nonce:

style-src “’self’ ‘nonce-$request_id’ https://*.example.com”

 Так же для удобства, выносим каждую директиву в переменную, и получаем:

   worker_processes  1;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       3000 ssl;
        server_name  localhost;

        ssl_certificate /opt/homebrew/etc/ca-certificates/cert.pem;

        ssl_certificate_key /opt/homebrew/etc/ca-certificates/key.pem;

        set $CSP_SCRIPT_SRC "'self' 'nonce-$request_id' 'strict-dynamic' https://www.google.com/recaptcha/";
        set $CSP_STYLE_SRC "'self' 'nonce-$request_id' https://*.example.com";

        location / {
            add_header Content-Security-Policy "script-src $CSP_SCRIPT_SRC; style-src $CSP_STYLE_SRC";
            sub_filter_once off;
            sub_filter **CSP_NONCE** $request_id;
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /index.html;
        location = / {
            root   html;
        }
    }

    include servers/*;
}  
  

По такому принципу, вы можете добавить остальные директивы.

У вас получиться примерно так:

   #user  nobody;
worker_processes  1;



events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       3000 ssl;
        server_name  localhost;

        # location of ssl certificate
        ssl_certificate /usr/local/etc/ca-certificates/cert.pem;

        # location of ssl key
        ssl_certificate_key /usr/local/etc/ca-certificates/key.pem;

        set $CSP_SCRIPT_SRC "'self' 'nonce-$request_id' 'strict-dynamic' https://www.google.com/recaptcha/";

        set $CSP_STYLE_SRC "'self' 'nonce-$request_id' https://*.example.com";

        set $CSP_CONNECT_SRC "'self' https://*.example.com";

        set $CSP_FONT_SRC "'self' https://fonts.gstatic.com/";

        set $CSP_IMG_SRC "'self'";

        set $CSP_OBJECT_SRC "'self'";

        set $CSP_BASE_URI "'self'";

        set $CSP_FRAME_SRC "'self' https://www.google.com https://mc.yandex.ru";

        set $CSP_MANIFEST_SRC "'self'";

        set $CSP_MEDIA_SRC "'self'";

        set $CSP_WORKER_SRC "'self'";

        set $CSP_FRAME_ANCESTORS "'self'";

        location / {
            add_header Content-Security-Policy "default-src 'none'; script-src $CSP_SCRIPT_SRC; style-src $CSP_STYLE_SRC; connect-src $CSP_CONNECT_SRC; font-src $CSP_FONT_SRC; img-src $CSP_IMG_SRC; object-src $CSP_OBJECT_SRC; base-uri $CSP_BASE_URI; frame-src $CSP_FRAME_SRC; manifest-src $CSP_MANIFEST_SRC; media-src $CSP_MEDIA_SRC; worker-src $CSP_WORKER_SRC; frame-ancestors $CSP_FRAME_ANCESTORS;";
            sub_filter_once off;
            sub_filter **CSP_NONCE** $request_id;
            root   html;
            index  index.html index.htm;
        }


        error_page   403 404 500 502 503 504  /index.html;

        location = / {
            root   html;
        }
    }

    include servers/*;
}  
  

В целом на этом моменте можно считать настройку CSP завершенной.

CSP is designed to be fully backward compatible (except CSP version 2 where there are some explicitly-mentioned inconsistencies in backward compatibility; more details here
section 1.1).
Browsers that don’t support it still work with servers that implement it, and vice versa: browsers that don’t support CSP ignore it, functioning as usual, defaulting to the standard same-origin policy for web content.
If the site doesn’t offer the CSP header, browsers likewise use the standard same-origin policy
.

To enable CSP, you need to configure your web server to return the Content-Security-Policy

HTTP header.
(Sometimes you may see mentions of the X-Content-Security-Policy
header, but that’s an older version and you don’t need to specify it anymore.)

Alternatively, the <meta>

element can be used to configure a policy, for example:

   
  
  default-src 'self'; img-src https://*; child-src 'none'; 
  
  

Note:
Some features, such as sending CSP violation reports, are only available when using the HTTP headers.

Threats

Mitigating cross-site scripting

A primary goal of CSP is to mitigate and report XSS attacks. Атаки X SS используют доверие браузера к содержимому, полученному с сервера.
Вредоносные сценарии выполняются браузером жертвы, поскольку браузер доверяет источнику контента, даже если он исходит не оттуда, откуда кажется.

В качестве окончательной формы защиты сайты, которые не хотят допускать использование скриптов,
Executed может глобально запретить выполнение скрипта.

Смягчение атак с перехватом пакетов

Помимо ограничения доменов, из которых можно загружать контент, сервер может указать, какие протоколы разрешено использовать;
например (в идеале с точки зрения безопасности) сервер может указать, что весь контент должен загружаться с использованием HTTPS.
Полная стратегия безопасности передачи данных включает не только применение HTTPS для передачи данных, но и пометку всех файлов cookie с помощью secure
атрибут

и обеспечение автоматического перенаправления со страниц HTTP на их аналоги HTTPS.
Сайты также могут использовать Strict-Transport-Security

HTTP-заголовок, гарантирующий, что браузеры подключаются к ним только по зашифрованному каналу.

Использование CSP

Указание вашей политики

Вы можете использовать Content-Security-Policy

HTTP-заголовок для указания вашей политики, например:

 

  

Политика представляет собой строку, содержащую директивы политики, описывающие вашу Политику безопасности контента.

Написание политики

Полный список директив политики см. на справочной странице заголовка Content-Security-Policy .
.

Примеры: общие случаи использования

В этом разделе приведены примеры некоторых общих сценариев политики безопасности.

Пример 1

  

  

Пример 2

  default-src 'self' example.com *.example.com

  

Пример 3

 

  

  • Изображения могут загружаться откуда угодно (обратите внимание на подстановочный знак «*»).
  • Медиафайлы разрешены только с сайтов example.org и example.net (а не с поддоменов этих сайтов).
  • Исполняемый сценарий разрешен только с сайта userscripts.example.com.

Пример 4

  

Сервер разрешает доступ только к документам, загружаемым специально по HTTPS через единый источник onlinebanking.example.com.

Пример 5

  default-src 'self' *.example.com; img-src *

  

Обратите внимание, что в этом примере не указан script-src

; на примере CSP,
этот сайт использует настройку, указанную default-src

директива, что означает, что скрипты могут быть загружены только с исходного сервера.

Проверка вашей политики

Чтобы упростить развертывание, CSP можно развернуть в режиме только отчетов.
Политика не применяется, но о любых нарушениях сообщается по предоставленному URI.
Кроме того, заголовок отчета можно использовать для тестирования будущей версии политики без ее фактического развертывания.

Вы можете использовать Content-Security-Policy-Report-Only

HTTP-заголовок для указания вашей политики, например:

 

  

Если оба Content-Security-Policy-Report-Only

заголовок и Content-Security-Policy

присутствуют в одном и том же ответе, обе политики соблюдаются.
Политика, указанная в Content-Security-Policy
заголовки применяются, пока Content-Security-Policy-Report-Only
политика создает отчеты, но не применяется.

Включение отчетности

По умолчанию отчеты о нарушениях не отправляются. Чтобы включить отчеты о нарушениях, необходимо указать report-to

директива политики, предоставляющая хотя бы один URI для доставки отчетов:

  default-src 'self'; report-to http://reportcollector.example.com/collector.cgi

  

Затем вам нужно настроить сервер для получения отчетов; он может хранить или обрабатывать их любым удобным для вас способом.

Синтаксис отчета о нарушении

blocked-uri
disposition

Либо "enforce"
или "report"
в зависимости от того, Content-Security-Policy-Report-Only

заголовок или Content-Security-Policy
используется заголовок.

document-uri

URI документа, в котором произошло нарушение.

effective-directive

Директива, исполнение которой привело к нарушению.
Некоторые браузеры могут предоставлять разные значения, например, Chrome предоставляет style-src-elem
/ style-src-attr
, даже когда фактически исполненная директива была style-src
.

original-policy

Исходная политика, указанная в Content-Security-Policy
HTTP-заголовок.

referrer


Ссылка на документ, в котором произошло нарушение.

script-sample

Первые 40 символов встроенного скрипта, обработчика событий или стиля, вызвавшего нарушение.
Применимо только к script-src*
и style-src*
нарушений, когда они содержат 'report-sample'

status-code

Код состояния HTTP ресурса, на котором был создан экземпляр глобального объекта.

violated-directive

Директива, исполнение которой привело к нарушению. violated-directive
это историческое название effective-directive
поле и содержит то же значение.

Образец протокола нарушения

  default-src 'none'; style-src cdn.example.com; report-to /_/csp-reports

  

HTML-код signup.html
выглядит так:

 

  
      
    Sign Up
       
  
  
    Here be content.
  


  

 
   
     
     
     
     
     "default-src 'none'; style-src cdn.example.com; report-to /_/csp-reports"
     
     
     
  


  

Совместимость с браузером

Таблицы BCD загружаются только в браузере

Примечания о совместимости

См. также

Эта спецификация УСТАРЕЛА (старая и потрепанная). W3C провел стандартизацию CSP, и вы можете найти спецификацию W3C здесь .
.

Содержание

А полис
состоит из директив
, например » разрешить 'нет'
«. Каждая директива состоит из имени директивы
и значение директивы
, который представляет собой список основных элементов
или URI
, для определенных типов директив.

Когда CSP активирован для сайта, некоторые базовые ограничения

в среде браузера применяются по умолчанию
чтобы помочь обеспечить надлежащее соблюдение любой определенной политики. Эти базовые ограничения обеспечивают общие улучшения безопасности за счет ограничения типов разрешенного динамического контента: обычно любой скрипт на сайте, который преобразует текст в код (с помощью eval()
или аналогичные функции) запрещено. Подробности об усовершенствованиях можно найти в Базовых ограничениях .
раздел.

Язык политики и синтаксис

Примечание. В случае описанных выше уточнений политики можно иметь два значения report-uri; в этой ситуации копия отчета отправляется на каждый из двух URI.

Примеры определений политики

Пример 1:
Сайт хочет, чтобы весь контент поступал из его собственного домена:

 X-Content-Security-Policy: разрешить «само»
  

Пример 2:
Сайт аукциона хочет разрешить изображения из любого места, плагины контента из списка доверенных медиа-провайдеров (включая сеть распространения контента) и скрипты только со своего сервера, на котором размещен очищенный JavaScript:

 X-Content-Security-Policy: разрешить «сам»; img-источник *; \
 объект-источник media1.com media2.com *.cdn.com; \
 script-srctrustscripts.example.com
  
 X-Content-Security-Policy: разрешить *; скрипт-src 'сам'
X-Content-Security-Policy: разрешить *; скрипт-источник 'сам'; media-src 'сам';
  

Пример 4:
Сайт онлайн-платежей хочет гарантировать, что весь контент на его страницах загружается через SSL, чтобы злоумышленники не могли подслушивать запросы на небезопасный контент:

 X-Content-Security-Policy: разрешить  https://*:443 

  

разрешить
  • Общий раздел, определяющий политику безопасности для всех типов контента, которые не вызываются ни в одной из других директив. Определяет политику по умолчанию для неуказанных типов контента, за исключением предков кадров .
    , который ДОЛЖЕН быть указан как «*», если это не указано явно.
  • Пользовательские агенты НЕ ДОЛЖНЫ загружать контент из любого источника, если директива разрешения не указана явно. Это можно считать эквивалентом политики «не разрешать ничего».

      Пользовательские агенты ДОЛЖНЫ применять эту директиву для всех HTTP-запросов, не подпадающих под действие одной из более конкретных директив.

      • варианты
    • Здесь указаны параметры для изменения основного поведения CSP.

    Значение этой директивы представляет собой список токенов LDH, разделенных пробелами, каждый из которых определяет функцию, которую нужно включить или отключить:

    встроенный скрипт

  • включает встроенные скрипты и
  • javascript:

    URI

    eval-скрипт

    включает

    eval()

      функциональность скриптов, интерпретируемых браузером, и позволяет создавать код из строк с использованием

      новой функции()

    • конструктор,
    • setTimeout

    • и

      setInterval

      Пользовательские агенты ДОЛЖНЫ игнорировать любые токены, не распознаваемые CSP, и ДОЛЖНЫ отправлять нефатальное предупреждение на консоль ошибок.

    img-src

  • Указывает, какие источники действительны для изображений и значков.

    Пользовательские агенты НЕ ДОЛЖНЫ запрашивать изображения из неутвержденных источников.

    Пользовательские агенты ДОЛЖНЫ подчинять запросы изображений директиве разрешения, если img-src не указан явно.

    медиа-источник

  • Указывает, какие источники действительны для звука
    и видео
    элементы.

  • Пользовательские агенты НЕ ДОЛЖНЫ запрашивать аудио
    и видео
    элементы из неутвержденных источников.
  • Пользовательские агенты ДОЛЖНЫ подчинять аудио- и видеозапросы директиве разрешения, если media-src не указан явно.
  • источник сценария
    • Указывает, какие источники действительны для сценариев.
    • Регулирует, какие скрипты можно загружать через src=
      атрибут.
    • Пользовательские агенты НЕ ДОЛЖНЫ запрашивать сценарии из неутвержденных источников.
    • Пользовательские агенты ДОЛЖНЫ подчинять запросы сценариев директиве разрешения, если сценарий-src не указан явно.
    объект-источник
    • Указывает, какие источники действительны для объекта
      , встроить
      , и апплет
      элементы.
    • Пользовательские агенты НЕ ДОЛЖНЫ запрашивать объекты из неутвержденных источников.
    • Пользовательские агенты ДОЛЖНЫ подвергать запросы объекта, внедрения и апплета директиве разрешения, если object-src не указан явно.
    фрейм-источник
    • Указывает, какие источники действительны для кадра
      и iframe
      элементы.
    • Пользовательские агенты НЕ ДОЛЖНЫ запрашивать содержимое кадра из неутвержденных источников.
    • Пользовательские агенты ДОЛЖНЫ подвергать запросы кадров директиве разрешения, если источник кадра не указан явно.
    шрифт-источник
    • Указывает, какие источники действительны для @font-src
      CSS загружается.
    • Пользовательские агенты НЕ ДОЛЖНЫ запрашивать шрифты, полученные из неутвержденных источников, если они предназначены для использования в качестве шрифта в CSS.
    • Пользовательские агенты ДОЛЖНЫ обрабатывать запросы, вызванные @font-src
      в директиву разрешения, если шрифт-src не указан явно.
    xhr-src
    • Указывает, какие источники действительны для XMLHttpRequest
      связи.
    • Пользовательские агенты НЕ ДОЛЖНЫ заставлять XMLHttpRequests открывать запросы к источникам, не разрешенным этой директивой.
    • Пользовательские агенты ДОЛЖНЫ обрабатывать запросы, вызванные XMLHttpRequest
      в директиву разрешения, если xhr-src не указан явно.
    рамки-предки
      Указывает, какие источники действительны

      предки

        для внедрения защищенного ресурса через объект
      • ,
      • рамка
        и

      • iframe
         теги. Предком является любой HTML-документ между защищенным ресурсом и вершиной дерева фрейма окна; например, если A встраивает B, который встраивает C, то и A, и B являются 

        предками
        из C. Если A встраивает и B, и C, B равно
        , а не

        предок C, но A все еще

        .

        Если эта директива явно не указана в политике, предполагается, что она равна «*». Это отличается от других исходных директив, которые наследуют значение

    разрешить

    .
  • Все веб-страницы, являющиеся предками защищенного контента, должны быть указаны значением этой директивы. Например, если A встраивает B, который встраивает C, а C определяет предков кадра
    как «B,C», то C не отображается как подкадр.
  • Отвечает на вопрос: «На какие сайты можно встроить этот ресурс?»
  • Пользовательские агенты НЕ ДОЛЖНЫ отображать защищенный документ, если какой-либо из его предков-фреймов не разрешен этой директивой.
  • Пользовательские агенты ДОЛЖНЫ всегда отображать защищенный документ, если предки кадра не указаны явно.
  • Обратите внимание, что эта директива касается кликджекинга
    угроза, но не CSRF
    • Используя предков фреймов, можно предотвратить размещение ресурса на вредоносной веб-странице. Браузер прекратит загрузку защищенного документа, как только будет получена политика его предков и обнаружено нарушение политики.
    • Однако эта директива не препятствует отправке запроса на документ
      на сервер документа в фрейме, поскольку директивы политики принимаются браузером в ответе сервера. Чтобы предотвратить подделку межсайтовых запросов, заголовок Sec-From
      обеспечивает более надежный механизм.
  • стиль-источник
    • Указывает, какие источники действительны для таблиц стилей, связанных с внешними ссылками.
    • Пользовательские агенты ДОЛЖНЫ всегда разрешать встроенные таблицы стилей и атрибуты стиля тегов HTML.
    • Пользовательские агенты НЕ ДОЛЖНЫ запрашивать таблицы стилей из источников, не разрешенных директивой style-src.
    • Пользовательские агенты ДОЛЖНЫ подчинять запросы таблицы стилей директиве разрешения, если style-src не указан явно.
    отчет-ури
    • Указывает браузеру, куда отправлять отчет при нарушении CSP.
    • Отчет будет представлять собой объект JSON с MIME-типом application/json, отправленный через POST по указанному URI, содержащемуся в значении этой директивы.
    • Приемлемые URI отчета ДОЛЖНЫ использовать схему и порт в качестве защищенного контента, а также общедоступный суффикс .
      и наиболее общая метка DNS защищенного контента и URI отчета должны совпадать. Например, www.foo.co.uk и report.foo.co.uk, но не report.bar.co.uk. Относительные URI допустимы и разрешаются в той же схеме, хосте и порту, что и документ, обслуживаемый CSP.
    • Пользовательские агенты ДОЛЖНЫ отправлять отчеты о нарушениях на любые URI, приемлемые в этой директиве. Подробную информацию об информации, представленной в отчетах о нарушениях, можно найти в Синтаксисе отчетов о нарушениях .
      раздел.
    • Пользовательские агенты ДОЛЖНЫ игнорировать URI отчета, которые не соответствуют общедоступному суффиксу и требованиям соответствия базового хоста. Пользовательским агентам СЛЕДУЕТ регистрировать одну ошибку на консоли ошибок. Пользовательские агенты ДОЛЖНЫ затем продолжить применение CSP, как если бы URI отчета не был указан.
    • Пользовательские агенты НЕ ДОЛЖНЫ учитывать коды ответа HTTP 3xx, чтобы предотвратить утечку HTTP-заголовков между доменами.
    политика-ури
    • Указывает расположение файла, содержащего политики безопасности для защищаемого ресурса.
    • политика-ури
      ДОЛЖНО быть определено только при отсутствии других определений политики в X-Content-Security-Policy .
      HTTP-заголовок.
    • Пользовательские агенты ДОЛЖНЫ вызвать фатальную ошибку
      и ДОЛЖЕН применять политику «разрешить 'none'», если policy-uri
      определяется среди других директив в заголовке.
    • Пользовательские агенты ДОЛЖНЫ игнорировать любые URI политики другого происхождения (схема, хост или порт) из защищенного контента. Пользовательские агенты ДОЛЖНЫ разрешать относительные URI в той же схеме, хосте и порту, что и защищенный документ.

    Список исходных выражений

    Исходные выражения представляют собой комбинацию схемы и часто хоста и порта. Исходные выражения могут содержать подстановочные знаки. Примеры исходных выражений только для хоста: " *.mozilla.com
    " и " mozilla.org
    ". Интернационализированные доменные имена указываются в соответствии с их представлениями в Punycode .
    .

    данные:
    выражает поддержку всех URI данных.

    Вместо номера порта можно использовать подстановочный знак «*». Это означает, что все порты (кроме запрещенных портов
    ) действительны для источника. Примеры:

    http://foo.com:*
    Любой порт можно использовать для доступа к контенту с foo.com через http
    foo.com:*
    Любой порт может использоваться для доступа к контенту с foo.com по той же схеме, что и ресурс, защищенный CSP

    .

    Имя хоста каждого исходного выражения МОЖЕТ содержать до одного подстановочного знака (*), и это ДОЛЖНО быть крайней левой меткой DNS.

    Действует
    Выражения имен хостов с подстановочными знаками включают " *.mozilla.com
    " и " *
    ".

    Недействительно
    Выражения имени хоста с подстановочными знаками включают " www.*.com
    ", " *.mozilla.*
    " и " mozilla.*
    ".

    Подстановочный знак (*) соответствует нулю или более меткам DNS
    . Все " d.c.b.a
    ", " c.b.a
    ", и" б.а
    "соответствует выражению" *.b.a
    ".

    Ключевые слова исходного выражения

    Вместо выражений источника эти ключевые слова можно использовать для указания классов источников.

    'нет'
    Относится к пустому набору (нет допустимых хостов)
    'сам'
    Относится к источнику, обслуживающему защищенный контент, включая схему, хост и порт.

    Синтаксис формальной политики

       ::= ";"
    
      ::= разрешить 
    
      ::=  | ";"
    
      ::= " "
     | "options" 
     | " "<URI (  RFC 2396 
    )>
     | " "
    
      ::= 
    
      ::= 
     | 
    
     ::= 
     | "eval-script" 
     | "inline-script" 
     |  
    
      ::= "img-src"
     | "медиа-источник"
     | "стиль-источник"
     | "объект-источник"
     | "кадр-источник"
     | "шрифт-источник"
     | "скрипт-источник"
     | "xhr-источник"
     | "рамки-предки"
    
      ::= "report-uri"
     | "политика-ури"
    
      ::= 
     | "'никто'"
    
      ::= 
     | " "
    
      ::= "'self'"
     | 
     
      ::= 
     | ":"
     | ":/"
     | "://"
    
      ::= 
    
      ::= 
     | 
    
      ::= "*"
     | 
     | "."
    
      ::= 
     | ":*"
     | ":"
    
      ::= 
     | 
    
      ::= 
     | 
    
      ::=  |  | "-"
    
      ::=  |  | "+" | "." | "-"
    
      ::=  | 
     | " " | "+" | "." | "-" | "_"
     | "'" | """ | "[" | "]" | "\" | "|"
     | "/" | "?" | "{" | "}" | "=" | "+"
     | "`" | "~" | "!" | "@" | "#" | "$"
     | "%" | "^" | "&" | "*" | "(" | ")"
     
      ::= "a"|"b"|"c"|"d"|"e"|"f"|"g"|"h"|"i"
     |"j"|"k"|"l"|"m"|"n"|"o"|"p"|"q"|"r"
     |"s"|"t"|"u"|"v"|"w"|"x"|"y"|"z"
     |"А"|"Б"|"С"|"D"|"Е"|"F"|"G"|"H"|"I"
     |"J"|"K"|"L"|"M"|"N"|"O"|"P"|"Q"|"R"
     |"S"|"T"|"U"|"V"|"W"|"X"|"Y"|"Z"
    
      ::=  | 
    
      ::= "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"0"
    
      ::= ""
      

    Синтаксис отчета о нарушении

    запрос
    Строка HTTP-запроса ресурса, политика которого нарушена (включая метод, ресурс, путь, версию HTTP)
    заголовки запросов
    Заголовки HTTP-запроса, отправленные с запросом (выше) на контент, защищенный CSP
    заблокирован-ури
    URI ресурса, загрузка которого была заблокирована из-за нарушения политики
    нарушил директиву
    Раздел политики, который был нарушен (например, « script-src *.mozilla.org
    ").
    исходная политика
    Исходная политика, содержащаяся в HTTP-заголовке X-Content-Security-Policy (или, если заголовков было несколько, список политик, разделенных запятыми)

    Формат JSON отчета о нарушении:

     {
     csp-отчет: {
     запрос: «GET /index.html HTTP/1.1»,
     request-headers: "Хост: example.com
     Пользователь-Агент: .
     .",
     заблокированный-uri: ".",
     нарушенная директива: "."
     }
    }
      

    MIME-тип передаваемого отчета будет установлен на application/json
    .

    Образец отчета о нарушении

     {
     "csp-отчет":
     {
     "request": "GET  http://index.html 
     HTTP/1.1",
     "request-headers": "Хост: example.com
     Пользовательский агент: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.3a5pre) Gecko/20100601 Minefield/3.7a5pre
     Принять: text/html,application/xhtml+xml,application/xml;q=0,9,*/*;q=0,8
     Accept-Language: en-us,en;q=0.5
     Принять-кодирование: gzip, deflate
     Accept-Charset: ISO-8859-1,utf-8;q=0,7,*;q=0,7
     Поддержание в живых: 115
     Соединение: поддержание активности",
     "blocked-uri": "http://evil.com/some_image.png",
     "violated-directive": "img-src 'self'",
     "original-policy": "allow 'none'; img-src *; разрешить 'self'; img-src 'self'"
     }
    }
      

    Ни один встроенный скрипт не будет выполняться



    Код не будет создан из строк



    Нет данных: URI, если это не разрешено посредством явной политики



    Привязки XBL должны исходить из chrome: или ресурса: URI


    Привязки XBL, загруженные через любой протокол, кроме chrome: или ресурса:

    Привязки XBL, загруженные через протоколы chrome: или resources:

      Ограничения на policy-uri и report-uri

    • Пользовательские агенты ДОЛЖНЫ выдать фатальную ошибку И вернуться к политике «разрешить «нет»», когда:

      анализ значения директивы policy-uri, ссылающегося на URI на другом хосте из защищенного документа.

    • получение HTTP-ответа policy-uri, обслуживаемого с Content-Type, отличным от text/x-content-security-policy
    • Пользовательские агенты ДОЛЖНЫ выдавать нефатальное предупреждение И игнорировать:
      • любые значения директивы report-uri, которые ссылаются на URI с открытым суффиксом, отличным от защищенного документа
      • любые значения директивы report-uri, которые относятся к базовому хосту, а не к защищенному документу
    • Соблюдение конфиденциальности:
      Отчет, отправленный в report-uri, содержит потенциально конфиденциальную информацию, включая значения файлов cookie и параметры строки запроса. Эта информация предназначена только для защищенного сайта в целях отладки и т.п. Злоумышленнику не должно быть разрешено украсть информацию отчета путем внедрения report-uri вместе с произвольной политикой, которая может быть нарушена.

      определяют R 1
      ≡ все URI, принятые первым CSP HTTP-заголовка

      определяют R 2
      ≡ все URI, принимаемые вторым CSP HTTP-заголовка

      е
      — это набор всех URI, принятых пересекающимся CSP)

       пересечение(A, B, C, D) = пересечение(A, пересечение(B, пересечение(C,D)))
        

      Пример: если присутствуют два заголовка политики, один (P 1
      ) может разрешать скрипты из доменов A, B и C. Политика в другом заголовке (P 2
      ) может разрешать сценарии из доменов B, C и D. Политика применяется (P применяется
      ) браузером разрешает скрипты только из доменов B и C (принудительно P
      = П 1
      ∩ П 2
      ).

      Конфликт report-uri
      ценности

      Векторы утечки данных

      Поскольку в отчете передаются заголовки HTTP и вся строка запроса, возможно, что в случае компрометации отчет о нарушении может привести к утечке частной информации в произвольный URI.

      Процедура уточнения политики

      1. Политика выражена явно (см. ниже)
      2. Они пересекаются
      3. Полученная политика применяется.

      Policy Refinement Overview

      Прояснение политики

      Язык политики CSP допускает неявные значения для директив посредством использования директивы политики «allow» (по умолчанию). Чтобы сделать политику явной, язык политики «расширяется» или к отсутствующим директивам добавляются значения, указанные в директиве «allow». Это упрощает пересечение политик и их соблюдение, поскольку все директивы будут иметь явное значение.

      Making a policy explicit

      Суть объединения двух политик заключается, по сути, в создании новой политики, в которой любой действительный запрос также будет удовлетворять обеим исходным политикам
      . По сути, если один HTTP-запрос разрешен обеими политиками, он будет разрешен уточненной политикой. Если HTTP-запрос запрещен любой из указанных политик
      оно будет отвергнуто изысканной политикой.

      Intersecting two explicit CSPs

      Чтобы определить пересечение двух политик, разные директивы рассматриваются индивидуально: для каждой директивы в CSP учитываются значения в обеих указанных политиках (A и B), и только те хосты, которые разрешены в обоих значениях директив. включены в перекрёсток.

      Intersecting two directives

      Обработка ошибок синтаксического анализа

      При анализе политики CSP может возникнуть ряд различных проблем.
      Эти ошибки анализа не являются нарушением политики .
      , а любые сообщения об ошибках, вызванные ошибками синтаксического анализа, отделены от отчетов о нарушениях, которые сайты могут получать в случае нарушения политик их сайта .
      с помощью директивы report-uri.

      Непризнанная директива
      Если пользовательский агент сталкивается с нераспознанной директивой (имя не распознано), директива и ее значение пропускаются (вплоть до точки с запятой или конца заголовка, в зависимости от того, что наступит раньше), и пользовательский агент ДОЛЖЕН сообщить предупреждающее сообщение. в консоль ошибок с указанием неизвестного имени директивы.
      Нераспознанные варианты
      жетон
      Если в опциях присутствует нераспознанный токен
      значение директивы, пользовательский агент ДОЛЖЕН игнорировать его и ДОЛЖЕН сообщить предупреждающее сообщение в консоль ошибок с указанием нераспознанного токена.
      Отсутствует «разрешить»
      Если директива «allow» отсутствует, пользовательский агент ДОЛЖЕН сообщить предупреждающее сообщение в консоль ошибок и ДОЛЖЕН принять значение директивы «allow 'none'» для политики. Пользовательский агент ДОЛЖЕН применять остальную часть политики в том виде, в котором она написана (при условии, что другие ошибки политики не обнаружены).
      Синтаксическая ошибка директивы
      Когда любая известная директива содержит значение, которое нарушает синтаксис CSP
      , пользовательский агент ДОЛЖЕН сообщить предупреждающее сообщение о недопустимом синтаксисе в консоль ошибок И ДОЛЖЕН «закрыться при сбое», применяя наиболее безопасную политику «разрешить «нет»» для защищенного документа.
      Нет признанных директив
      Если в указанной политике нет распознанных директив, пользовательский агент ДОЛЖЕН сообщить в консоль ошибок предупреждающее сообщение о «недействительной политике» И ДОЛЖЕН применить политику «разрешить «нет»» к защищенному документу.
      Другие ошибки синтаксического анализа
      Любые другие ошибки синтаксического анализа, не описанные здесь, ДОЛЖНЫ привести к тому, что пользовательский агент применит политику «разрешить «нет»». Если такой случай возникнет, пользовательский агент ДОЛЖЕН сообщить об ошибке в консоль ошибок с описанием проблемы.

      Ненормативные соображения на стороне клиента

      Пользовательские сценарии 
      CSP не должен мешать работе пользовательских сценариев (таких как надстройки браузера и букмарклеты).
      Перенаправление на контент 
      Когда ресурс запрашивается по URI X[0]
      защищен политикой CSP
      , URI этого ресурса загружается только в том случае, если это разрешено CSP
      . Если URI X[0]
      разрешает HTTP-перенаправление любого типа (временное или постоянное) новый URI X[1]
      также должно быть разрешено политикой CSP
      . В результате все запросы, генерируемые документом, должны быть разрешены CSP, независимо от того, являются ли они первоначальным запросом или шагами, предпринятыми во время перенаправления.
      Будущие директивы 
      Чтобы поддерживать будущие директивы (или новые версии этой спецификации), CSP должен анализировать, но игнорировать директивы с неизвестными именами. Когда UA встречает неизвестную директиву, на консоль ошибок выводится предупреждение, и директива игнорируется.

      Чтобы упростить развертывание, CSP можно развернуть в режиме «только отчет», в котором обслуживаемая политика не применяется, но о любых нарушениях сообщается по предоставленному URI. Результатом является сценарий «что, если», где сайт может указать политику и измерить количество сбоев. Кроме того, заголовок отчета можно использовать для тестирования будущей версии политики без ее фактического развертывания.

      Режим «только отчет» включается путем указания политики в X-Content-Security-Policy-Report-Only
      заголовок вместо X-Content-Security-Policy
      заголовок.

      Если оба X-Content-Security-Policy-Report-Only
      заголовок и X-Content-Security-Policy
      присутствуют в одном и том же ответе, обе политики соблюдаются. Политика, указанная в X-Content-Security-Policy
      заголовки применяются. Все загрузки/скрипты сравниваются с указанными в X-Content-Security-Policy-Report-Only .
      заголовок, и любые нарушения генерируют отчеты, но не применяются.

      Поведение HTTP-сервера

      Размещение HTTP-заголовка

      X-Content-Security-Policy
      Заголовок HTTP-ответа МОЖЕТ присутствовать в заголовках сообщений .
      раздел HTTP-ответа сервера. В частности, оно НЕ ДОЛЖНО появляться в заголовках трейлеров .
      раздел ответа, чтобы политика могла применяться при загрузке остального содержимого страницы. Несколько X-Content-Security-Policy
      Заголовки ответов МОГУТ быть вставлены.

      ЭЦП64