Understanding & Sharing Rails sessions

Understanding & Sharing Rails sessions

Understand how Rails sessions work, the crypto applied, the risks if you are using a version of Rails older than 4.1 and learn how to share the session with apps in other languages.

C69521d6e22fc0bbd69337ec8b1698df?s=128

Matt Aimonetti

September 13, 2014
Tweet

Transcript

  1. Matt Aimonetti Splice: Go, Ruby, JS, Obj-C, C#, C++, C

    Matt Aimonetti - splice.com - @mattetti
  2. None
  3. None
  4. None
  5. “Knowledge is power” France is Bacon

  6. “Crypto is hard” Bruce Schneier

  7. “Barcelona is awesome” My wife

  8. None
  9. The events depicted in this presentation took place in California

    in 2014. ! At the request of the survivors, the names have been changed. Out of respect for the dead, the rest has been told exactly as it occurred.
  10. Bob Alice

  11. Abe

  12. None
  13. None
  14. None
  15. None
  16. None
  17. None
  18. Conchita

  19. None
  20. None
  21. None
  22. Dave

  23. None
  24. None
  25. None
  26. {}

  27. session.current_user

  28. None
  29. None
  30. Frank

  31. None
  32. None
  33. None
  34. None
  35. None
  36. ActiveSupport::MessageVerifier

  37. Splice::Application.config.secret_key_base = "f7b5763636f4c1f3ff4bd444eaccaca295d87b 990cc104124017ad70550edcfd22b8e89465398 254e0b608592a9aac29025440bfd9ce42579835 ba06a86f85f9" config/initializers/secret_token.rb config/secrets.yml Before Rails

    4.1 After Rails 4.1
  38. None
  39. key_generator = ActiveSupport::CachingKeyGenerator.new( ActiveSupport::KeyGenerator.new( secret_key_base, iterations: 1000 ) )

  40. Password-Based Key Derivation Function 2 ! AKA ! PBKDF2

  41. derived_secret = key_generator. generate_key("Rails salt")

  42. None
  43. SHA-­‐1(Secret,  Salt  +1) SHA-­‐1(Secret,  Salt) SHA-­‐1(Secret,  Salt)

  44. verifier = ActiveSupport::MessageVerifier. new(derived_secret) ! msg = { user: "Matt",

    role: "villain"} ! signed_message = verifier.generate(msg) ! # => "BAh7BzoKd2hlcmVJIg5CYXJjZWxvbmEGOgZFVDoJd 2hhdEkiC0JhcnVjbwY7BlQ=-- ad7af07ad5b384d458b7cf8a962c04fc53ed81d1"
  45. BAh7BzoKd2hlcmVJIg5CYXJjZWxvbmEGOgZFV DoJd2hhdEkiC0JhcnVjbwY7BlQ= -- ad7af07ad5b384d458b7cf8a962c04fc53ed8 1d1 Base 64 encoded version of

    the dumped message Signature of encoded message
  46. Marshal.load(Base64.decode64(“BAh7…”)) # => {:user=>"Matt", :role=>"Villain"}

  47. ActiveSupport::MessageEncryptor

  48. crypt_secret = key_generator.generate_key( "signed encrypted cookie") ! encryptor = ActiveSupport::MessageEncryptor.new(

    secret, crypt_secret) ! message = encryptor. encrypt_and_sign({msg: "hello world"}) ! encryptor.decrypt_and_verify(message) # => {:msg => "hello world"}
  49. None
  50. None
  51. None
  52. None
  53. None
  54. None
  55. None
  56. None
  57. None
  58. None
  59. Wendy

  60. Eve

  61. Splice::Application.config.secret_key_base = "f7b5763636f4c1f3ff4bd444eaccaca295d87b 990cc104124017ad70550edcfd22b8e89465398 254e0b608592a9aac29025440bfd9ce42579835 ba06a86f85f9" config/initializers/secret_token.rb config/secrets.yml

  62. None
  63. None
  64. None
  65. None
  66. class ::Pwned def marshal_load(*args) end def marshal_dump end end

  67. class ::Pwned def marshal_load(*args) ActiveRecord::Base.connection.tables.each do |t| ActiveRecord::Base.connection.drop_table(t) end end

    def marshal_dump; end def by "Eve" end end ! session[:pwned] = ::Pwned.new
  68. None
  69. request.cookie_jar. signed_or_encrypted. send(:serializer) ! => Marshal

  70. Rails.application.config.action_dispatch. cookies_serializer = :hybrid only store simple objects!

  71. None
  72. None
  73. None
  74. http://godoc.org/github.com/mattetti/goRailsYourself/crypto

  75. type Person struct { Id int `json:"id"` FirstName string `json:”first_name"`

    LastName string `json:”last_name"` Age int `json:"age"` } ! ! john := Person{Id: 12, FirstName: "John", LastName: "Doe", Age: 42}
  76. railsSecret := "fromYourConfig" cookieSalt := []byte(“cookie_salt") signedCookieSalt := []byte("scookie")

  77. kg := KeyGenerator{Secret: railsSecret} ! // derived keys secret :=

    kg.CacheGenerate(cookieSalt, 32) signSecret := kg.CacheGenerate(signedCookieSalt, 64) ! e := MessageEncryptor{ Key: secret, SignKey: signSecret}
  78. /* john := Person{Id: 12, FirstName: "John", LastName: "Doe", Age:

    42} */ ! msg, err = e.EncryptAndSign(john) if err != nil { log.Fatal(err) }
  79. // decrypting the person object contained in //the session var

    sessionContent Person err = e.DecryptAndVerify(msg, &sessionContent) if err != nil { log.Fatal(err) } // Person{Id:12, FirstName:"John", // LastName:”Doe”, Age:42}
  80. None
  81. None
  82. None
  83. None
  84. None
  85. None
  86. None
  87. Questions @mattetti ! ! splice.com