Read more

Rails: Verify the CSRF token

Emanuel
October 28, 2019Software engineer at makandra GmbH

Rails uses a CSRF token Show archive.org snapshot in forms and AJAX requests to verify a user request. Internally it compares the injected CSRF token of the form data with the CSRF token in the encrypted user session. To prevent SSL BREACH attacks, the CSRF token from the form data is masked Show archive.org snapshot .

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

To better debug issues, when these tokens do not match, it is useful to unmask the CSRF token from the form data. Here is a method that works for Rails 5.2.

def decode_csrf_token(csrf_token)
  decoded_masked_token = Base64.strict_decode64(csrf_token)
  one_time_pad = decoded_masked_token[0...32]
  encrypted_csrf_token = decoded_masked_token[32..-1]

  encrypted_csrf_token_bytes = encrypted_csrf_token.bytes
  one_time_pad.each_byte.with_index { |c1, i| encrypted_csrf_token_bytes[i] ^= c1 }
  csrf_token = encrypted_csrf_token_bytes.pack("C*")
  Base64.strict_encode64(csrf_token)
end

Example form:

<input type="hidden" name="authenticity_token" value="af3uqNHd1MDskKeJH7+AiV7o8gozjqCsu78rbndSG/TlE+KPrKe2l3pltzi4O0xtFnUX3cRfsB+MxfP4BXvT6Q==">

Example usage:

decode_csrf_token("af3uqNHd1MDskKeJH7+AiV7o8gozjqCsu78rbndSG/TlE+KPrKe2l3pltzi4O0xtFnUX3cRfsB+MxfP4BXvT6Q==")
=> jO4MJ316YleW9RCxp4TM5Eid5df30RCzN3rYlnIpyB0=

Rails will only accept this request if jO4MJ316YleW9RCxp4TM5Eid5df30RCzN3rYlnIpyB0= is the same as the value in your cookie:

{
  "session_id"=>"8ef662867ab2457717ba74c143c08733",
  "timestamp"=>1572261371,
  "_csrf_token"=>"jO4MJ316YleW9RCxp4TM5Eid5df30RCzN3rYlnIpyB0="
}

Note: The session cookie is encrypted by default. You can decrypt it with Rails: Decrypt a session cookie.

Posted by Emanuel to makandra dev (2019-10-28 13:35)