HTTPを使用したWebアプリケーションにおいて、安全なセッション管理を行うことは難しい問題である。タブブラウザによる画面の複数起動や、Webブラウザの戻るボタン/更新ボタンの押下といった、予期しない画面遷移に起因するバグの発生に頭を悩ませることは多いだろう。
大きな問題が発生しないならば、画面遷移の仕様上の制限をクライアントに許容してもらう選択肢もあるだろうが、不正な画面遷移を利用したセキュリティホールが存在するならば、放置しておいてよい問題ではなくなる。今回はセッション管理を安全に行うための基本的な注意点について解説していこう。
セッション固定攻撃(Session Fixation)という脆弱性を耳にしたことはあるだろうか。脆弱性そのものの詳しい解説は本稿の趣旨ではないため割愛するが、簡潔に説明すると、以下のような手順を踏むことによりセッション情報がハイジャックされてしまう問題である。
この攻撃は以下の条件がそろうときに成立する。
Strutsを使用したアプリケーションでは攻撃の成功条件がそろいやすいため、この問題を必ず認識しておく必要がある。攻撃の成功条件がそろいやすいという根拠および対策について順を追って説明していこう。
J2EEを使用したWebアプリケーションにおいてセッションIDはセッションオブジェクトを生成した段階で発行される。セッションを開始する際には、以下のような実装がログインロジック内で組み込まれることが多いだろう。
/** ログイン処理を実行して成功したらセッションを発行 */
if (login(userId, password)) {
HttpSession session = request.getSession(true);
// sessionにログイン情報をセット
}
一見ログインに成功しないとセッションIDが発行されないように見える実装だが、Strutsを使用したアプリケーションでは落とし穴が存在する。個々のActionクラスはRequestProcessorのprocess()メソッドにより呼び出される流れを取るが、process()メソッド内においてSession呼び出しのロジックが実装されているからだ。
以下はSession呼び出しのロジックの一例である。多言語対応のため使用される言語情報を取得するために、緑色で示す個所においてSessionが呼び出されている。
public void process(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
// 中略
// Select a Locale for the current user if requested
processLocale(request, response);
// 後略
protected void processLocale(HttpServletRequest request,
HttpServletResponse response) {
// 中略
// Has a Locale already been selected?
HttpSession session = request.getSession();
if (session.getAttribute(Globals.LOCALE_KEY) != null) {
return;
}
// 後略
従って一般的な実装においては、セッションIDの発行タイミングは開発者が制御できるものではなく、Strutsにより自動的に処理されるということが分かるだろう。
ログイン画面がActionクラスを介さない静的コンテンツとして実装されていたとしても、空の認証情報を設定してログイン処理を実行するなどの手段で、Actionクラスが呼び出されるリクエストを送信することにより、セッションIDはログイン前であっても強制的に発行される結果となる。
Copyright © ITmedia, Inc. All Rights Reserved.