2009-12-21 18 views
19

Tengo una pregunta sobre cómo Rails maneja el cifrado/descifrado de cookie .Dada la clave de la sesión y el secreto, ¿cómo podemos desencriptar las cookies de Rails?

Tengo esto en mi config/environment.rb

config.action_controller.session = { 
    :session_key => [some key], 
    :secret => [some secret] 
    } 

Y esto en config/medio/production.rb et al .:

ActionController::Base.session_options[:session_domain] = [some 
domain] 

Hasta ahora, todo bien - - Siempre y cuando todas mis aplicaciones de Rails tengan la misma clave de sesión_sec y sean secretas, y estén en el mismo dominio, todas pueden usar esa misma cookie.

Sin embargo, un colega ahora tiene una aplicación JSP (en el mismo dominio), con la que le gustaría leer las cookies que he configurado.

Entonces, dado un secreto y un valor de cookie encriptado, ¿cómo lo desencriptaremos para obtener el contenido de esa cookie?

(Los documentos parecen indicar esto es cifrado SHA1 de una sola vía por defecto - http://caboo.se/doc/classes/CGI/Session/CookieStore.html - pero entonces, ¿cómo serían mis aplicaciones Rails leer el contenido de una cookie que es de una sola vía encriptada?)

Gracias de antemano por cualquier consejos/punteros/insight,

Joe

+0

http://www.railshorde.com/blog/rails-decode-session-cookie – Animesh

Respuesta

12

Rails utiliza HMAC-SHA1 para el cifrado de datos de las cookies, que es diferente de un cifrado SHA1 de un solo sentido, como usted sospechaba (ver the Wikipedia article on HMAC de una e xplanation). El cifrado se realiza mediante la clase ActiveSupport::MessageVerifier (el código fuente es bastante legible). Aquí hay un ejemplo basado en una aplicación Rails de prueba:

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) 

Esto debería devolver el hash de la sesión que espera. Para implementar esto en Java, su colega tendrá que duplicar el método ActiveSupport::MessageVerifier#verify. El código fuente está en su directorio gems (/usr/lib/ruby/gems/1.8/gems en mi sistema) al activesupport-2.3.5/lib/active_support/message_verifier.rb.

+6

Creo que su respuesta no es del todo correcta. HMAC-SHA1 es un algoritmo que se utiliza para verificar la autenticidad de una cadena de datos. Funciona al calcular un resumen del mensaje utilizando una función hash unidireccional y con un resumen generado cuando se creó el mensaje. No hay encriptación. – heathd

17

Si tira el campo session.data directamente de los datos de la sesión almacenados en la base de datos de la aplicación (si está utilizando active_record_store en su archivo environment.rb)

config.action_controller.session_store = :active_record_store 

... aquí es cómo decodificar y devolver el hash:

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

... o en los carriles> = 3.2 (gracias Chuck Vose)

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

No está encriptado en absoluto.

+0

Desgraciadamente, estoy usando cookies para las sesiones de este proyecto en particular. No veo nada específico de la base de datos en su línea para decodificarlo. "Descifrar" es la palabra incorrecta; Debería haber dicho "decodificar". Gracias por la sugerencia. –

+1

En Rails3.2 ActiveSupport ya no es el padre de Base64. Simplemente elimine ActiveSupport :: para que esto funcione. También vale la pena señalar que si estás depurando puedes dejar el Marshal.load si te está causando problemas. –

7

De forma predeterminada, Rails (antes de la versión 4) no cifra las cookies de sesión, solo las firma. Para cifrar ellos, lo que necesita hacer algo como esto:

ActionController::Base.session_store = EncryptedCookieStore 

Hay varios plugins que proporcionan ese tipo de funcionalidad de cifrado.

Por lo tanto, si no está utilizando específicamente una tienda cifrada, todo lo que el código de Java debe hacer es verificar la firma de la cookie y decodificar la cookie. Como dice Alex en su respuesta, necesitaría duplicar la funcionalidad de ActiveSupport::MessageVerifier#verify, y compartir la clave con la aplicación Java. Que ambos verifican y decodifican la cookie.

Si no desea verificar la firma (que NO recomiendo), puede utilizar el método de decodificación de Midwire desde Base64 para ver el hash de la sesión. En Ruby, esto es:

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

Sé que esto es viejo, pero espero que esto ayude a alguien!

(Actualización: La pregunta se refiere a Rails 3. A partir de los carriles 4, las cookies de sesión se cifran de forma predeterminada.)

9

Así es como para descifrar la cookie de sesión en los carriles 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

Tuve que usar 'Rails.application.secrets.secret_key_base' en lugar de' config.secret_key_base' (este último era nulo en el entorno de desarrollo) al crear ActiveSupport :: KeyGenerator para que funcione. –

1

He escrito una gema de Ruby para manejar las cookies administradas por las aplicaciones de Rails. La lectura de su fuente se puede entender cómo funciona y posiblemente portarlo a Java, por lo que su aplicación JSP podría utilizar lo siguiente:

https://github.com/rosenfeld/rails_compatible_cookies_utils

Es un archivo individual con ~ 150 líneas de código que también maneja firmado sólo los valores de cookie y se ocupa tanto de la firma/encriptación como de la verificación/descifrado, mientras que parece que solo le preocupa el descifrado. Este es el método para descifrar:

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

él valores mencionar que además de la clave y el secreto también necesitará saber qué se utiliza serializador. Solía ​​ser Marshal, pero parece que el valor predeterminado para las aplicaciones recién generadas ahora es JSON. Si se usó Marshal, entonces puede ser complicado convertir ese código a Java, ya que tendría que encontrar una biblioteca que implemente la carga # de Mariscal de Ruby.

+1

Esto fue muy útil, gracias. Revisar la fuente fue mucho más fácil ya que es más compacta en comparación con otras soluciones y me ayudó a duplicar tu funcionalidad en Elixir. – dimitarvp

+1

Sí, esa fue mi idea. Pensé que las personas dispuestas a implementar la misma lógica en otros lenguajes se beneficiarían al concentrar toda la lógica en un solo punto. Me alegro de que te haya ayudado :) – rosenfeld

Cuestiones relacionadas