携帯電話向けWebアプリのセッション管理はどうなっているか
そうは言っても、本書にはブログやSNSなど認証が必要なアプリケーションも登場する。本書で採用している認証方式はこうだ。
- 携帯電話の個体識別番号を用いた、いわゆる「かんたんログイン」のみを使う
- 認証状態をセッション管理機構で維持しない。全てのページで毎回認証する
- そのため、「iモードID」など、ユーザに確認せずに自動的に送信されるIDを用いる
つまり、全てのリンクやFORMのアクションに、「guid=ON」を指定しているのだ。
これは、携帯電話向けWebアプリケーション開発の定石とは言えないだろう。本書を勉強して著しく実力をつけた開発者がいたとして、いざ本格的なサイトを開発しようとすると非常にとまどうのではないか。セッション管理は、Webアプリケーション開発の基本であるのだから、最初からその基本をきちんと教えるべきだろう。
この手法の限界は多いのだが、たとえば以下のような問題がある
- iモードIDはSSLの場合送信されないので、SSL対応のサイトは開発できない
- セッション情報をすべてhiddenなどで引き回さないといけないので、複雑なアプリケーション開発は困難
- PCサイトとの互換性がない。PCと携帯電話の相互乗り入れするサイトも作れない(あるいは困難)
- 標準的なセキュリテイ対策手法が使用できない
などなど。このように、一般のPC向けサイト開発とはまったく互換性のない手法を敢えて教える必要があるのか。
このような事態を予見するような意見は既にあった。高木浩光氏のインターネットにおけるセキュリティとプライバシーの両立についてに出てくる「劣化するWeb開発技術者」(スライドP42から下記に引用)がそれだ。
まさに上記のような、『「セッションID」という概念を知らない』技術者、『契約者固有IDがないとWebアプリを作れない』技術者を量産するような内容になっているのだ。
この方法の欠点として、「標準的なセキュリテイ対策手法が使用できない」ことを指摘したが、実際問題として、本書のアプリケーションでは、クロスサイト・リクエストフォージェリ(CSRF)対策をまったく考慮していない。このため、正規ユーザの権限にてSNSの書き込みや削除などが行えるようだ。
以下は、本書のSNSの日記削除ページから引用だ。日記を削除してよいか確認したのち、「削除実行」のボタンの部分のフォームだ。
<form action="deletediary.php?guid=ON" method="post"> <div style="text-align:right;"> <input type="hidden" name="exec" value="1" /> <input type="hidden" name="id" value="<?php varout($entry['id']) ?>" /> <input type="submit" value="削除実行" /> </div> </form>
上記のように、CSRF対策のトークン類はとくに渡されていない。携帯電話の場合、Refererをチェックすることもできない(docomoの大多数の端末がRefererに対応していない)ので、CSRF脆弱性がある。
通常のCSRFは、正規ユーザが「たまたまログイン状態だった」場合に被害を受けるものだが、本書の方法だと「自動的に勝手にログインされる」わけだから、CSRFの影響を受ける確率は高くなる。
対策は容易ではない。元々セッション管理をしていないのだから、一般的なCSRF対策に用いられるトークン類を覚えておく場所がない。docomoの場合、Refererが送出されない端末が大多数なのでRefererをチェックするわけにも行かない。だからといって、個体識別番号などをトークンとして用いることもできない。個体識別番号は秘密情報ではなく、どのサイトにもばらまかれるものだからだ。個体識別番号を暗号化する、あるいは適当なSaltをつけてハッシュ値を求めるなどの方法が考えられるが、暗号アルゴリズムの選定や、鍵やSaltの管理などが大変で、そんな苦労をするくらいなら、あっさりPHPのセッション管理機構を使う方が楽で安全だ。それに、携帯電話向けWebアプリ開発では、セッションIDをURLに埋め込むことが定石的に行われるが、この方法の場合、原理的にCSRF脆弱性は発生し得ない。最初から秘密情報をURLに埋め込んでいるためだ。このセッションIDは第三者は知り得ないので、CSRF攻撃を掛けようがないのだ。
ただしこちらの方は、CSRF脆弱性は心配ないが、残念ながらセッションフィクセーションの問題がある。本書P270には以下のような認証プログラムがある(login.php)。
// 前略 // 【徳丸注】ここまでくれば認証OK // 会員データをセッションに格納する session_start(); $_SESSION['name'] = $name; // 会員ページにリダイレクトする【後略】
認証成功時にセッションIDの再生成をしていないので、セッションフィクセーションの脆弱性が生じる(参考)。session_start();の後に、session_regenerate_id(); を追加する必要がある。携帯向けWebアプリの場合、URLにセッションIDを埋め込むので、CSRF脆弱性の余地がない代わりに、セッションフィクセーションの攻撃は受けやすくなる。忘れずに対策しておきたい。
このようなセッション管理系の脆弱性のチェックリストとしては、ウェブ健康診断仕様の「(K) セッション管理の不備」が利用できる。以下に引用する。
(K)セッション管理の不備
検出パターン | 脆弱性有無の判定基準 | 備考 (脆弱性有無の判定基準詳細、その他) | |
---|---|---|---|
1 | ログインの前後でセッションID が変化するか | セッションID が変わらない場合は指摘 | − |
2 | 言語・ミドルウェアの備えるセッション管理機構を使用せず手作りのセッション管理機構を使っていないか | 手作りのセッション管理機構を使用している場合は指摘 | セッションID のパラメータ名等で、言語・ミドルウェアのセッション管理機構を使用しているかを判断します。判断がつかない場合には、"手作りの疑いあり"として報告します。 |
3 | SSL を使用するサイトの場合、セッションID を保持するCookie にセキュア属性が付与されているか | Cookie のセキュア属性が付与されていない場合は指摘 | - |
4 | Cookie をオフにしてアクセスした場合、セッションIDがURL 埋め込みにならないか | セッションID がURL 埋め込みの場合は指摘 | リファラから漏洩するおそれがある場合にのみ、脆弱と判定します。(5 を参照) |
5 | 携帯電話向けサイト等でセッションID をURL 埋め込みにしている場合、外部リンクからReferer 経由でセッションID が漏洩しないか | Referer からセッションID が漏洩する場合は指摘 | PC/携帯サイト両方が対象。外部へのリンク(検査対象とは異なるホスト上のページへのリンク)が存在する場合にのみ脆弱と判定します。セッションID の漏洩が問題とならない場合(認証等の機能が無いケースや、ワンタイムなセッションID を使用しているケース)は報告から除外します。 |
携帯電話向けアプリケーションの場合、上記3項と4項は該当しない(Cookieを使っている場合は該当する)が、それ以外(1、2、5)は対策する必要がある。このあたりも含めて、携帯電話向けWebアプリケーションのセッション管理をどのように書けばよいかは、近くまとめようと思っている。