Given the session key and secret, how can we decrypt Rails cookies?

后端 未结 5 1056
感动是毒
感动是毒 2020-12-24 02:37

I\'ve got a question about how Rails handles cookie encryption/decryption.

I\'ve got this in my config/environment.rb

  config.action_controller.sess         


        
相关标签:
5条回答
  • 2020-12-24 03:13

    If you pull the session.data field straight from the session data stored in your app's database (if you are using active_record_store in your environment.rb file)

    config.action_controller.session_store = :active_record_store
    

    ... here is how you decode it and return the hash:

    Marshal.load(ActiveSupport::Base64.decode64(@session.data))
    

    ... or in Rails >= 3.2 (thanks Chuck Vose)

    Marshal.load(Base64.decode64(@session.data))
    

    It is not encrypted at all.

    0 讨论(0)
  • 2020-12-24 03:15

    Rails uses HMAC-SHA1 for encrypting cookie data, which is different from a one-way SHA1 encryption, as you suspected (see the Wikipedia article on HMAC for an explanation). The encryption is done by the ActiveSupport::MessageVerifier class (source code is fairly readable). Here's an example based on a test Rails app:

    secret = 'b6ff5a9c3c97bf89afe9a72e6667bafe855390e8570d46e16e9760f6394' +
      '4ab05577b211ec2f43f6c970441518f0241775499bde055078f754c33b62f68ba27ca'
    
    cookie = "_test_session=BAh7CCIYdXNlcl9jcmVkZW50aWFsc19pZGkGIhV1c2VyX2NyZW" +
      "RlbnRpYWxzIgGAMzBlODkxZDQ2MWZhNjFkMDFmNzczMmJjNDdjMjIwZGFjMTY2NWEwNDMwZ" +
      "DVjMmUxOWY5MDFjMjQ5NWQ4OTM1OGZlMzE3NzRiZTFiZjM1ZTVlZDY2ZGUzYTkwOWZjZTgw" +
      "NTFlNGUxZWI0MTUzYTRjODZiMGZmMzM3NzliM2U3YzI6D3Nlc3Npb25faWQiJTgxNzk0Yjd" +
      "kN2IxYzRjMDE0M2QwOTk5NTVjZjUwZTVm--25c8f3222ab1be9f2394e2795a9f2557b06d0a92"
    
    session = cookie.split('=').last
    verifier = ActiveSupport::MessageVerifier.new(secret, 'SHA1')
    verifier.verify(session)
    

    This should return the session hash you expect. To implement this in Java your colleague is going to have to duplicate the ActiveSupport::MessageVerifier#verify method. Source code is in your gems directory (/usr/lib/ruby/gems/1.8/gems on my system) at activesupport-2.3.5/lib/active_support/message_verifier.rb.

    0 讨论(0)
  • 2020-12-24 03:21

    I've written a Ruby gem to handle cookies managed by Rails apps. Reading its source you can understand how it works and possibly port it to Java so that your JSP app could use that:

    https://github.com/rosenfeld/rails_compatible_cookies_utils

    It's a single file with ~ 150 lines of code which also handles signed only cookie values and takes care of both signing/encrypting and verifying/decrypting, while you seem to only be concerned about decrypting. This is the method for decrypting:

    https://github.com/rosenfeld/rails_compatible_cookies_utils/blob/master/lib/rails_compatible_cookies_utils.rb#L41-L52

    It worths mentioning that besides the key and the secret you'll also need to know which serializer is used. It used to be Marshal but it seems the default for newly generated apps is now JSON. If Marshal was used then it may be tricky to convert that code to Java as you'd have to find a library which implements Ruby's Marshal#load.

    0 讨论(0)
  • 2020-12-24 03:23

    By default, Rails (before version 4) does not encrypt session cookies, it only signs them. To encrypt them, you need to do something like this:

    ActionController::Base.session_store = EncryptedCookieStore
    

    There are multiple plugins that provide that kind of encryption functionality.

    So, if you're not specifically using an encrypted store, all the Java code needs to do is verify the cookie signature and decode the cookie. As Alex says in his answer, you would need to duplicate the functionality of ActiveSupport::MessageVerifier#verify, and share the key with the Java application. That both verifies and decodes the cookie.

    If you don't want to verify the signature (which I do NOT recommend), you can use Midwire's method of decoding from Base64 to view the session hash. In Ruby, this is:

    Marshal.load(ActiveSupport::Base64.decode64(the_cookie_value))
    

    I know this is old, but hope this helps somebody!

    (Update: The question relates to Rails 3. Starting with Rails 4, session cookies are encrypted by default.)

    0 讨论(0)
  • 2020-12-24 03:28

    Here's how to decrypt the session cookie in Rails 4

    def decrypt_session_cookie(cookie)
      cookie = CGI.unescape(cookie)
      config = Rails.application.config
    
      encrypted_cookie_salt = config.action_dispatch.encrypted_cookie_salt               # "encrypted cookie" by default
      encrypted_signed_cookie_salt = config.action_dispatch.encrypted_signed_cookie_salt # "signed encrypted cookie" by default
    
      key_generator = ActiveSupport::KeyGenerator.new(config.secret_key_base, iterations: 1000)
      secret = key_generator.generate_key(encrypted_cookie_salt)
      sign_secret = key_generator.generate_key(encrypted_signed_cookie_salt)
    
      encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)
      encryptor.decrypt_and_verify(cookie)
    end
    

    http://big-elephants.com/2014-01/handling-rails-4-sessions-with-go/

    0 讨论(0)
提交回复
热议问题