script nonce что это
Улучшение сетевой безопасности с помощью Content Security Policy
Content Security Policy (CSP, политика защиты контента) — это механизм обеспечения безопасности, с помощью которого можно защищаться от атак с внедрением контента, например, межсайтового скриптинга (XSS, cross site scripting). CSP описывает безопасные источники загрузки ресурсов, устанавливает правила использования встроенных стилей, скриптов, а также динамической оценки JavaScript — например, с помощью eval. Загрузка с ресурсов, не входящих в «белый список», блокируется.
Принцип действия
CSP сейчас является кандидатом в рекомендации консорциума W3C. Для использования политики страница должна содержать HTTP-заголовок Content-Security-Policy с одной и более директивами, которые представляют собой «белые списки». В версии 1.0 поддерживаются следующие директивы:
Для всех директив действуют следующие правила:
Content-Security-Policy: default-src ‘self’;
Попытка загрузки ресурсов из иных доменов будут пресекаться браузером с выдачей уведомления в консоли:
По умолчанию CSP ограничивает исполнение JavaScript путём запрета встроенных скриптов и динамической оценки кода. В комбинации с «белыми списками» это позволяет предотвращать атаки с внедрением контента. Например, XSS-атаку с внедрением тэга инлайн-скрипта:
Загрузка внешних скриптов, которые не включены в CSP, также будет пресечена:
На данный момент в перечне URL нельзя прописывать пути ( http://cdn.example.com/path ), можно лишь перечислять сами домены ( http://cdn.example.com ). Зато поддерживаются символы подстановки, так что вы можете описать сразу все поддомены ( http://*.example.com ).
Поддержка браузерами
Получение отчётов о нарушениях CSP
Допустим, у нас есть такая CSP:
Это означает, что браузер может загружать ресурсы только с нашего собственного домена. Но нам нужно использовать сервис Google Analytics, который будет пытаться скачивать JavaScript с www.google-analytics.com. А это уже нарушение нашей CSP. В этом случае report-uri отправит запрос со следующим JSON:
Content-Security-Policy-Report-Only
Прописывание заголовка
HTTP-заголовок можно прописать прямо в конфигурационных файлах на сервере:
Также многие языки программирования и фреймворки позволяют добавлять заголовки программно (например, PHP, Node.js):
CSP в дикой природе
Давайте посмотрим, как CSP внедрён в Facebook:
А теперь вариант Twitter:
CSP Level 2
Также является кандидатом в рекомендации. В CSP Level 2 сделаны следующий нововведения:
Nonce — это генерируемая случайным образом на сервере строковая переменная. Она добавляется в CSP-заголовок:
и в тэг инлайн-скрипта:
Пример хэша, сгенерированного из строковой console.log(‘Hello, SitePoint’); с помощью алгоритма Sha256 (base64).
Во время рендеринга страницы браузер для каждого инлайн-скрипта вычисляет хэши и сравнивает с перечисленными в CSP. Приведённый выше хэш позволяет выполнить скрипт:
Content Security Policy
The web’s security model is rooted in the same-origin policy. Code from https://mybank.com should only have access to https://mybank.com ‘s data, and https://evil.example.com should certainly never be allowed access. Each origin is kept isolated from the rest of the web, giving developers a safe sandbox in which to build and play. In theory, this is perfectly brilliant. In practice, attackers have found clever ways to subvert the system.
Cross-site scripting (XSS) attacks, for example, bypass the same origin policy by tricking a site into delivering malicious code along with the intended content. This is a huge problem, as browsers trust all of the code that shows up on a page as being legitimately part of that page’s security origin. The XSS Cheat Sheet is an old but representative cross-section of the methods an attacker might use to violate this trust by injecting malicious code. If an attacker successfully injects any code at all, it’s pretty much game over: user session data is compromised and information that should be kept secret is exfiltrated to The Bad Guys. We’d obviously like to prevent that if possible.
This overview highlights a defense that can significantly reduce the risk and impact of XSS attacks in modern browsers: Content Security Policy (CSP).
Source allowlists
The issue exploited by XSS attacks is the browser’s inability to distinguish between script that’s part of your application and script that’s been maliciously injected by a third-party. For example, the Google +1 button at the bottom of this page loads and executes code from https://apis.google.com/js/plusone.js in the context of this page’s origin. We trust that code, but we can’t expect the browser to figure out on its own that code from apis.google.com is awesome, while code from apis.evil.example.com probably isn’t. The browser happily downloads and executes any code a page requests, regardless of source.
Instead of blindly trusting everything that a server delivers, CSP defines the Content-Security-Policy HTTP header, which allows you to create an allowlist of sources of trusted content, and instructs the browser to only execute or render resources from those sources. Even if an attacker can find a hole through which to inject script, the script won’t match the allowlist, and therefore won’t be executed.
Since we trust apis.google.com to deliver valid code, and we trust ourselves to do the same, let’s define a policy that only allows script to execute when it comes from one of those two sources:
Simple, right? As you probably guessed, script-src is a directive that controls a set of script-related privileges for a specific page. We’ve specified ‘self’ as one valid source of script, and https://apis.google.com as another. The browser dutifully downloads and executes JavaScript from apis.google.com over HTTPS, as well as from the current page’s origin.
With this policy defined, the browser simply throws an error instead of loading script from any other source. When a clever attacker manages to inject code into your site, they’ll run headlong into an error message rather than the success they were expecting.
Policy applies to a wide variety of resources
Let’s quickly walk through the rest of the resource directives. The list below represents the state of the directives as of level 2. A level 3 spec has been published, but is largely unimplemented in the major browsers.
The following directives don’t use default-src as a fallback. Remember that failing to set them is the same as allowing anything.
You can use as many or as few of these directives as makes sense for your specific application, simply listing each in the HTTP header, separating directives with semicolons. Make sure that you list all required resources of a specific type in a single directive. If you wrote something like script-src https://host1.com; script-src https://host2.com the second directive would simply be ignored. Something like the following would correctly specify both origins as valid:
If, for example, you have an application that loads all of its resources from a content delivery network (say, https://cdn.example.net ), and know that you don’t need any framed content or plugins, then your policy might look something like the following:
Implementation details
You will see X-WebKit-CSP and X-Content-Security-Policy headers in various tutorials on the web. Going forward, you should ignore these prefixed headers. Modern browsers (with the exception of IE) support the unprefixed Content-Security-Policy header. That’s the header you should use.
Regardless of the header you use, policy is defined on a page-by-page basis: you’ll need to send the HTTP header along with every response that you’d like to ensure is protected. This provides a lot of flexibility, as you can fine-tune the policy for specific pages based on their specific needs. Perhaps one set of pages in your site has a +1 button, while others don’t: you could allow the button code to be loaded only when necessary.
The source list also accepts four keywords:
These keywords require single-quotes. For example, script-src ‘self’ (with quotes) authorizes the execution of JavaScript from the current host; script-src self (no quotes) allows JavaScript from a server named » self » (and not from the current host), which probably isn’t what you meant.
Sandboxing
The meta tag
CSPs preferred delivery mechanism is an HTTP header. It can be useful, however, to set a policy on a page directly in the markup. Do that using a tag with an http-equiv attribute:
Inline code is considered harmful
It should be clear that CSP is based on allowlist origins, as that’s an unambiguous way of instructing the browser to treat specific sets of resources as acceptable and to reject the rest. Origin-based allowlists don’t, however, solve the biggest threat posed by XSS attacks: inline script injection. If an attacker can inject a script tag that directly contains some malicious payload ( ), the browser has no mechanism by which to distinguish it from a legitimate inline script tag. CSP solves this problem by banning inline script entirely: it’s the only way to be sure.
This ban includes not only scripts embedded directly in script tags, but also inline event handlers and javascript: URLs. You’ll need to move the content of script tags into an external file, and replace javascript: URLs and with appropriate addEventListener() calls. For example, you might rewrite the following from:
to something more like:
The rewritten code has a number of advantages above and beyond working well with CSP; it’s already best practice, regardless of your use of CSP. Inline JavaScript mixes structure and behavior in exactly the way you shouldn’t. External resources are easier for browsers to cache, more understandable for developers, and conducive to compilation and minification. You’ll write better code if you do the work to move code into external resources.
Inline style is treated in the same way: both the style attribute and style tags should be consolidated into external stylesheets to protect against a variety of surprisingly clever data exfiltration methods that CSS enables.
If you must have inline script and style, you can enable it by adding ‘unsafe-inline’ as an allowed source in a script-src or style-src directive. You can also use a nonce or a hash (see below), but you really shouldn’t. Banning inline script is the biggest security win CSP provides, and banning inline style likewise hardens your application. It’s a little bit of effort up front to ensure that things work correctly after moving all the code out-of-line, but that’s a tradeoff that’s well worth making.
CSP Level 2 offers backward compatibility for inline scripts by allowing you to add specific inline scripts to the allowlist using either a cryptographic nonce (number used once) or a hash. Although this may be cumbersome, it is useful in a pinch.
To use a nonce, give your script tag a nonce attribute. Its value must match one in the list of trusted sources. For example:
Now, add the nonce to your script-src directive appended to the nonce- keyword.
Remember that nonces must be regenerated for every page request and they must be unguessable.
Hashes work in much the same way. Instead of adding code to the script tag, create a SHA hash of the script itself and add it to the script-src directive. For example, let’s say your page contained this:
Your policy would contain this:
Content Security Policy — опасная политика
Обзор нового веб-стандарта и его фундаментальных уязвимостей
Чтобы идти в ногу со временем, браузеры внедряют все новые технологии для обеспечения безопасности пользователей. Одна из них — Content Security Policy, позволяющая разработчикам сайтов четко объяснить браузеру, на какие адреса тот может выполнять межсайтовые запросы. Однако новый веб-стандарт страдает от существенных недостатков, ставящих под сомнение его пригодность как защиты от XSS.
Content Security Policy vs Same Origin Policy
Одним из главных принципов безопасности браузеров и веба в целом является Same Origin Policy — дословно «политика единого источника» (устоявшегося термина до сих пор не существует). Ее суть заключается в проверке трех компонентов, из которых состоит origin: протокол, хост и порт. Если страница http://test1.ru/a.html пытается получить доступ к DOM страницы http://test2.ru/b.html, то у нее ничего не выйдет, так как хосты отличаются. Если бы SOP не существовал, любой сайт мог бы делать запросы на произвольные адреса и получать оттуда данные, что, как подсказывает логика, не есть хорошо. Причем страдали бы все: как пользователи, чьи персональные данные летали бы без принуждения, так и владельцы ресурсов, — в общем, в вебах творился бы полный хаос. Поэтому Same Origin Policy всех спасает и все счастливы. Однако есть одно но: что, если на страницу http://test1.ru/a.html внедрен злой скрипт с сайта http://test2.ru/, который делает плохие штуки в контексте браузера жертвы? В данном случае SOP бесполезен, ибо на
Очевидно, что такой подход не поможет защититься от случаев, когда у атакующего есть возможность внедрить код в скрипт с валидным токеном. Кроме того, есть масса вариантов обхода, о чем пойдет речь ниже.
CRLF Injection
При наличии CRLF-инъекции в заголовках ответа, то есть отсутствии фильтрации символа переноса строки, у атакующего есть возможность банального обхода CSP с помощью внедрения собственных директив. Здесь большую роль играет то, какой заголовок браузер будет использовать при наличии нескольких с одинаковым именем. Как в случае с HTTP Parameter Pollution, где одинаковые имена параметров обрабатываются по-разному на разных платформах, при внедрении еще одного заголовка Content-Security-Policy важно, где он окажется — перед первоначальным или после него, так как один браузер может взять последний заголовок, а другой — первый. Так, если браузер отдает приоритет первому и мы внедряем наш CSP перед настоящим, то обход тривиален:
Если же используется последний встреченный заголовок, то мы можем отправить его в тело страницы, отправив rnrn:
Таким образом, первоначальный заголовок попадет в содержание HTTP-ответа и не будет иметь силы.
Scriptless Attacks
Перейдем к более интересным вариантам обхода — на стороне клиента. Основная цель межсайтового скриптинга — получить некую приватную информацию пользователя, которая обычно хранится в cookie. Однако с введением таких мер защиты, как флаг httpOnly, запрещающий JS-скриптам доступ к защищаемым cookie, внедрением в браузеры XSS-фильтров (XSS Auditor в Chrome, XSSFilter в IE), собственно и самого CSP, исследователи безопасности все чаще обращают внимание на другие цели, например личные данные, различного рода токены (CSRF, oAuth, в скором будущем и script-nonce). При этом используются новые способы отправки данных на сторонние сайты, без JavaScript!
CSSAR
Еще в 2008 году Эдуардо Вела (Eduardo Vela), Дэвид Линдсей (David Lindsay) и Гарет Хейс (Gareth Heyes) представили технику чтения атрибутов тегов с помощью CSS-селекторов. На данный момент техника все так же актуальна. Если раньше она позиционировалась как обход NoScript, то сейчас ее можно использовать и для CSP. Суть CSSAR (CSS Attribute Reading) в брутфорсе значений с помощью селекторов атрибутов. Для этого на уязвимую страницу подключается CSS-файл с комбинациями выражений:
Если значение целевого инпута начинается с «a», то будет отправлен запрос на сайт атакующего через подгрузку фонового изображения, относящегося к соответствующей комбинации символов. CSS не имеет возможности указать позицию символа, поэтому для получения следующего знака необходимо сгенерировать массу вариантов вида
Поэтому конечный PoC может иметь объем в несколько сотен килобайтов.
CSSAR в действии
Вариант обхода № 4. Postcards from post-XSS world
Интересные идеи предложил Михал Залевски (Michal Zalewski). Например, имея внедрение кода перед формой, защищенной CSRF-токеном, можно вставить незакрытый тег img:
Все содержание страницы до следующей закрывающей кавычки, включая и целевой токен, после незакрытого атрибута src будет отправлено на сайт атакующего.
Использование политики безопасности контента (CSP) для защиты веб-приложений
Политика безопасности контента (Content Security Policy — CSP) — это стандарт компьютерной безопасности, обеспечивающий дополнительный уровень защиты от межсайтовых сценариев (XSS), clickjacking (перехвата кликов) и других атак с использованием кода, основанных на выполнении вредоносного контента в контексте доверенной веб-страницы. Используя подходящие директивы CSP в заголовках ответа HTTP, вы можете выборочно указать, какие источники данных должны быть разрешены в вашем веб-приложении. В этой статье описано, как использовать заголовки CSP для защиты сайтов от атак XSS и других попыток обойти политику CSP.
Зачем нам нужен CSP?
В то же время злоумышленники используют атаки с использованием cross-site scripting (XSS), чтобы обманным путем заставить веб-сайты, которым доверяет пользователь, распространять вредоносный код. Без дополнительных мер безопасности браузер выполнит весь код из доверенного источника и так как он не может определить, какой код является допустимым, то любой внедренный вредоносный код также выполнится.
Content Security Policy (CSP) — стандартизированный набор директив, которые сообщают браузеру, каким источникам контента можно доверять, а какие следует блокировать. Используя тщательно определенные политики, вы можете ограничить содержимое браузера, чтобы устранить многие распространенные векторы атак и значительно снизить риск атаки XSS. По умолчанию CSP также применяет современные стили кодирования сценариев для дополнительной безопасности.
Истории и поддержка браузеров
Content Security Policy — это рекомендация рабочей группы W3C по безопасности веб-приложений. Версия 1 (или уровень 1) была предложена в 2012 году, Level 2 — в 2014 году, а Level 3 разрабатывается с 2015 года в качестве проекта. Хотя это всего лишь рекомендации, создатели браузеров быстро внедрили CSP, начиная с Firefox 4. Подавляющее большинство современных браузеров поддерживают все или почти все директивы уровня 2, и в этой статье описывается уровень 2 CSP как фактический текущий стандарт.
Реализации CSP использовали 3 разных имени заголовка политики безопасности контента, в зависимости от браузера и времени принятия:
Использование директив CSP
CSP позволяет определять различные ограничения содержимого с помощью директив, обычно указанных в заголовках ответа HTTP. Вот пример добавления заголовков CSP на веб-сервер Apache:
При необходимости вы также можете указать желаемые директивы на уровне страницы, используя метатеги HTML. Вот пример, который устанавливает ту же политику, что и выше:
Каждая директива состоит из имени, за которым следует одно или несколько значений, и заканчивается точкой с запятой. Вы можете использовать подстановочный знак * для обобщения целых значений, поддоменов, схем и портов:
Этот заголовок позволяет использовать источники из любого субдомена example.com (но не самого example.com) по любой схеме (http, https и т.д.).
Официальная рекомендация W3C содержит полный список директив с более формальными определениями, но следующий обзор должен дать вам хорошее представление о наиболее часто используемых.
Директивы белого списка источников
Основной целью CSP является ограничение источников веб-контента, поэтому существует множество директив для указания разрешенных источников для различных типов ресурсов. Как только заголовок Content-Security-Policy указан, браузер будет отклонять любой контент из источников, которые явно не занесены в белый список, с использованием любой из приведенных ниже директив. Исходные значения разделены пробелами и могут включать как URL-адреса, так и специальные ключевые слова ‘none’, ‘self’, ‘unsafe-inline’ и ‘unsafe-eval’ (подробно обсуждается ниже). Обратите внимание, что каждая директива может быть указана только один раз в том же заголовке, а ключевые слова должны быть введены в одинарные кавычки.
Написание JavaScript и CSS с CSP
Встроенный код является основным вектором нападения, потому что он всегда выполняется в текущем контексте, поэтому его нельзя ограничивать. Когда CSP включен, он блокирует весь встроенный код по умолчанию. Это означает, что никаких встроенных стилей или встроенных сценариев не должно существовать, включая встроенные обработчики событий или javascript: URL поэтому любой новый код должен следовать передовым методам использования исключительно внешних файлов сценариев и стилей. Ключевое слово unsafe-inline разрешает встроенный код для всех или некоторых источников скриптов, но W3C рекомендует избегать его, где это возможно.
Например, страница HTML и JavaScript старого стиля может содержать код сценария как в тегах Want to click the button?
Чтобы преобразовать это в современный и совместимый с CSP стиль, поместите сценарий в отдельный файл и используйте HTML чисто декларативно, что-то вроде:
Даже после того, как типичные векторы атак были заблокированы, злоумышленники все равно могут выполнить сценарий, если используется динамически запускаемый (evaluated) код. Вот почему CSP также блокирует все функции запуска строк по умолчанию, включая eval (), new Function (), setTimeout ([string]) и аналогичные конструкции. Это приводит к нескольким изменениям в практике кодирования, включая использование JSON.parse () вместо eval() для анализа данных JSON.
Подобно unsafe-inline, вы можете использовать ключевое слово unsafe-eval, чтобы разрешить запуск кода для некоторых или всех источников. Опять же, это противоречит лучшей практике для современного кода и должно использоваться только для устаревшего кода, который не может быть реорганизован.
Nonces и Hashes чтобы разрешить встроенные скрипты
Если вам абсолютно необходимо сделать исключение для некоторого унаследованного встроенного кода, который нельзя перенести в отдельный файл, CSP предоставляет две функции, позволяющие разрешать определенные блоки кода, не прибегая к unsafe-inline. Для внесения в белый список определенного фрагмента кода вы можете использовать nonce (одноразовый) номер (уникальный одноразовый идентификатор) для тега
Чтобы разрешить этот конкретный тег сценария, используйте:
Генерация nonce номера для каждой загрузки страницы может быть проблематичным, поэтому другой подход заключается в использовании криптографического хэша самого разрешенного кода. Для этого начните с вычисления хэша SHA для всех символов внутри тега
Тогда директива, использующая хэш SHA256 этого кода:
Директивы CSP на уровне страницы
Помимо источников контента, внесенных в белый список, CSP также может налагать ограничения на действия, которые может выполнять текущая страница. Чтобы использовать эту функцию, используйте директиву sandbox, чтобы обрабатывать страницу так, как если бы она находилась внутри изолированного фрейма. Полное описание ограничений, накладываемых песочницей на страницу, см. в разделе Sandboxing в спецификации HTML5.
Чтобы повысить безопасность старых сайтов с большим количеством устаревших HTTP-страниц, вы можете использовать директиву upgrade-insecure-requests для перезаписи небезопасных URL-адресов. Это дает указание агентам пользователя изменять HTTP на HTTPS в схемах URL-адресов и может иметь неоценимое значение, если у вас все еще есть несколько URL-адресов HTTP.
Политика тестирования и мониторинг нарушений
Политика безопасности контента предоставляет мощные функциональные возможности для контроля источников контента и поведения страниц. Однако это также означает, что одна неправильно настроенная директива может сделать сайт частично или полностью недоступным для посетителей, поэтому вам нужен способ безопасного тестирования директив.
Прежде чем начать работу с директивами CSP, вы можете использовать заголовок Content-Security-Policy-Report-Only вместо Content-Security-Policy. В режиме report-only браузер будет отслеживать политику и сообщать о нарушениях, но фактически не применяет ограничения. Используйте директиву report-uri, чтобы сообщить браузеру, где он должен публиковать отчеты о нарушениях в формате JSON. Это может быть любой локальный или внешний URI, например:
Обратите внимание, что вы можете комбинировать заголовки Content-Security-Policy-Report-Only и Content-Security-Policy, чтобы протестировать новую политику, при этом применяя существующую.
После того, как политика активна, вы можете использовать ту же директиву report-uri для получения подробных отчетов о нарушениях политики. Каждый отчет JSON начинается с атрибута csp-report и выглядит примерно так:
Как видите, отчеты предоставляют информацию о каждом нарушении политики, включая заблокированный URI и нарушенную директиву. Это значительно упрощает устранение неполадок, особенно для политик с сотнями директив и значений.
Поддержка Content Security Policy в Netsparker
В течение последних нескольких лет CSP Level 2 был реализован во всех современных браузерах и широко используется в Интернете как эффективный способ снижения риска XSS. Чтобы отразить это, Netsparker проверяет наличие HTTP-заголовков Content-Security-Policy и сообщает об уязвимости «Best Practice», если они отсутствуют.
Однако простого наличия заголовка CSP недостаточно, поскольку недопустимые директивы будут игнорироваться браузерами (и, следовательно, неэффективны), в то время как небезопасные значения директив не обеспечат ожидаемый уровень защиты. Netsparker выполняет более 20 подробных проверок, чтобы убедиться, что директивы используют правильный синтаксис в сочетании со значениями, обеспечивающими эффективную безопасность. См. Vulnerability Index для получения полного списка проверок CSP, доступных в Netsparker.
Демонстрация Content Security Policy в действии
И, наконец, для практической демонстрации настройки заголовков CSP посмотрите это еженедельное интервью по безопасности с исследователем безопасности Netsparker Свеном Моргенротом. Разговаривая с Полом Асадуряном, Свен рассказывает о проблемах, которые CSP предназначен для решения, и показывает практическую демонстрацию заголовков CSP в действии.