読者です 読者をやめる 読者になる 読者になる

woshidan's blog

そんなことよりコードにダイブ。

セキュリティ勉強会に参加しました 3

CSRF セキュリティ 徳丸本 セッション管理 セッションIDの固定

ユーフォ12話すごいよかったですね。

今週の勉強会は外部の勉強会の準備で忙しい人が多くてお休みだったので、予習分を忘れないうちにまとめ。参加したので追記しました。

内容

  • セッション管理
    • Webじゃないアプリケーションでセッションを管理するということ
    • Webアプリケーションでセッションを管理するということ
    • ブラウザのクッキーでセッションを管理する
    • Railsのセッション管理について
    • セッションIDが固定されていると...
  • ブラウザ側のセキュリティ対策
  • クロスサイト・リクエストフォージェリ
  • 受動的攻撃と能動的攻撃
  • インジェクション系攻撃初級

何となく用語が曖昧だったので確認。

セッション管理

Webじゃないアプリケーションでセッションを管理するということ

OS上で動作するアプリケーションやsshで接続してコマンドを叩いている場合、起動しているアプリケーションやコマンドラインプロンプト*1が、それを利用しているユーザの情報や、その操作の情報、つまり、アプリケーションとユーザの状態を管理しています。

そして、アプリケーションを利用している間は、基本的に起動するときにアカウントを選択したユーザとして利用できていますよね*2

Webアプリケーションでセッションを管理するということ

一方、HTTPでリクエストを受け付けて動くWebアプリケーションの場合、アプリケーションを利用している間、ずっと特定のユーザのために動いてくれるわけではありません。

基本的にHTTPリクエストだけでコマンドを受け付けると、基本的にはそれまで誰によってどのような操作が行われていたか、ということは本来保存されません。

ユーザからリクエストを受けたサーバは、URIとHTTPリクエストに対応した処理*3を行ったあと、リクエストを送ったユーザにレスポンスを返したら、ユーザの事は忘れてしまいます。

なので、何か工夫をしないと、リクエストを送るたびに認証情報を送る必要があります。

ためしにAPIcurlで叩いているなどであったら、毎回トークンを入力しても、まあ仕方ないかな、という気がしますが、毎回は不便です。

この工夫をして、ログインしてからログアウトするまで、Webアプリケーションを利用している間は同じユーザが利用している、と認識できるようにトークン等を管理することをWebアプリケーションのセッション管理というみたいです*4

ブラウザのクッキーでセッションを管理する

セッション管理のために、認証が済んだらユーザにひもづいた情報をブラウザのクッキーに保存し、リクエストの度にクッキーに保存された情報も送る事で、アプリケーションにログインしている状態*5を表現しています。

このとき、クッキーが通信路で盗聴されたりユーザに見られたりする可能性を考えて、直接ユーザーIDをクッキーに保存するのではなくて、サーバに保存している情報を取り出すための値をクッキーに入れておく方がよいようです。

また、この値は推測できないようなものにしておく必要があります。

Railsのセッション管理について

Railsのセッション管理は、デフォルトだと_app_name_sessionというクッキーに暗号化したセッションIDを保存するcookie_storeの形を通して行われます。

このcookie_store、デフォルトだと、サーバ側のセッションIDを破棄してくれない*6ので、実アプリケーションで使う場合、ログアウト処理やユーザ情報を変更した前後等は注意します。

また、sessionの管理機構はいくつかあって、セッション管理機構を切り替えやすいようにか、セッションの値そのものは、@delegeteというインスタンス変数に入っていました。

# コントローラで
session['foo'] = 'bar'
session.instance_variable_get('@delegate')
=> {"session_id"=>"92a5ddceb5041bfa6b5db66fd308448b", , "foo"=>"bar"}

参考:

Railsのセッション管理方法について - Programming log - Shindo200

Rails SessionにCookieStore使った時の問題点 - OAuth.jp

Railsのセッション機構に関しては、他に「ActiveRecordSessionStore」「DalliStore」等があります。

DalliStoreは今度一回自分で設定してみたいですね。

セッションIDが固定されていると...

丁度、cookie_storeの場合、サーバ側ではセッションIDを意図的に消さない限りは保存されているバージョンがある、という話をしたところで、 セッションIDが固定されていて、サーバ側でログアウト時にセッションIDをきちんと削除しない場合の話を少し考えてみます。

ログインしたユーザのクッキーを攻撃者が何かの方法で盗みます。 上記の場合、サーバ側では、ユーザーがログアウトした後もクッキーの値にセットしたセッションIDをそのまま保存しています。

攻撃者が、盗んだセッションIDをクッキーにセットしてからサーバへリクエストを送ると、サーバーでは、そのリクエストをログインしていたユーザからのものと判断して、ログインしていたユーザに表示する画面を表示します*7

ログインに関する重要な情報を更新したり、ログアウトしたタイミングでクッキーを無効にして、新しいものを発行したりするように注意します*8

ブラウザ側のセキュリティ対策

ブラウザのバージョンをあげないと、セキュリティが〜という話はよく聞きますが、 ブラウザ側では、基本的に「JavaScriptで出来る範囲を限定させる」「利用者に配布元を確認させる」という方針で対策を行っているそうです。

「利用者に配布元を確認させる」は主に、ブラウザのプラグインの話だそうで、「JavaScriptで出来る範囲を限定させる」というのは、たとえば、違うサイトの要素を表示させている部分に対しては、JavaScriptを使ってcookieを覗けないようにする、などのことがあげられます。

後者のJavaScriptに対するセキュリティ上の制限を、同一生成元ポリシーと言います。

クロスサイトスクリプティング

つまり、ブラウザによって、違うサイトの内容を表示している要素の中へはJSでアクセスできないようにしましょうという対策がとられているので、では、なんとかして、サイトの内部にJavaScriptを送り込んでしまおう、というのはクロスサイトスクリプティングというそうです。

主に、フォームに入力した内容が動的にHTMLに挿入されるような箇所を狙ってJavaScriptの文字列を入力してしまおう、ということが行われます。

ところでこれ、どうクロスサイトしてるのか、ちょっと分からないので、理解不足っぽいですね...。

クロスサイト・リクエストフォージェリ

攻撃者のサイトのフォームの送信先が攻撃対象のサービスになっており、攻撃者のサイトを見ているユーザーの不正なリクエストを送らせる、 といった攻撃を「クロスサイト・リクエストフォージェリ」というみたいです。

フォームを表示した際、自サイトからである事を示すCSRFトークンを発行し、そのトークンがリクエストに無ければリクエストを弾く、という対策が考えられます。

フォームが偽造されていて、フォームの送信先が実はショッピングサイトでした、高額な商品を買わされてしまった。 というのをショッピングサイトの方で防ぎたいよね、みたいなイメージなのでしょうか...。

受動的攻撃と能動的攻撃

  • 能動的攻撃(攻撃者がWebサーバに対して直接攻撃する事)
  • 受動的攻撃(Webサイトに罠を仕掛けて、サイトの利用者を通してアプリケーションを攻撃)

インジェクション系攻撃初級

ヌルバイト文字等、要素、文の終端にあたる部分を入れて、一旦入力値を区切る。

たとえば、ヌルバイト文字をリクエストパラメータにしこませて、バリデーションの際に一旦入力値はヌルバイト文字のところで終了した、とバリデーションのメソッドに勘違いをさせて、攻撃につながる不正な文字列をそのまま表示させる、など。

正直、このへんは読んでいてテンションが上がっていて、ろくでもなさがにじみ出てますね...。

追記

あらためて読んで印象に残ったところなど。

  • クッキーはサーバ側からブラウザに管理するように指示された値
  • セッションを強制させる、とは
  • 社内の古いブラウザ用検証機でクッキーモンスターバグ検証できないかな

クッキーを電波から盗まれたら

ログインしている最中に、WireShirkかなにか使ってフィルタリングされていないセッション管理クッキー盗まれたら、それは普通に乗っ取れるのだろーか。

何かのサイトで、変なIPからログインされています、パスワード変えてくださいという通知が来て、変えた事があるけれど。

*1:まあ、これも広義の起動しているアプリケーションですが

*2:アプリケーションを終了すると、システムファイルに結果等を保存したりして、一旦「アプリケーションとユーザの状態」の管理は終了しますが

*3:Railsでアクションに書いているような

*4:sessionメソッドを叩くことも、クッキーを利用する事も手段であって目的ではないみたいです

*5:通信的にはつどつど接続切れてるんですが

*6:少なくともそういう時期があったらしい

*7:まだ、セッションIDが盗まれたユーザのセッションIDを消去していないので

*8:そもそもそんなことしなくていいように、フレームワークを利用する、というのですが、あんまりフレームワーク盲信して勉強しないと、セキュリティパッチの意味を読んでても、いつまで経っても分からないような気がします。。作るかどうかは別として、一度は自分が作るつもりで勉強したい...