web-dev-qa-db-ja.com

Chrome 18+:コンテンツセキュリティポリシーでインラインスクリプトを許可するには?

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のため、インラインスクリプトの実行を拒否しました。

In Chrome 16、_'unsafe-inline'_を使用すると、拡張機能が正常にロードされ、alert()も機能します。ただし、in Chrome= 16 、_'unsafe-inline'_を_'foo'_に置き換えると、拡張機能がロードされますが、もちろんalert()は機能しません。したがって、おそらくChrome 18は16より厳密です、しかし...

_default-src 'unsafe-inline'_は実際に無効ですか、またはこれはバグですか? alert()をChrome 18で動作させるにはどのCSP値を使用できますか?


以下の受け入れられた回答に基づいて、インラインスクリプトはChrome 18の拡張機能で動作しなくなりました。alert()は独自のJavaScriptファイルに配置する必要があります。

29
Chris McFarland

Chrome(46+)の最近のバージョンでは、現在の答えはもはや真ではありません。unsafe-inlineはまだ効果がありません(マニフェストおよびmetaヘッダータグ内)が、 ドキュメンテーション 、説明されているテクニックを使用して here 制限を緩和できます.

<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にはタグのコンテンツが含まれていましたが、インラインスクリプトは実行されません(in Chrome 53)。

新規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

付録:ハッシュの生成

ハッシュを生成する2つの方法を次に示します。

  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 Crypto Libraryを使用します
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);
}

インラインスクリプトをハッシュするときは、スクリプトタグのwholeの内容(すべての先頭/末尾の空白を含む)が含まれていることを確認してください。これをビルドに組み込みたい場合は、 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'`;

これは、ハッシュを生成するためのgulpプラグインである hash-csp で使用されるメソッドです。

23
Chris Hunt

次の回答は、古いバージョンのChrome(<46)に当てはまります。最近のものについては、@ Chris-Huntの回答 を確認してください。 https://stackoverflow.com/a/38554505/422670

質問に対して非常によく似た回答を投稿しました https://stackoverflow.com/a/11670319/422670

言われているように、v2拡張機能のインラインセキュリティポリシーを緩和する方法はありません。 _unsafe-inline_は意図的に機能しません。

JavaScriptをすべてjsファイルに移動し、_<script src>_でそれらを指すこと以外に方法はありません。

ただし、サンドボックス化されたiframe内で評価と新しい関数を実行するオプションがあります。たとえば、マニフェストに次の行があります。

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

サンドボックス化されたページは、拡張機能またはアプリAPIにアクセスできず、サンドボックス化されていないページに直接アクセスできません(postMessage()を介してそれらと通信できます)。特定のCSPでサンドボックスの権限をさらに制限できます

Google Chrome iframeの github evalのチーム から、サンドボックスiframeと通信して問題を回避する方法についての完全な例もあります。 ショート分析チュートリアルとして

Googleのおかげで、ラインナップには多くの拡張機能の書き換えがあります:(

[〜#〜] edit [〜#〜]

REMOTEスクリプトのセキュリティポリシーを緩和することは可能です。しかし、インラインではありません。

eval()およびsetTimeout(String)setInterval(String)、およびnew Function(String)などの親類に対するポリシーは、_'unsafe-eval'_を追加することで緩和できます。ポリシー:_"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"_

ただし、これを行わないことを強くお勧めします。これらの機能は、悪名高いXSS攻撃ベクトルです。

これは trunk documentation にあり、スレッド "eval re-allowed" で説明されています

_inline scripts_は戻りません:

インラインJavaScriptの実行に対する制限を緩和するメカニズムはありません。特に、_'unsafe-inline'_を含むスクリプトポリシーを設定しても効果はありません。

14
Stefano

インラインスクリプトのハッシュの使用 は、コンテンツセキュリティポリシーレベル2で許可されています。仕様の例から:

コンテンツセキュリティポリシー:script-src 'sha512-YWIzOWNiNzJjNDRlYzc4MTgwMDhmZDlkOWI0NTAyMjgyY2MyMWJlMWUyNjc1ODJlYWJhNjU5MGU4NmZmNGU3OAo ='

代替例は nonce です。これも例からです:

コンテンツセキュリティポリシー:script-src 'self' 'nonce- $ RANDOM';

それから

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

これらはChrome 40+でサポートされているように見えますが、現時点で他のブラウザでどのような運が得られるかはわかりません。

3
Brian M. Hunt

Afaik、これはバグです。

"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 はこの問題を指します。

2
Maximilian Hils