開発者ツール · SHA ハッシュ計算ツール
サブリソースの整合性: ブラウザーが SHA-384 を使用してスクリプトをチェックする方法
· 背景
しゃ-256 base64 ブラウザ API セキュリティ
整合性属性を使用すると、バイトが変更された CDN スクリプトをブラウザーが拒否できます。この投稿では、属性の形式、base64 の SHA-384 が一般的な選択である理由、および SRI が保護できないものについて説明します。
あらゆるものに対応できる CDN — SRI が設計したサプライ チェーン リスク
Web ページ上のスクリプト タグには、整合性属性 `<script src="https://cdn.example.com/lib.js" integrity="sha384-..."></script>` を含めることができます。整合性の値は、スクリプトのバイトの暗号化ダイジェストです。ブラウザはスクリプトをダウンロードするときに、受信したバイトのダイジェストを計算し、整合性属性と比較します。一致する場合、スクリプトがロードされます。一致しない場合、ブラウザはロードを拒否し、コンソールに失敗を報告します。これにより、変更されたコードを提供する侵害された CDN や、応答を傍受して変更するネットワーク攻撃者から保護されます。
サブリソース整合性 (SRI) は、スクリプトとスタイルシートに適用される W3C 仕様です。これは、ブラウザがクロスオリジン リソースのコンテンツに関して行うことができる唯一の暗号保証です。バイトはダイジェストと一致する必要があり、一致しない場合、リソースは拒否されます。これは、誰がリソースを作成したかを証明するものではなく、ダイジェストが計算されてからそのリソースが変更されていないことを証明するだけです。信頼できる CDN から HTTPS 経由で提供されるリソースの場合、ダイジェストは、CDN が侵害されたり、キャッシュされた古いコンテンツを提供したりすることに対する安全策を提供します。
整合性属性 — アルゴリズムのプレフィックス、ハイフン、base64 ダイジェスト、および複数のハッシュのサポート
整合性属性には、アルゴリズム名、ハイフン、base64 のダイジェストという特定の形式があります。例: `integrity="sha384-JZDdQnrrAMe+sxxpn47in+PwhkxrCrt4SNvt+xWqV3zPJUkeFF0Qq/wNtuvNqPP5"`。アルゴリズム名は、SHA-256、SHA-384、または SHA-512 です。 Base64 は 16 進数ではなくエンコーディングです。これは、SRI 仕様による意図的な選択です。 Base64 は 16 進数よりもコンパクトです (同じダイジェストで約 33% 短い)。これは、HTML 属性に埋め込むときに重要になります。ハイフンはアルゴリズム名とダイジェストを区切ります。複数の整合性値をスペースで区切ってリストできます。それらのいずれかが一致すると、リソースが受け入れられます。
なぜ SHA-384 なのか? SRI 仕様では、SHA-256、SHA-384、および SHA-512 が許可されています。 SHA-384 は、サイズ/security のバランスを提供するため、コミュニティのデフォルトになりました。 SHA-256 は小さい (base64 では 32 バイト、44 文字) ですが、SHA-384 は幅が広く (base64 では 48 バイト、64 文字)、SHA-256 と比較して属性サイズは大幅に増加しませんでした。 SHA-512 は利用可能ですが、この使用例では大きなダイジェストが必要ないと思われるため、ほとんど使用されません。 SHA-384 の選択は歴史的かつ実用的なものであり、優れたセキュリティ特性を反映したものではありません (この目的では 3 つすべてが暗号的に強力です)。
SHA-384 が提供され、必要な Base64 マテリアルを生成します。コミュニティの好みはツールからは推測されません
SRI の Base64 エンコードは、base64url ではなく標準の Base64 です。標準の Base64 では、+ および / 文字が使用されます。これらは、パーセント エンコーディングなしの HTML 属性では有効ですが、URL およびフォーム データでは特別な意味を持ちます。 SRI 形式は URL ではなく HTML 属性用に設計されているため、標準の Base64 が適切です。整合性値を手動で構築する場合は、SHA-384 ダイジェスト (バイトのシーケンス) を計算し、それらのバイトを標準の Base64 としてエンコードし、`sha384-` を先頭に付加して整合性属性に貼り付けます。
ブラウザは同じ手順を逆に実行します。整合性属性から Base64 を抽出し、バイトにデコードしてダイジェストを回復し、ダウンロードされたスクリプト バイトの SHA-384 を計算し、2 つのダイジェスト値を比較します。それらは正確に一致する必要があります。ダイジェスト内の 1 ビットの違いが拒否の原因となります。あいまいな一致や部分的な信用はありません。整合性は 2 値です。
クロスオリジン SRI の動作には、このハッシュ計算ツール以外のブラウザーのドキュメントが必要です
SRI では、クロスオリジン応答で CORS が必要です。別のオリジンからスクリプトをロードする場合、サーバーは `Access-Control-Allow-Origin: *` またはあなたのヘッダーを含む特定のオリジン ヘッダーで応答する必要があります。 CORS ヘッダーがないと、ブラウザーは SRI をチェックできません。CORS がないと、応答本文がサーバーが送信しようとしていたものと一致するかどうかを確認できないためです。 CORS ヘッダーは、この応答を確認しても安全であるというサーバーのステートメントです。 SRI は、バイトが正しいかどうかをチェックします。これらは共に、サプライチェーンへのコミットメントを形成します。サーバーによってコンテンツの検証が許可され、ユーザーもそれを実行します。
クロスオリジン スクリプトに CORS ヘッダーがなく、整合性属性がある場合、ブラウザーはスクリプトをダウンロードします (そのオリジンからのスクリプトがサイトの CSP で許可されている場合) が、整合性は検証されません。スクリプトは、整合性属性が存在しないかのようにロードされます。これは SRI の失敗ではありません。それはセキュリティ境界です。読み取れない応答を検証することはできません。
不一致の場合に何が起こるか — ブラウザはリソースをブロックし、コンソールにレポートします
ブラウザは整合性の不一致を検出すると、スクリプトの実行を拒否し、ブラウザのコンソールにメッセージを記録します。通常、メッセージには URL、予想されるハッシュ、および計算されたハッシュが指定されます。失敗はアトミックです。リソースがそのままロードされるか、完全に拒否されます。部分的なロードやフォールバックはありません。 Web サイトがそのスクリプトに依存しており、それが拒否されると、サイトが破損する可能性があります。これは意図的なものです。間違ったコードを配信することは、コードを配信しないことよりも悪く、サイレント障害により攻撃が無期限に継続する可能性があります。
SRI セットアップのテストは簡単です。ブラウザ コンソールを開いてページをロードし、整合性の不一致に関するメッセージを探します。不一致が見つかった場合は、コンソールに表示される計算されたハッシュと整合性属性のハッシュを比較してください。一致しない場合は、再計算します。スクリプトが更新された可能性があるため、新しいダイジェストが必要です。
実用的な例 — スクリプトのダイジェストを計算し、base64 ステップを含む整合性値にフォーマットする
SRI ダイジェストを手動で計算するには、スクリプト バイトとハッシュ ツールのみが必要です。スクリプトをダウンロードして、ToolAcre SHA ハッシュ計算ツールに貼り付け、SHA-384 を選択し、base64 出力 (16 進数ではない) をコピーし、先頭に `sha384-` を付加して、整合性属性に貼り付けます。スクリプトが大きい場合は、curl または wget を使用してスクリプトをファイルに保存し、貼り付けるよりもファイルを読み取る方が高速です。インライン スクリプト (URL からではなく HTML の `<script>` タグ内) の場合、SRI は適用されません。インライン スクリプトは定義により常に信頼されます。 SRI は外部リソース用です。
実用的な例: SRI を使用して CDN から jQuery をロードするとします。スクリプトの URL を見つけてダウンロードし (または、curl を使用して取得し)、バイトを電卓に貼り付けるか、コマンド ラインで `sha384sum` を使用し、SHA-384 ダイジェストを Base64 として取得し、`sha384-[base64-digest]` としてフォーマットします。スクリプト タグの integrity 属性に貼り付けます。ページをロードし、コンソール エラーが表示されないことを確認します。
これでカバーされないもの — 意図的に変更されるスクリプト、および外部スクリプトをまったく読み込まないため固定するものが何もない ToolAcre のようなサイト
SRI は、すべてのサプライチェーン攻撃から保護するわけではありません。これは、ダイジェストの計算後に変更されるバイトから保護しますが、最初から侵害されたコードから計算されるダイジェストからは保護しません。ダイジェストを計算する前に CDN が侵害された場合、SRI は役に立ちません。ダイジェストは、それを計算したソースと同じくらい信頼できます。最大限の保証を得るには、元のソース (ライブラリの GitHub リリースなど) からダイジェストを計算し、CDN からロードするときにそれらのダイジェストを使用します。ダイジェストは、リリースプロセスを通じてメンテナーからのコミットメントとなります。
SRI は、ダイジェストを計算する時点でのネットワークの侵害や、開発マシンの侵害に対する保護も行いません。ダイジェストが作成されてからブラウザーがスクリプトをロードするまでの間のスクリプトへの変更のみを保護します。継続的な保証のために、一部のデプロイメントでは SRI に加えてリリース署名が使用されます。リリースはメンテナのキーによって署名され、署名を検証し、検証されたバイトからダイジェストを計算して、それを SRI で使用します。
この記事は、ハッシュ ソースからの ToolAcre のサイト全体の外部スクリプト インベントリを主張するものではありません
ToolAcre SHA ハッシュ計算機は、標準の Base64 でダイジェストを直接出力します (`toBase64()` 関数からの `base64` 出力として)。 SRI 形式に変換するには、アルゴリズム名とハイフンを先頭に付けます: `sha256-`、`sha384-`、または `sha512-`。ハッシュは、アルゴリズム名が別個であるか、異なる方法でエンコードされている多くのコンテキスト (git、Docker、npm、URL) で使用されるため、計算機はそのプレフィックスを自動的に適用しません。境界は明確です。電卓は、ファイルやバイナリ キーではなく、貼り付けた UTF-8 テキストをハッシュします。 16 進数と Base64 の両方を出力します。コンテキストに基づいてどちらを使用するかを選択します。 SRI の場合、仕様により Base64 が必須です。 git やその他のツールでは、従来どおり 16 進数が使用されます。 npm と Go では、base64 が使用されます。エンコーディングの選択はあなた次第です。ダイジェストバイトは同じです。
SRI は、集中管理された権限を持たずにブラウザがクライアント側で実行できる数少ない暗号化チェックの 1 つです。 ToolAcre の SHA 計算ツールなどの信頼できるツールを使用してダイジェストを計算し、読み込まれたリソースに対してそれを検証することは、特定のサプライ チェーン攻撃に対して Web サイトを強化するアクセス可能な方法です。保護はダイジェストと同じくらい優れています。外部リソースを更新するたびに再計算し、ブラウザがスクリプトを拒否せずに読み込むかどうかをテストします。