VOYAGE GROUP エンジニアブログ

voyagegroup_techのブログ
VOYAGE GROUPエンジニアブログです。

Rails

Rails(Web)アプリケーションのセキュリティ(パスワードハッシュstretch編)

こんにちはECナビ山口(tadasy)です。
忙しぶるのはどちらかというと得意です。

最近PeXという部署からECナビ事業本部というところに異動したのでrubyは触ってません。
えぇまったく。

前回の更新からだいぶ期間があきました。
まぁアレです。忙しかったのです。
つれー、つれーわー、実質(ry

前回はログファイルのセキュリティについて触れました。
Rails(Web)アプリケーションのセキュリティ(ログファイル編)

今回はRails2系でよく使われるプラグインのrestful_authenticationでの
パスワードハッシュ化について書きます。
※3系のことはよくわからんです。

restful_authenticationとは?

詳しくは
restful-authentication
を見てもらえればと思いますが
ざっくり説明すると
Webサービスなんかでよくあるユーザ管理(ユーザの登録、ログイン、ログアウト)なんかの機能をまとめた便利プラグインです。

パスワードハッシュ化&stretching

パスワードのハッシュ化とstretchingについては下の春山さんの資料が大変参考になります。

パスワードの話

restful_authenticationでのstretching

ではrestful_authenticationがstretchingしているところを見てみます。
RAILS_ROOT/vendor/plugins/restful-authentication/lib/authentication/by_password.rb

だいぶソースを端折っていますが、REST_AUTH_DIGEST_STRETCHESという定数で繰り返し回数を指定して
stretchingしているようです。
この定数は以下のファイルで設定されているようです。
RAILS_ROOT/config/initializers/site_keys.rb

このファイルは下のコマンドでモデルを作ったときに自動生成されます。
ruby script/generate authenticated user sessions

何回stretchする?

デフォルトの設定では10回のstretchをしているようです。
資料にも書いてありますが、回数が多ければ強度を増すことができます。
ただ、回数が多ければ多いほどハッシュ化に時間がかかりますし、ログイン認証処理にも同様に時間がかかる様になります。
なので、サービス要件を考慮した回数でstretchしたらいいと思います。

ちなみに僕が作るときは1000回以上はstretchするようにしています。
というのも、以前1000回のstretchingでサービスを構築した時の実績として、性能面ではサービスの要件を十分に満たせるレベルでしたし(むしろ速かった)、強度的にもある程度担保できていたと考えるからです。

ただ次回以降は、もう少しstretchして、5,000回くらいで試してみてもいいかもしれないとも思っています。

Rails(Web)アプリケーションのセキュリティ(ログファイル編)

はじめまして、ジョニー・デップに激似の山口(@tadasy)と申します。

僕はPeXという部署で働いておりまして、
PeXpaycaグルピの運営に携わっております。

ECナビではサービスを作るときは、よくPHPを使われるのですが、
PerlやPython,Rubyなどで構築されているサービスもちょいちょいあります。

僕が所属しているPeXという部署でも、主力サービスであるPeXはPHP(symfony)で構築されていますが
payca、グルピはRuby(Ruby on Rails)で構築しました。

そのRailsのwebアプリケーションを構築・運用していく中で、セキュリティ的に気をつけたポイントを
何回かにわけて心折れるまで(おそらく2,3回)書いていこうと思います。

というわけで第1回はログファイルについてです。

ログファイルのセキュリティ?

ログファイルのセキュリティって言われてもあまりピンとこないかもしれませんが、Railsではproduction環境でもデフォルトで、HTTPのパラメータが全部ログに出力されてしまうとこです。そりゃもう全部です。
ログイン画面のパスワードはもちろん、会員情報登録画面の個人情報も当然、ログファイルの書かれます。

せっかくDBに会員パスワード情報を復号できない形でハッシュ化して保存していても、ログファイルに書かれてしまったら、もろもろ台無しです。

回避方法

action packのaction_controllerには filter_parameter_logging というクラスマクロが定義されています。
これを使うことでログファイルへの書き出しを抑止できます。

上記のように記述するとログファイルに記載される該当するパラメータ値が[FILTERED]という文字に置き換えられます。

  • filter適用前のログファイル
  Parameters: {..."user"=>{"password_confirm"=>"naisho", "last_name"=>"石鍋", "password"=>"naisho", "login"=>"loginid", "first_name"=>"太郎"}...}
  • filter適用後のログファイル
  Parameters: {..."user"=>{"password_confirm"=>"[FILTERED]", "last_name"=>"石鍋", "password"=>"[FILTERED]", "login"=>"loginid", "first_name"=>"太郎"}...}

適用後のログファイルをみると"password_confirm"というパラメータも置き換得られていることがわかります。
これは、
filter_parameter_logging :password
と書くことで
/password/i

という正規表現でパラメータ名をチェックされるためです。

詳しい使い方

詳しい使い方についてはaction_controller/base.rbにfilter_parameter_logging定義されていますので
そちらのコメント欄が参考になります。
一応コメントを引用しておきます。

# Replace sensitive parameter data from the request log.
# Filters parameters that have any of the arguments as a substring.
# Looks in all subhashes of the param hash for keys to filter.
# If a block is given, each key and value of the parameter hash and all
# subhashes is passed to it, the value or key
# can be replaced using String#replace or similar method.
#
# Examples:
#   filter_parameter_logging
#   => Does nothing, just slows the logging process down
#
#   filter_parameter_logging :password
#   => replaces the value to all keys matching /password/i with "[FILTERED]"
#
#   filter_parameter_logging :foo, "bar"
#   => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
#
#   filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
#   => reverses the value to all keys matching /secret/i
#
#   filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
#   => reverses the value to all keys matching /secret/i, and
#replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
ブロックも渡せるらしく、かなり柔軟な使い方ができそうですが
特に使い道が思いつかないので、今はシンプルに利用しています。


注意
Rails3系ではfilter_parameter_loggingはdeprecatedになっており、別の使い方が推奨されているようです。
記事検索
QRコード
QRコード