Subresource Integrity (SRI) とは、CDN などから取得したファイルが意図せず改ざんされていないかをブラウザが検証するセキュリティ機能です。SRI を利用する際には、取得したファイルのハッシュ値と一致すべきハッシュ値を指定します。
Subresource Integrity の必要性
複数のサイトで使われるスクリプトやスタイルシートなどのファイルを Content Delivery Networks (CDNs) にホストすることにより、読み込みに必要な時間や通信帯域を減らすことができます。しかし、CDNはリスクにもなり得ます。仮に攻撃者が CDN を掌握できれば、攻撃者は CDN 上のファイルに悪意あるコンテンツを挿入することにより(あるいは完全に置き換えることにより)、その CDN からファイルを読み込む全てのサイトを攻撃対象とすることができます。
Subresource Integrity は、Web アプリケーションや Web ドキュメントが(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
また、SRI Hash Generator (https://srihash.org/) によりオンラインで 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 を以下のように処理します。
- ブラウザは integrity 属性を持った
<script>または<link>属性を見つけると、スクリプトや<link>属性で指定された任意のスタイルシートを適用する前に、integrity 属性のハッシュ値とスクリプトやスタイルシートのハッシュ値を比較しなくてはなりません。 - スクリプトやスタイルシートが対応する integrity 属性値と一致しない場合、ブラウザはスクリプトを実行したりスタイルシートを適用してはいけません。その代わりに、スクリプトやスタイルシートの取得が失敗したというネットワークエラーを返さなくてはなりません。
仕様
| 仕様書 | 策定状況 | 備考 |
|---|---|---|
| Subresource Integrity | 勧告 | |
| Fetch | 現行の標準 |
ブラウザ実装状況
| 機能 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
<script> と <link> での integrity 属性 |
45.0 | 43 (43) | 未サポート | 32 | 未サポート [1] |
CSP require-sri-for ディレクティブ |
? | 49 (49) | ? | ? | ? |
| 機能 | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
|---|---|---|---|---|---|
<script> と <link> での integrity 属性 |
45.0 | 43.0 (43) | 未サポート | 未サポート | 未サポート [1] |
CSP require-sri-for ディレクティブ |
? | 49.0 (49) | ? | ? | ? |