単純ではない、最新「クロスサイトスクリプティング」事情:HTML5時代の「新しいセキュリティ・エチケット」(2)(2/3 ページ)
HTML5の新しい要素、属性による、いままでとは異なるクロスサイトスクリプティングが登場しています。もう一度、XSSをおさらいしましょう。
DOM Based XSSの増加
従来サーバー上だけで生成していたHTMLを、Ajaxなどと組み合わせブラウザー上でJavaScriptによって操作する機会が増えたため、JavaScriptによるDOM操作時に発生するXSS、すなわちDOM Based XSSが急増しています。
【関連記事】
IPAが「DOM Based XSS」の脆弱性に関するレポートを公開
http://www.atmarkit.co.jp/ait/articles/1301/29/news155.html
DOM Based XSSにおいて、攻撃者によってスクリプトが含まれる可能性のある箇所を「ソース」、JavaScriptプログラム内でそのソースを用いることによって実際にXSSが発生する原因となる機能のことを「シンク」と一部の研究者は呼んでいます。
実際にソースとして働く機能の例としては以下のようなものがあります。
location.href
location.search
location.hash
document.cookie
document.referrer
window.name
localStorage
sessionStorage
シンクとして働く機能の例としては以下のようなものがあります。
document.write
element.innerHTML
eval
setTimeout
setInterval
jQuery(),$(), $.html()
もちろんこれらは代表的な例であり、ソース、シンクともこれら以外にもさまざまなものがあります。必ずしもこの「ソース」「シンク」という用語を覚えておく必要はありませんが、DOM Based XSSに関する理解を深めるためには役に立ちますので紹介しました。
DOM Based XSSへの具体的な対策としては、(1) 使用しているJavaScriptライブラリの適切なバージョンアップに加え、(2)DOM操作APIの適切な使用、(3)扱うURLをhttpおよびhttpsに限定する、の3点になります。
- (1) 使用しているJavaScriptライブラリの更新
現在多くのWebサイトではjQueryをはじめ、多数のJavaScriptライブラリが使用されていますが、これらのライブラリについても脆弱性が発見、報告されることがあります。
サイトを構築後も、JavaScriptライブラリにセキュリティ修正を行ったバージョンがリリースされた場合には、サイトで利用しているライブラリを更新する必要があります。
- (2) DOM操作APIの適切な使用
DOM Based XSSは、JavaScript上でHTMLを組み立てる場合に、攻撃者の用意した文字列がHTML内にそのまま挿入されることによって発生するXSSです。
DOM Based XSSにおいても、XSS対策の原則である「HTML生成時におけるエスケープ」に従い、シンクへ文字列を与える時点でエスケープ処理を行うという方法は有効ですが、可能であれば文字列を操作するのではなく、DOMを通じてHTMLを生成、操作する方が、原理的にXSSの発生を抑えやすくできます。
例えば、DOM Based XSSを発生させる典型的なコードの例として、以下のようなinnerHTMLの使用があったとします。
// ★★★脆弱なコードの例★★★ var div = document.getElementById( "msg" ); div.innerHTML = some_text; // 外部からコントロール可能な文字列
これに対して、従来サーバー側で行われてきた文字列をエスケープするという方法をそのままブラウザー上で行うと以下のようになります。
// 安全なコードの例。★★★決して最適な方法ではない(後述)★★★ function escape_html( s ){ return s.replace( /&/g, "&" ) .replace( /</g, "<" ) .replace( />/g, ">" ) .replace( /"/g, """ ) .replace( /'/g, "'" ); } var div = document.getElementById( "msg" ); // some_text は外部からコントロール可能な文字列 div.innerHTML = escape_html( some_text );
この方法でも安全にはなりますが、自由にDOMを操作できるブラウザー上のJavaScriptであれば、DOM APIを経由して操作する方が、原理的に確実にXSSの発生を抑えやすく、またより自然で見通しのよいコードにもなります。
// ★★★安全なコードの例(推奨)★★★ var div = document.getElementById( "msg" ); // some_text は外部からコントロール可能な文字列 var text = document.createTextNode( some_text ); div.appendChild( text );
jQueryであれば、$( selector ).html( some_text ); ではなく、$( selector ).text( some_text )を使うことになります。
テキストノードだけでなく、属性についても同様にDOM APIを経由して操作することが望ましいといえます。
// ★★★脆弱な例★★★ var div = document.getElementById( "msg" ); var url = "http://example.jp/" + some_page; // some_page は外部からコントロール可能な文字列 div.innerHTML = '<a href="' + url + '">' + url + "</a>";
// ★★★安全な例★★★ var div = document.getElementById( "msg" ); var url = "http://example.jp/" + some_page; // some_page は外部からコントロール可能な文字列 var elm = document.createElement( "a" ); elm.setAttribute( "href", url ); elm.appendChild( document.createTextNode( url ) ); div.appendChild( elm );
Copyright © ITmedia, Inc. All Rights Reserved.