概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Rails 6 adds Purpose Metadata to Cookies – Saeloun Blog
- 原文公開日: 2019/11/12
- 著者: Prateek Choudhary
- サイト: Saeloun -- Ruby on Railsのコンサルティング会社で、Rails + React開発のほかに、React Nativeによるモバイルアプリ開発も手がけています。
Rails 6のcookieに「purpose」メタデータが追加(翻訳)
Action Dispatchが提供するcookies.signed
とcookies.encrypted
は、ユーザーによるcookie値の不正な改変を防ぐのに利用できます。
例
# ユーザーがcookie値を改変できないようにする
cookies.signed[:proxy_id] = current_admin.id
# このときのクライアント側のcookieの中身
# MTAx--fd47225e9e6de0710a4f84104d73fec1e4d94c65
# cookie値の改変だけでなく読み出しもできないようにする
cookies.encrypted[:current_zip] = current_user.zip
# このときのクライアント側のcookieの中身
# aHNzb2dxVkN1bE1MQTd0MnFsSkZ2dz09LS1tM2NHcVZQbjRoT0RVOVdvdE9FdHZnPT0%3D--be007d00dda3678f79fda9d2a7bcfacc6a760919
何が問題だったか
Rails 6より前は、上述のメソッドでcookieの中身しか署名されず、名前には署名されていませんでした。
このため、あるcookieから別のcookieに署名済みデータをコピペされる可能性があるというセキュリティ上の脆弱性がありました。
#17136で、cookieの値をコピーして別のユーザーのところで使える可能性がある例が示されました。
Rails 6以後
Rails 6では、#32937でpurpose
メタデータがcookieに追加されました。
このメタデータではcookieの名前が設定に使われ、それがcookieに埋め込まれます。
これによって、あるcookieの値を別のところにコピペされることを防止します。
例
cookies.signed[:proxy_id] = current_admin.id
# このときのクライアント側のcookieの中身
# eyJfcmFpbHMiOnsibWVzc2FnZSI6Ik1UQXgiLCJleHAiOm51bGwsInB1ciI6ImNvb2tpZS5wcm94eV9pZCJ9fQ%3D%3D--ac22ece5b73ea1fbd3de8e925be57a173e9f8a2b
上の例では、--
より前のデータはBase64
でエンコードされた値で、そこにpurpose
メタデータとexpiry
メタデータが埋め込まれています。
このメタデータが設定されていない従来のcookieについては引き続き配慮されます。
この機能をあえて外したい場合は以下の設定が使えます。
config.action_dispatch.use_cookies_with_metadata = false
この設定はデフォルトでtrueになります。