CDN
外部のURIを使ってライブラリなどのダウンロードを高速化する仕組み。
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
見ての通り、CDNサービスがハックされてファイルが改竄されたりするとXSSが起こる。
Subresource Integrity
ファイルのハッシュをHTMLに書いておいて改竄を検出する仕組み。
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous"></script>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
crossorigin="anonymous">
integrity
属性にはファイルのハッシュとハッシュを作るのに使ったハッシュ関数を書いておく。
crossorigin
属性はCORS[1]に関係する属性で、integrity
属性を使う場合は必須。
[2]によれば、crossorigin
属性はCross-origin data leakageという脆弱性が生まれてしまうのを防ぐために必要なのだそうだ(よく分かってない)。
[3]によれば、crossorigin="anonymous"
は、Cookieや認証情報のような、ユーザとCDNを利用しているドメインとを関連付けることを可能にする情報を、CDNサービスに送信しないことを意味し、これによってCross-origin data leakageを防ぐことができるという。
ハッシュ関数として何を使うかは、SHA-256、SHA-384、SHA-512の中から選ぶことができる。
例えばSHA-384をハッシュとして使う場合のintegrity
属性の値は以下のコマンドで求めることができる。
echo sha384-"$(openssl dgst -sha384 -binary bootstrap.min.js | openssl base64 -A)"
わざわざローカルにファイルをダウンロードするのが面倒なら以下のようなコマンドも使える。
# Wget版
echo sha384-"$(wget -nv -O - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js | openssl dgst -sha384 -binary | openssl base64 -A)"
# cURL版
echo sha384-"$(curl -s -S -f https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js | openssl dgst -sha384 -binary | openssl base64 -A)"
コマンドを打つのも面倒なら以下のサイトを使うことができる。
SRI Hash Generator
ブラウザの対応状況
Subresource Integrityが有効に働くためにはユーザがSubresource Integrityを実装したブラウザを使っている必要がある。
[4]によれば、この記事執筆時のブラウザの対応状況は、Chrome 45以上、Firefox 43以上、Opera 32以上。
まだ仕様が策定段階なので[2]、IEなどは実装していない。
以下のサイトを使うことで、あなたのブラウザがSubresource Integrityをサポートしているかどうかについては確認することができる。
Subresource Integrity
フォールバック
ファイルが改竄されていた場合、そのファイルはロードされないのでサイトの表示が崩れることになる。
JavaScriptについては以下のようなフォールバック策があるようだ[5]。
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous"></script>
<script>window.jQuery.fn.modal || document.write('<script src="bootstrap.min.js"><\/script>')</script>
CSSについては以下のようなフォールバック策があるようだ[6]。
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
crossorigin="anonymous">
<script>
for (var i = 0; i < document.styleSheets.length; i++) {
var sheet = document.styleSheets[i];
if (sheet.href == "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css") {
var rules = sheet.rules ? sheet.rules : sheet.cssRules;
if (rules.length == 0) {
var link = document.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("href", "bootstrap.min.css");
document.getElementsByTagName("head")[0].appendChild(link);
}
}
}
</script>
まとめ
書いておいて損は無いので今からでもintegrity
属性とcrossorigin
属性を書いておきましょう。
References
- [1]: Cross-Origin Resource Sharing
- [2]: Subresource Integrity
- [3]: Do not let your CDN betray you: Use Subresource Integrity ★ Mozilla Hacks – the Web developer blog
- [4]: Subresource Integrity - Web security | MDN
- [5]: javascript - how to fallback twitter-bootstrap cdn to local copy - Stack Overflow
- [6]: jquery - How to fallback to local stylesheet (not script) if CDN fails - Stack Overflow