Try Now
Get hands on with Cobalt's PtaaS Platform

Rails — Decrypting Devise’s Warden Session Cookie

Do you have users who have logged into your rails app that also need to be authenticated on your other platforms without providing their credentials again? Here we will look into leveraging cookies to do just that!

If you’ve used Rails chances are you’ve used Devise. Devise is commonly the Rails one-stop-shop for all things authentication. This article will detail how to decode and decrypt a session cookie from Devise (4.2.0) which is using Warden (1.2.6) in both Ruby and Python.

First in Ruby, start by locating your app’s token, sometimes called secret_key_base, config_secret_token, or just secret_token. Generally this will be located in your application.yml file or set in your environment variables. For this example I will use this one:

Secret Token (view Raw)

Second step is to log into your app and pull your authentication cookie value. An easy way to do this is open the chrome inspector and look at the requests to your app. There should be a set-cookie header that specifies the cookie like so:

Full Cookie (view Raw)

This value needs to be stripped and should only contain what is after the first ‘=’ all the way to the first occurrence of ‘ — ‘. Everything after ‘ — ‘ is the signature which we don’t need for this example. My stripped value is:

Stripped Cookie Value (view Raw)

Now that we have the raw cookie value let’s work on getting what we need to decode and decrypt it. First we need to hash our secret_token. Warden uses the OpenSSL PKCS5 module and runs the pbkdf2 method with a generic ‘encrypted cookie’ as the salt, 1000 as the iter value and 32 as the key length. This will run the key derivation function 1000 times and spit out a key with 32 bytes.

Hashing the Secret Token (View Raw)

Once we have the hashed token we are ready to process our cookie. We will first decode the cookie using Base64.decode64 here we will also take only the part before the ‘ — ‘. Next we will use Base.64.strict_decode64 to further decode the encrypted message into byte format. And finally we can create an AES 256 cipher using OpenSSL::Cipher. Inserting our token_hashed into the cipher.key and then updating the cipher with our decoded_cookie is all it takes! You should then see the decrypted message.

Decrypting the cipher (View Raw)

As you can see the cookie has been decrypted into human readable text. Here we have access to the user ID, an encrypted password fragment, and a sign_in_token. Depending on your exact devise settings this decrypted message may contain more or less data.

One Step Further — Decrypt Devise’s Warden Session Cookie in Python

Have two different web stacks hosting parts of the same application? Use one cookie to authenticate! Here is how to decrypt the Devise / Warden session cookie in python. The steps are very similar to those found above.

All togetha now (view Raw)

Main thing to note in the Python version is the byte strings. Most of these hashing and cipher methods require the input to be of type bytes. Also you may ask: “When creating the cipher on line 29 why are we passing blank bytes in for the Initialization Vector?” Because the IV is not needed for Cipher Block Chaining (CBC) decryption which is what we are doing up there with the AES module.

Back to Blog
About Cameron Clifford
Cameron Clifford works as a senior engineering manager for Cresta where he helps the team deploy secure code. With over a decade's experience in the cybersecurity sector, Cameron offers a plethora of expertise for cybersecurity best practices. More By Cameron Clifford