ニュース

XSS攻撃の温床「innerHTML」はもう終わり、「Firefox 148」に「setHTML()」が導入

入力を自動でサニタイズしてくれる「Sanitizer API」が実装

公式開発者向けブログ「Mozilla Hacks」におけるアナウンス

 先日リリースされた「Firefox 148」には、主要Webブラウザーで初めて「Sanitizer API」が実装されているとのこと。「クロスサイトスクリプティング」と呼ばれるタイプの脆弱性を抑制する技術として期待されており、他のWebブラウザーも追随する見込みだ。

 「クロスサイトスクリプティング」(Cross-Site Scripting、XSS)は、外部からの入力を十分にチェックせずに受け付けてしまう動的サイトで多く見られる脆弱性、およびそれを悪用したセキュリティ攻撃の手法。たとえばスクリプトなどを含むコンテンツをコメント欄に入力したにもかかわらず、適切な処理を施さずにそのまま投稿できてしまう場合、当該サイトに実行可能な不正コードが埋め込まれてしまうことがある。これを許してしまうと、正規サイトに偽コンテンツを埋め込んで閲覧者を騙したり(フィッシング)、Cookieに含まれる認証情報を盗まれたり、ユーザーになりすましといった被害につながる可能性がある。

 対策としては、安全なコンテンツだけを許可するように入力を制限する方法や、外部から入力されたスクリプトを“無毒化”(サニタイズ、Sanitize)する方法がある。入力をなるべく制限したくない場合、後者の採用望ましい。

 しかし、HTML要素の読み取り・書き込みを行う「innerHTML」プロパティには無毒化処理を実施する機能がなく、プログラマーが自分で処理を書く必要があった。そのため、無毒化処理にどうしても漏れが生じ、XSS脆弱性の温床となってしまっているのが現実だ。

 そこで考案されたのが、「Firefox 148」で導入された「Sanitizer API」だ。このAPIは、「innerHTML」に代わる仕組みとして「setHTML()」を提供する。「setHTML()」は書き込み専用のメソッドで、危険なスクリプトを含むHTMLコードを渡しても、自動で“無毒化”を行う。「innerHTML」から「setHTML()」への置き換えを徹底するだけで、XSS脆弱性の多くを回避できるはずだ。

document.body.innerHTML = "<h1>Hello my name is <img src='x'
onclick='alert(1)'>";

# スクリプトが実行されてしまう

document.body.setHTML("<h1>Hello my name is <img src='x'
onclick='alert(1)'>");

# スクリプトが自動で削除され(無毒化)、以下のHTMLコードがセットされる
<h1>Hello my name is</h1>

 もし“無毒化”が厳しすぎる場合は、プログラマーの責任においてカスタムサニタイザーを定義し、特定のHTMLコードを許可することもできる。指定した型を安全に変換するポリシーを作成できる「Trusted Types API」と組み合わせれば、よりXSS攻撃に強いWebサイト・アプリを構築できるだろう。

 「Sanitizer API」を試してみたい場合は、「Firefox 148」で「HTML Sanitizer API Playground」へアクセスしてみるとよい。実際の挙動を手軽に確かめることができる。

「Sanitizer API」のテストサイト「HTML Sanitizer API Playground」
さまざまなカスタムサニタイザーで「Sanitizer API」の無毒化処理の挙動を実際に確かめられる(左は無対策なのでXSS攻撃が成立しているが、右は無毒化されている)