Rails 4: Cookie の値を見る


Rails の cookie の値はどうなっているんだろうかと思って覗いてみました。

環境

  • Rails 4.2.5
  • Ruby 2.0.0p481

コード

先人のコードをそのまま使いました。 bundle exec rails c でコンソールを起動して下のコードを実行します。

cookie にクッキーの値を代入し、 keysecret_key_base の値を代入すれば処理できます。

cookie の値

cookie の値は たとえば Chrome だったら Developer Tools で Resources を表示し、 左側に表示されるツリーから該当の Cookie を選択すれば値を取得できます(Version 47.0.2526.106 で確認)。

Cookie は name と value の組になりますが、 Rails 4 が作成する Cookie の name は 標準で _xxx_session の形になります。 これは Rails.application.config.session_store で指定されているもので、 標準では config/initializers/session_store.rb で記述されています。

secret_key_base の値

標準では config/secrets.yml に記載されています。

salt と secret

上のコードでは saltsecretconfig で設定されている値を渡しています。 標準では “encrypted cookie” と “signed encrypted cookie” になっています。

これらの値は コントローラの中で cookies という変数チェックすると確認できます。

クッキーの値の例

Rails のテスト用アプリケーションでクッキーの値を取得してみました。 テスト用アプリケーションでは devise gem を使用しており、 クッキーを取得したとき ユーザID 2 のユーザでログインしていました。

デコードの処理内容

クッキーデコード時の処理内容を確認します。

  1. CGI.unescape でクッキーに入っている値を URLデコード します。

  2. キージェネレータを作成します。 キージェネレータはシークレットキーの値とイテレーション回数をインスタンス変数にもつオブジェクトで、初期化処理は次のようになっています。

    デコード時にiterationsに 1000 を代入しているのは、Rails::Applicationクラスで次のように1000が使用されているからです。

  3. salt を元にキーを作成します。 メソッドgenerate_keyは下のように定義されています。

    OpenSSL::PKCS5.pbkdf2_hmac_sha1 はハッシュ関数 sha1 を用いて暗号化に使用するキーを生成するメソッドで、 ここでは 1000回 イテレーションを繰り返しています。

  4. sign_secret を上と同様にして生成します。

  5. MessageEncryptor のオブジェクトを生成します。 MessageEncryptorのイニシャライザは下記のようになっています。

    options[:chiper]は設定されないまま実行されますから、 AES-256-CBC が暗号化方式として設定されます。 AES は共通鍵暗号で、 ここで作成したMessageEncryptorオブジェクトはencryptdecryptが可能です。

  6. verify を行って decrypt します。 verify を行うのは padding attack を防ぐためだそうです。 単純に decrypt するわけではないので、 たとえば secret の値が誤っていたりするとエラーが発生して復号後の文字列が取得できません。

cookie の値を作る

前節で書いたのと同じ要領で MessageEncryptor のオブジェクトを作成して encrypt_and_sign を実行すれば cookie の値を作成できます。 encrypt_and_signメソッドは実行する度に結果が変わります。