Subresource Integrity (SRI) とは、 (CDN などから) 取得したファイルが意図せず改ざんされていないかをブラウザーが検証するセキュリティ機能です。 SRI を利用する際には、取得したファイルのハッシュ値と一致すべきハッシュ値を指定します。

Subresource Integrity の必要性

複数のサイトで使われるスクリプトやスタイルシートなどのファイルを Content Delivery Networks (CDNs) にホストすることにより、読み込みに必要な時間や通信帯域を減らすことができます。しかし、 CDN はリスクにもなり得ます。仮に攻撃者が CDN を掌握できれば、攻撃者は CDN 上のファイルに悪意あるコンテンツを挿入することにより (あるいは完全に置き換えることにより)、その CDN からファイルを読み込む全てのサイトを攻撃対象とすることができます。

Subresource Integrity は、ウェブアプリケーションやウェブ文書が (CDN など任意の場所から) 取得したファイルについて、第三者によってファイルの中に別のものが挿入されていないか、そして、それらのファイルに対してその他の改ざんが行われていないかを検証することにより、先程のような攻撃のリスクを軽減します。

メモ: Subresource Integrity 機能はすべてのリスクを緩和するわけではありません。第三者の JavaScript はしばしば、スクリプトの提供者のサイトやその他の第三者のサイトに格納されたデータにアクセスする AJAX リクエストを含んで第三者のデータに依存したり、クエリ引数や入力値のようなユーザーのデータに依存したりするようになっています。これらは JavaScript の機能性に対応するために必要になります。地図ライブラリはおそらく表示する地図の <svg> データにアクセスする必要があるため、 JavaScript の機能の対応が必要なことがよくありますが、これは onclick 属性のイベントを含む可能性があります。

Subresource Integrity の使い方

Subresource Integrity の機能は、ブラウザーが取得するリソース (ファイル) のハッシュ値を base64 エンコードし、その値を <script><link> 要素の integrity 属性に指定することによって使用します。

integrity 属性の値は、ハッシュアルゴリズムを示す接頭辞 (現在利用できる接頭辞は sha256, sha384, sha512 です) と、 base64 でエンコードされたハッシュ値をダッシュで繋いだ文字列です。

integrity 属性値には、ホワイトスペースで区切って複数のハッシュ値を含めることができます。リソースはこれらのハッシュ値のいずれかに一致した場合に読み込まれます。

base64 でエンコードされた sha384 ハッシュを含む integrity 文字列の例:

sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC

厳密に言うと、integrity 属性値におけるハッシュ値の部分は、あるハッシュ関数にデータを入力 (スクリプトやスタイルシートファイル) して生成された暗号学的ダイジェスト値です。しかし暗号学的ダイジェスト値ハッシュと呼ぶほうが一般的であるため本記事でもそのように呼んでいます。

SRI ハッシュを生成するツール

次の openssl コマンドにより SRI ハッシュを生成することができます。

cat FILENAME.js | openssl dgst -sha384 -binary | openssl -base64 -A         

又は、次のような shasum コマンドの呼び出しでも実現できます。

shasum -b -a 384 FILENAME.js | xxd -r -p | base64

また、SRI Hash Generator (https://srihash.org/) によりオンラインで SRI ハッシュを生成することもできます。

Content Security Policy と Subresource Integrity

Content Security Policy を使用すると、特定の種類のファイルに対して Subresource Integrity の使用をサーバーに強制するよう設定することができます。このためには、以下のように CSP ヘッダーで require-sri-for ディレクティブを使用します。

Content-Security-Policy: require-sri-for script;

これは JavaScript を読み込むとき、 Subresource Integrity 情報があってチェックに通った場合のみ成功として扱います。

スタイルシートを読み込むときに SRI を使用するように指定することもできます。

Content-Security-Policy: require-sri-for style;

script 及び style の両方を指定し、両方の種類のファイルに SRI を強制することもできます。

以下の例では、 oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC が特定のスクリプト example-framework.js の期待される SHA-384 ハッシュ値としてすでに知られており、スクリプトのコピーが https://example.com/example-framework.js にホストされているものとします。

script 要素の Subresource Integrity

次の <script> 要素により、ブラウザーが https://example.com/example-framework.js を実行する前に、まず想定されるハッシュ値とスクリプトのハッシュ値が一致することをブラウザに確認させることができます。

<script src="https://example.com/example-framework.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

crossorigin 属性については CORS 設定属性を参照してください。

Subresource Integrity のブラウザでの扱い

ブラウザは SRI を以下のように処理します。

  1. ブラウザは integrity 属性を持った <script> または <link> 属性を見つけると、スクリプトや <link> 属性で指定された任意のスタイルシートを適用する前に、integrity 属性のハッシュ値とスクリプトやスタイルシートのハッシュ値を比較しなくてはなりません。
  2. スクリプトやスタイルシートが対応する integrity 属性値と一致しない場合、ブラウザはスクリプトを実行したりスタイルシートを適用してはいけません。その代わりに、スクリプトやスタイルシートの取得が失敗したというネットワークエラーを返さなくてはなりません。

仕様書

仕様書 状態 備考
Subresource Integrity 勧告  
Fetch 現行の標準  

ブラウザーの対応

<script integrity>

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本対応45 なし43 なし ? なし1
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
基本対応4545 なし43 ? なし5.0

1. WebKit bug 148363 tracks WebKit implementation of Subresource Integrity (which includes the integrity attribute).

CSP: require-sri-for

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本対応54 なし491 なし41 なし
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
基本対応5454 なし49141 なし6.0

1. From version 49: this feature is behind the security.csp.experimentalEnabled preference (needs to be set to true). To change preferences in Firefox, visit about:config.

関連情報

ドキュメントのタグと貢献者

このページの貢献者: mfuji09, hashedhyphen, satakeh
最終更新者: mfuji09,