SessionSafe: Implementing XSS Immune Session Handling

SessionSafeは、ハンブルグ大学のMartin Johnsさんが書いたWeb APの方式案です。

もしWeb APにXSS脆弱性があって、これが攻撃されたとしても、

  1. セッションIDが盗まれない
  2. 当該ページ以外の情報が窃取・改竄されない

ことを目指しています。

面白いなーと思ったので、内容について少し書きます。

なお、元記事を高速斜め読みしたので、この日記の内容には間違いが含まれているかもしれません。興味のある方は原本を見てください。

セッションIDが盗まれない

以下の二つのドメインがあるとします。

www.example.com
secure.example.com

セッションIDのCookieは、secureサブドメインに発行します。

Webページを表示する際はwww.example.comのURLにアクセスします。そこで返すHTMLに色々と仕掛けを施します。

HTMLの仕掛け

■画像
HTMLには以下のような画像(imgタグ)が含まれています。

<img src="http://secure.example.com/getCookie.cgi?rid=xxx">

ブラウザはsecureサブドメインのgetCookie.cgiにアクセスします。リクエストには、あらかじめセットされているセッションID Cookieが含まれます。

getCookie.extは1x1ドットの意味の無い画像を返します。

Ajax
HTMLは、初期状態では意味のあるコンテンツを含んでいません。画面表示コンテンツは、Ajaxで取りに行きます。

Ajaxアクセス先:
http://www.example.com/a.cgi?rid=xxx

サーバは、このAjaxアクセスの前に、画像に正しくリクエストがされている場合だけ、然るべきHTMLコンテンツを返します。返されたHTMLはdocument.write()して画面表示します。

ポイント
  • Ajaxでのdocument.write()でXSSが生じても、ドメインが違うためセッションIDは奪われない。
  • secureサブドメインは固定の画像しか返さないため、XSSリスクが極めて低い。
  • ridはサブセッションIDのような役割を果たし(セッションIDと関連付ける)、secureの画像へのリクエストと、wwwのAjaxリクエストを結びつける。
  • ridはワンタイムで予測困難な値にする。

当該ページ以外の情報が窃取・改竄されない

通常、どこかのページに存在するXSS脆弱性が突かれた場合、同一ホスト・プロトコル・ポートのページで取扱う情報は、そのページにXSS脆弱性が無くても、攻撃者に窃取・改竄されてしまいます。

攻撃の手口としては、XSSを突いて、

  • XHR(XMLHTTPRequest)を仕込む
  • 裏に別ウィンドウを起動してメインのウィンドウを見張る

などがあります。

これらを防ぐために、SessionSafeでは以下の二つの対策を取ります。

  • 他のページのURLを予測不可能にする
  • サブサブドメインをスイッチする

これらについて、以下に書きます。

他のページのURLを予測不可能にする

攻撃者が、他のページ(例えば個人情報を表示するページ)のURLを知ることができないようにします。URLが判らなければ、当然XHRなどを用いて個人情報を奪うなどの攻撃はできません。

具体的には、URLに予測不可能なGETパラメータを付加します。

<a href="showUserInfo.cgi?rnonce=xxxx">個人情報照会へ</a>

ただこれだと、攻撃者はXSSを突いて、rnonceを奪うことができます。

ですので、

<a onclick="URLRandomizer.go('showUserInfo');">個人情報照会へ</a>

のようにして、rnonceをURLRandomizerオブジェクト内に隠蔽します。

しかしこれでも、URLRandomizerオブジェクトのコードがHTMLソース内に含まれている場合、innertHTMLなどでrnonceを抜かれる恐れがあります。

そのため、rnonceはAjaxでサーバに取りに行くようにして、ソース内に埋め込まないようにします。また、このAjaxリクエストでは、セッションIDと関連付けられたワンタイムトークンを使用し、攻撃者のAjaxがrnonceを取得できないようにします。

サブサブドメインをスイッチする

これは、「裏に別ウィンドウを起動してメインのウィンドウを見張る」タイプの攻撃への対策です。

単純に、

s01.www.example.com/
s02.www.example.com/
・・・

のようにページ毎にサブサブドメインを変えてやります(apacheではドメイン設定でワイルドカードが使えるので、それを使う)。

ドメインが変わると、裏のウィンドウからメインウィンドウを監視できなくなります。

感想

  • 明確なセキュリティ上の欠陥は思いつかず。
  • JavaScript=Off設定のユーザ、古いブラウザのユーザなどは使えない。
  • 戻る/リロードなどのナビゲーションに制約が生じる(元記事に記述有り)。
  • 仕組みが複雑=開発工数が増える。フレームワークなどができれば緩和されるか。
  • 現状の壊れやすいHTML/JavaScript基盤を前提として、その上にいかに安全なWeb APを作るのか、という思考実験として、とても面白い。
  • ただやっぱり無理やり感がある。本来は基盤の方をどうにかすべきなんだろう。