ruby on rails - example - Dada la clave de sesión y el secreto, ¿cómo podemos descifrar las cookies de Rails?
rails session id (5)
Tengo una pregunta sobre cómo Rails maneja el cifrado / descifrado de cookies.
Tengo esto en mi config / environment.rb
config.action_controller.session = {
:session_key => [some key],
:secret => [some secret]
}
Y esto en config / environment / production.rb et al .:
ActionController::Base.session_options[:session_domain] = [some
domain]
Hasta ahora, todo bien: mientras todas mis aplicaciones Rails tengan la misma clave de sesión y secreta, y estén en el mismo dominio, todas pueden usar la 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 establecido.
Entonces, dado un secreto y un valor de cookie encriptado, ¿cómo lo descifraríamos para obtener el contenido de esa cookie?
(Los documentos parecen indicar que esto es un cifrado SHA1 unidireccional de forma predeterminada, http://caboo.se/doc/classes/CGI/Session/CookieStore.html , pero entonces, ¿cómo leerían las aplicaciones Rails el contenido de un cookie que es unidireccional cifrada?)
Gracias de antemano por cualquier consejo / puntero / conocimiento,
Joe
Aquí es cómo descifrar la cookie de sesión en 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/
He escrito una gema de Ruby para manejar las cookies administradas por las aplicaciones Rails. Al leer su fuente, puede comprender cómo funciona y posiblemente transferirla a Java para que su aplicación JSP pueda usar eso:
https://github.com/rosenfeld/rails_compatible_cookies_utils
Es un archivo único con ~ 150 líneas de código que también maneja valores de cookies firmados y se encarga de firmar / cifrar y verificar / descifrar, mientras que parece que solo le preocupa descifrar. Este es el método para descifrar:
Vale la pena mencionar que, además de la clave y el secreto, también deberá saber qué serializador se utiliza. Solía ser Marshal, pero parece que el valor predeterminado para las aplicaciones recién generadas es ahora JSON. Si se usó Marshal, puede ser difícil convertir ese código a Java, ya que tendría que encontrar una biblioteca que implemente la carga # de Marshal de Ruby.
Por defecto, Rails (antes de la versión 4) no encripta las cookies de sesión, solo las firma. Para encriptarlos, necesitas hacer algo como esto:
ActionController::Base.session_store = EncryptedCookieStore
Hay varios complementos que proporcionan ese tipo de funcionalidad de cifrado.
Por lo tanto, si no está utilizando específicamente un almacén cifrado, todo lo que debe hacer el código Java es verificar la firma de la cookie y descodificarla. 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 tanto verifica como decodifica la cookie.
Si no desea verificar la firma (que NO recomiendo), puede usar 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 relaciona con Rails 3. A partir de Rails 4, las cookies de sesión están cifradas de manera predeterminada).
Rails usa HMAC-SHA1 para cifrar datos de cookies, que es diferente de un cifrado SHA1 de una vía, como sospechaba (consulte el artículo de Wikipedia en HMAC para obtener una explicación). 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 de prueba de Rails:
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 sesión que esperas. Para implementar esto en Java, su colega tendrá que duplicar el método de ActiveSupport::MessageVerifier#verify
. El código fuente está en su directorio de gemas ( /usr/lib/ruby/gems/1.8/gems
en mi sistema) en activesupport-2.3.5/lib/active_support/message_verifier.rb
.
Si extrae el campo session.data directamente de los datos de la sesión almacenados en la base de datos de su aplicación (si está usando active_record_store en su archivo environment.rb)
config.action_controller.session_store = :active_record_store
... aquí es cómo lo descifras y devuelves el hash:
Marshal.load(ActiveSupport::Base64.decode64(@session.data))
... o en Rails> = 3.2 (gracias Chuck Vose)
Marshal.load(Base64.decode64(@session.data))
No está encriptado en absoluto.