Chrome 18+: как разрешить встроенные сценарии с политикой безопасности контента? - PullRequest
29 голосов
/ 14 декабря 2011

Chrome 18 Dev / Canary только что выпущен, и для некоторых расширений в манифесте потребуется content_security_policy.

Я пытаюсь заставить CSP работать для встроенных сценариев, но я не знаю, делаю ли я что-то не так или это ошибка Chrome 18.

manifest.json:

{
    "name": "CSP Test",
    "version": "1.0",
    "manifest_version": 2,
    "options_page": "test.html",
    "content_security_policy": "default-src 'unsafe-inline'"
}

test.html:

<html><head>
<script type="text/javascript">
        alert("hello");
</script>
</head></html>

В Chrome 18 это распакованное расширение не загружается, что выдает ошибку:

Could not load extension from '[extension directory]'. Invalid value for 'content_security_policy'.

Если я изменю 'unsafe-inline' на 'self', расширение загружается нормально, но alert() не работает, и консоль страницы параметров содержит ошибку:

Отказ от выполнения встроенного скрипта из-за Content-Security-Policy.

В Chrome 16 использование 'unsafe-inline' позволяет нормально загружать расширение и alert() тоже работает. Однако в Chrome 16 замена 'unsafe-inline' на 'foo' позволяет загружать расширение, но, конечно, не дает работать alert(), поэтому, возможно, Chrome 18 более строг, чем 16, но ...

Действительно ли default-src 'unsafe-inline' недействителен, или это ошибка? Какое значение CSP можно использовать, чтобы alert() работал в Chrome 18?


Исходя из принятого ответа ниже, встроенные скрипты больше не работают в расширениях в Chrome 18. alert() необходимо будет поместить в собственный файл JavaScript.

Ответы [ 4 ]

24 голосов
/ 24 июля 2016

Для последних версий Chrome (46+) текущий ответ больше не соответствует действительности. unsafe-inline все еще не имеет никакого эффекта (в манифесте и в meta тегах заголовка), но согласно документации , вы можете использовать описанный метод здесь , чтобы ослабить ограничение. 1007 *

Использование хэша для <script> элементов

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

Использование просто. Сервер вычисляет хэш содержимого конкретного блока скрипта и включает в себя кодировку base64 этого значения в заголовке Content-Security-Policy:

Content-Security-Policy: default-src 'self';
                     script-src 'self' https://example.com 'sha256-base64 encoded hash'

Пример * * тысяча двадцать-одна Обратите внимание на следующее: manifest.json : { "manifest_version": 2, "name": "csp test", "version": "1.0.0", "minimum_chrome_version": "46", "content_security_policy": "script-src 'self' 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs='", "background": { "page": "background.html" } } background.html : <!DOCTYPE html> <html> <head></head> <body> <script>alert('foo');</script> </body> </html> Результат
alert dialog from inline script Дальнейшее расследование

Я также протестировал помещение соответствующей директивы в тег meta вместо манифеста. Несмотря на то, что CSP, указанный в сообщении консоли, действительно содержит содержимое тега, он не будет выполнять встроенный сценарий (в Chrome 53).

new background.html :

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs='">
  </head>
  <body>
    <script>alert('foo');</script>
  </body>
</html>

Результат
console error messages about content security policy

Приложение: Генерация хэшей

Вот два метода генерации хэшей:

  1. Python (передать JS в stdin, передать его куда-нибудь еще):
import hashlib
import base64
import sys

def hash(s):
    hash = hashlib.sha256(s.encode()).digest()
    encoded = base64.b64encode(hash)
    return encoded

contents = sys.stdin.read()
print(hash(contents))
  1. В JS используется криптографическая библиотека Stanford Javascript :
var sjcl = require('sjcl');
// Generate base64-encoded SHA256 for given string.
function hash(s) {
  var hashed = sjcl.hash.sha256.hash(s);
  return sjcl.codec.base64.fromBits(hashed);
}

Убедитесь, что при хэшировании встроенных сценариев включено содержимое тега сценария целом (включая все начальные / конечные пробелы). Если вы хотите включить это в свои сборки, вы можете использовать что-то вроде cheerio , чтобы получить соответствующие разделы. В общем, для любого html вы можете сделать:

var $ = cheerio.load(html);
var csp_hashes = $('script')
  .map((i, el) => hash($(el).text())
  .toArray()
  .map(h => `'sha256-${h}'`)
  .join(' ');
var content_security_policy = `script-src 'self' 'unsafe-eval' ${csp_hashes}; object-src 'self'`;

Этот метод используется в hash-csp , плагине gulp для генерации хешей.

14 голосов
/ 26 июля 2012

Следующий ответ верен для более старых версий Chrome (<46). Для более свежих, пожалуйста, проверьте @ Крис-Хант ответ <a href="https://stackoverflow.com/a/38554505/422670">https://stackoverflow.com/a/38554505/422670

Я только что опубликовал очень похожий ответ на вопрос https://stackoverflow.com/a/11670319/422670

Как уже говорилось, нет способа ослабить встроенную политику безопасности в расширениях v2 . unsafe-inline просто не работает, намеренно.

На самом деле нет другого способа, кроме как переместить весь ваш javascript в js-файлы и указать на них <script src>.

Тем не менее, есть возможность выполнить Eval и новую функцию внутри изолированного iframe, например, со следующими строками в манифесте:

"sandbox": {
    "pages": [
      "page1.html",
      "directory/page2.html"
    ]
},

У изолированной страницы не будет доступа к API расширений или приложений или прямого доступа к страницам без песочницы (она может связываться с ними через postMessage ()). Вы можете дополнительно ограничить права песочницы с определенным CSP

Теперь есть полный пример от команды Google Chrome для github eval в iframe о том, как обойти проблему, общаясь с изолированным iframe, а также краткое руководство по аналитике

Благодаря Google, в линейке есть много переписанных расширений: (* ​​1030 *

EDIT

Возможно ослабить политику безопасности для УДАЛЕННЫХ скриптов. Но не для строчных.

Политика против eval() и ее родственников, таких как setTimeout(String), setInterval(String) и new Function(String), может быть ослаблена добавлением 'unsafe-eval' к вашей политике: "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Однако мы настоятельно рекомендуем не делать этого. Эти функции являются пресловутыми векторами атаки XSS.

это появилось в документации по соединительным линиям и обсуждается в потоке "eval re-разрешено"

inline scripts не вернется, хотя:

Нет механизма ослабления ограничения на выполнение встроенного JavaScript. В частности, установка политики сценариев, включающей 'unsafe-inline', не будет иметь никакого эффекта.

3 голосов
/ 22 июня 2015

Использование хэша для встроенных сценариев разрешено в Content Security Policy Level 2. Из примера в спецификации:

Content-Security-Policy: script-src 'sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZDlkOWI0NTAyMjgyY2MyMWJlMWUyNjc1ODJlYWJhNjU5MGU4NmZmNGU3OAo = '

* 100 * * * * * * * * * * * * *'' nonce- $ RANDOM ';

затем

<script nonce="$RANDOM">...</script>
<script nonce="$RANDOM" src='save-because-nonce'></script>

Похоже, что они поддерживаются в Chrome 40+, но я не уверен, какая удача будет с другими браузерами в данный момент.

2 голосов
/ 14 декабря 2011

Афаик, это ошибка.

"default-src 'self' https://ssl.google-analytics.com"

работает, а

"default-src 'self' http://ssl.google-analytics.com"

оленья кожа.

Это действительно передовая технология, подробности смотрите http://code.google.com/p/chromium/issues/detail?id=105796.

Обновление: http://code.google.com/p/chromium/issues/detail?id=107538 относится к этой проблеме.

...