- Web の主要な脆弱性である XSS 攻撃を防ぐため、Firefox が標準化された Sanitizer APIを初めてサポート
- 従来の innerHTML の代わりに setHTML() メソッドを使うと、信頼できない HTML を DOM 挿入前に自動サニタイズして悪意のあるスクリプトを除去
- 開発者は、デフォルト設定が厳しすぎたり緩すぎたりする場合、カスタム設定によって許可する要素や属性を制御可能
- Firefox のこの機能は Trusted Types と組み合わせることで Web 全体のセキュリティ水準を高め、開発者が専任のセキュリティチームなしでも XSS を防げるようにする
XSS 脆弱性と Firefox の対応
- クロスサイトスクリプティング(XSS) は、ユーザーが入力したコンテンツを通じて攻撃者が任意の HTML や JavaScript を挿入したときに発生
- 攻撃者はこれを利用してユーザーの操作を監視したり、データを盗み取ったりできる
- XSS はほぼ 10 年にわたり 上位 3 大 Web 脆弱性(CWE-79) に分類されてきた
- Firefox は 2009 年から Content-Security-Policy(CSP) 標準を主導し、XSS 防御を強化してきた
- CSP は Web サイトが読み込み・実行できるリソースを制限する
- しかし既存サイトの構造変更や継続的なセキュリティレビューが必要で、広範な採用には限界があった
Sanitizer API と setHTML() の役割
- Sanitizer API は、悪意のある HTML を無害な形に変換する標準化された方法を提供
- 例示コードでは
<img src="x" onclick="alert('XSS')"> 要素は除去され、<h1>Hello my name is</h1> だけが残る
- setHTML() メソッドは HTML 挿入時に自動でサニタイズ処理を行い、デフォルトで安全な動作を保証
- 既存の
innerHTML 代入を setHTML() に置き換えるだけで、強力な XSS 防御が可能
- 開発者は デフォルト設定が厳しすぎたり緩すぎたりする場合、カスタム設定を通じて許可する HTML 要素や属性を定義できる
- 実験のために Sanitizer API playground ツールを活用できる
Trusted Types との組み合わせ
- Trusted Types API は HTML のパースと挿入を中央で制御し、追加のセキュリティ層を提供
setHTML() 使用時には Trusted Types ポリシーを容易に適用できる
- 厳格なポリシーでは
setHTML() だけを許可し、ほかの危険な挿入方法を遮断することで、将来の XSS 回帰防止に寄与
Firefox 148 のセキュリティ向上効果
- Firefox 148 は Sanitizer API と Trusted Types の両方をサポートし、基本セキュリティ水準を大幅に向上
- 開発者は複雑なセキュリティポリシーや専任のセキュリティチームがなくても、簡単なコード変更だけで XSS を防止できる
- この標準の導入は、すべてのブラウザで安全な Web 環境の普及につながると期待される
要約
- Firefox 148 は setHTML() メソッドと Sanitizer API により、Web 開発者が容易に XSS 攻撃を遮断できるよう支援
- この機能は CSP の限界を補い、デフォルトで安全な HTML 挿入方式を Web 標準として定着させる契機となる
- Trusted Types との組み合わせにより、長期的なセキュリティ維持と XSS 回帰防止が可能
- 結果として、Firefox は セキュリティがデフォルトの Web 環境への移行を主導している
2件のコメント
おお、確かにこういうものは必要ですよね。すべてのブラウザでサポートされれば、かなり良さそうです
Hacker News の意見
こういう種類の機能はいつも少し不安 ユーザー入力をそのまま渡しても安全に処理されるメソッドと、そうでないメソッドが混在していて、名前だけでは区別しづらいから 理想的には、危険な関数は最初から名前で明確に分かるべき また、HTML を「sanitize」するという概念自体が曖昧で、本当に安全かどうか判断しにくい
elementNode.textContentは信頼できない入力にも安全で、elementNode.innerHTMLはそうではない 前者はすべての文字を escape し、後者は何も escape しない 「HTML sanitization」は根本的に解決不可能な問題だという意見もある 関連する議論は このコメント を参照 こういう API は提案段階で通すべきではなかったinnerHTMLとsetHTMLを混在させて使うのではなく、innerHTMLを完全に廃止し、以前の挙動が必要ならsetHTMLUnsafeを使うように設計すべきinnerHTMLのような旧式 APIを無効化できるとよい ただしそうすると、古いブラウザーではサイトが動作しなくなるかもしれないContent-Security-Policy: require-trusted-types-for 'script'ヘッダー付きで配信すれば、sanitizer のないメソッドに通常の文字列を渡すことを防げる例のように
<h1>や<br>のようなタグをユーザー名に挿入できるなら、スクリプト実行は防げても、依然として任意のマークアップ注入は可能<style>タグで CSS を変えてしまうこともできるので、たとえば PayPal のプロフィールページのデザインを変えてしまうこともできる こんなことを誰が望むのかという疑問があるinnerHTMLではなくinnerTextやtextContentを使うべきだったsetHTMLはinnerHTMLの代替用setHTML()のデフォルト設定が厳しすぎたり緩すぎたりするなら、開発者が許可する HTML 要素や属性を自分で定義するカスタム設定を提供できるこの機能が登場したのはうれしいが、ブラウザー対応が十分に広がるまでには時間がかかりそう Can I use で対応状況を確認できる
タイトルはやや扇情的だった 実際、
innerHTMLに渡す前に入力を検査する関数でも sanitization は実装できるのではないかと思う ただ、こうした試みは結局車輪の再発明のように感じられる また、古い Firefox では hacks.mozilla.org がそもそも開けず、Pale Moon や SeaMonkey では MDN が崩れて見える まるで「ブラウザー・カルテル」が Web を壊そうとしているようだSanitizer API は使い方を誤るとfootgunになりうる 特に「remove」モードを使うときは注意が必要 むしろ
setTextだけを使って、ユーザーに HTML の追加を一切許可しない方がよいと思うsetHTMLを使う限り XSS は発生しないinnerHTMLが頻繁に使われている現実を見ると、完全に排除するのは難しいネットワークアクセスのあらゆる側面がきちんと制御され、今ではセキュリティチェーンがコード信頼からホスト設定信頼へ移った点が印象的 デフォルトも安全に設定されている
本当に欲しいのは、危険なコードを安全に実行できる
<sandbox>要素 危険なコードを修正するのではなく、隔離された環境で動かせるようにすること iframe には DOM と一緒に流れられない制約があり、AI や動的コンテンツが増える時代には構成可能なカプセル化が必要setHTMLUnsafeという名前は本当に気に入っている セキュリティ機能は、開発者がopt-inしなければならない仕組みだと失敗する その代わり、「危険な経路が危険に感じられる」ようにする方が効果的set_html()という名前はinner_htmlよりずっと直感的 JavaScript の API は本当に雑然としているので、いつか整理されるべき 今回の議論はセキュリティ中心だが、新しい API を公開するなら設計自体もきれいであるべき90年代の開発者たち:
2020年代の開発者たち: