locationへの代入や<a href>への設定などにおいて外部からコントロール可能な文字列を利用する場合は、javascript:スキームなどが含まれないよう注意する必要があります。
// ★★★脆弱な例(1)★★★ var url = decodeURIComponent( location.hash.substring(1) ); // URLの#以降の部分 location.href = url;
// ★★★脆弱な例(2)★★★ var url = decodeURIComponent( location.hash.substring(1) ); // URLの#以降の部分 var elm = document.getElementById( "link" ); // <a id="link"> elm.setAttribute( "href" url );
この例では、新しい画面の遷移先や、<a>要素のリンク先として現在のURL中の#より後ろの部分を使用していますが、攻撃者がhttp://example.jp/#javascript%3Aalert(1)のようなURLへ誘導した場合、#より後ろの部分のjavascript:alert(1)がそのまま新しいURLとして使用されるため、XSSが発生することになります。
対策として「URLとしてjavascript:スキームが入らないようにする」の場合だと、次に攻撃者はdata:スキームやvbscript:スキームを利用してXSSを行いますので、URLとしてhttpおよびhttpsだけに限定するのが賢明です。
以下は文字列の先頭が「http://」または「https://」で始まっているかどうかを確認してから使用するコードの例です。
// ★★★安全な例★★★ var url = decodeURIComponent( location.hash.substring(1) ); // URLの#以降の部分 if( url.match( /^https?:\/\// ) ){ var elm = document.getElementById( "link" ); // <a id="link"> elm.setAttribute( "href" url ); }
ただし、locationへの代入などページ遷移の目的でURLを使用する場合には、たとえURLがhttp://またはhttps://で始まっていても、攻撃者によって任意のサイトへの誘導に使われるオープンリダイレクタが発生する可能性があります(オープンリダイレクタについても、今後の連載にて解説する予定です)。
次回はXSSの後半として、「XHR Level 2によるリモートからのコード挿入によるXSS」および「XHRによってやり取りされるデータによるXSS」を取り上げたいと思います。
ネットエージェント株式会社 エバンジェリスト、株式会社セキュアスカイ・テクノロジー 技術顧問。Internet Explorer、Mozilla FirefoxをはじめWebアプリケーションに関する多数の脆弱性を発見。Black Hat Japan 2008、韓国POC 2008、2010他講演多数。
Copyright © ITmedia, Inc. All Rights Reserved.