We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

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

Subresource Integrity の必要性

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

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

Subresource Integrity の使い方

ブラウザーが取得するリソース (ファイル) のハッシュ値を base64 エンコードし、その値を <script><link> 要素の integrity 属性に指定することで、 Subresource 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 enc -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 を強制することもできます。

以下の例では、example-framework.js の SHA-384 ハッシュ値が oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC であり、 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 現行の標準  

ブラウザーの対応

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

機能 Chrome Firefox (Gecko) Internet Explorer Opera Safari
<script><link> での integrity 属性 45.0 43 (43) 未サポート 32 11 [1]
CSP require-sri-for ディレクティブ ? 49 (49) [2] ? ? ?
機能 Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
<script><link> での integrity 属性 45.0 43.0 (43) 未サポート 未サポート 11 [1]
CSP require-sri-for ディレクティブ ? 49.0 (49) [2] ? ? ?

[1] WebKit bug 148363
[2] about:config 設定の security.csp.experimentalEnabled で隠されています。

関連情報

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

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