JavaScriptセキュリティの基礎知識

第5回 問題を発生させにくくするURLの扱い方

この記事を読むのに必要な時間:およそ 7 分

前回は,セキュリティ上の境界条件はオリジンという単位で行われること,オリジンはURLをもとに決定されることを説明しました。今回は,実際にJavaScript内でURLというデータをどのように扱えばセキュリティ上の問題を発生させにくくなるのかについて解説していきます。

locationオブジェクト

locationオブジェクトの基本

JavaScriptにおいてURLを取り扱う最も基本的な要素の1つが,locationオブジェクトでしょう。locationオブジェクトには現在表示しているドキュメントのURLが格納されており,locationオブジェクトを操作することで現在のドキュメントから違うURLへページを遷移させることもできます。

locationオブジェクトの代表的なプロパティおよびメソッドを下表に示します。

locationオブジェクトの代表的なプロパティおよびメソッド

メソッド説明
assign引数で指定されたURLへ移動する
reloadページをリロードする。引数でtrueが指定された場合は,キャッシュを用いずに,サーバからリロードする
replace引数で指定されたURLへ移動するが,移動の履歴が残らない
プロパティ説明
protocolURLのプロトコル部分
hostURLのホスト部分。ポート番号があればそれも含む
hostnameURLのホスト部分。ポート番号は含まない
portURLのポート番号部分。デフォルトポートの場合は,空文字列
pathnameURLのパス名部分
searchURLの?以降のクエリ文字列
hashURLの#以降
href完全なURL全体

現在,主要なブラウザのほとんどでは,表示しているページの正規化されたオリジンをJavaScript上から取得するためのoriginプロパティがlocationオブジェクトに実装されています。

IE10以下などではlocation.originは実装されていないので,location.originプロパティを参照したい場合には,以下のようなコードを入れておくといいでしょう。

if( location.origin === undefined ){
    location.origin = location.protocol + "//" + location.hostname + (location.port ? ":" + location.port : "");
}

console.log( location.origin );  // 現在のオリジンを表示

たとえば,現在のドキュメントがhttp://example.jp:8080/list/?file=news.html#recentであった場合,locationオブジェクトの各プロパティの値は以下のようになります。

  • protocol → http:
  • host → example.jp:8080
  • hostname → example.jp
  • port → 8080
  • pathname → /list/
  • search → ?file=news.html
  • hash → #recent
  • href → http://example.jp:8080/list/?file=news.html#recent
  • origin → http://example.jp:8080

location.href以外に現在のドキュメントのURLを取得するためのインタフェース

現在のドキュメントの完全なURLを取得するためには,一般的にはlocation.hrefを使用しますが,ブラウザによってはlocation.href以外にも現在のドキュメントのURLを取得するためのインタフェースを持っている場合があります。以下にそれらの一部を示します。

  • document.URL
  • document.documentURI(IE10,11ではサポートされていない)
  • document.URLUnencoded(IE7~IE11のみサポート)

document.URLUnencodedはInternet Explorerのみでサポートされており,file:スキームなどの場合にdocument.URLとは異なる結果を返します(「パス区切りが/ではなく\になる」「パス中のスペースが%20になる」などの差があります)。

余談ですが,IE7およびIE8では,document.URLUnencodedは読み取り専用ではなく,値を代入した場合はlocation.hrefへの代入と同様にページの遷移が発生していました。

こういった,詳細がよくわからないIE独自の機能は,これまでも脆弱性の原因や攻撃の起点となることが多かったので,ブラウザ独自の機能は可能な限り使用を避けたほうがいいでしょう。

URLに認証情報が含まれている場合の注意点

document.documentURIは,location.hrefと同様に現在のドキュメントのURL全体を取得できますが,Basic認証の認証情報をURLに含めてドキュメントにアクセスした場合の挙動が異なります。具体的には,location.hrefにはユーザー名とパスワードは含まれませんが,document.documentURIにはブラウザによっては認証情報が含まれた値が格納されるという違いがあります。

たとえば,http://user:pass@example.jp/というURLへアクセスした場合,example.jpというサイトへユーザー名user”,パスワードpassという認証情報を使ってBasic認証経由でアクセスされることになりますが,ChromeやFirefoxではこのときURLが以下のように異なります。

  • location.href → http://example.jp/(認証情報を含まないURL)
  • document.documentURI → http://user:pass@example.jp/(ユーザー名およびパスワードを含んだURL)

「Basic認証の認証情報が含まれるURLへ攻撃者が被害者を誘導することで,XSSを発動させられる」という問題が,過去に何度か報告されています※1)。また,一般的には,認証情報を含めたURLへアクセスする必要性はありません。以上のことから,URLに認証情報が含まれている場合には「認証情報が含まれないようページを再ロードはする」「以降の処理を中止する」などの予防措置をとっておくといいでしょう。以下,URLに認証情報が含まれるときは強制的に認証なしのURLをリロードするコードの例です。

if( document.documentURI && location.href !== document.documntURI ){
    // URLに認証情報が含まれるときは強制的に認証なしのURLをリロードする
    location.href = location.href;
}
※1)
以下のブログエントリを参照。

著者プロフィール

はせがわようすけ

株式会社セキュアスカイ・テクノロジー常勤技術顧問。 Internet Explorer,Mozilla FirefoxをはじめWebアプリケーションに関する多数の脆弱性を発見。 Black Hat Japan 2008,韓国POC 2008,2010,OWASP AppSec APAC 2014他講演多数。 OWASP Kansai Chapter Leader / OWASP Japan Board member。

URL:http://utf-8.jp/

コメント

コメントの記入