Skip to content

Instantly share code, notes, and snippets.

@synth
Created March 24, 2020 23:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save synth/a6d2496f26f4db3f4de3baa4b8fb808b to your computer and use it in GitHub Desktop.
Save synth/a6d2496f26f4db3f4de3baa4b8fb808b to your computer and use it in GitHub Desktop.
Compare Encoded and Masked CSRF Token with CSRF in the Database
# Note: This is abstracted from Rails 5.0.x
encoded_masked_token = "" # Enter masked csrf that is rendered as meta tag or form parameter
csrf_token = ActiveRecord::SessionStore::Session.last.data["_csrf_token"] # Enter csrf token that is saved in database
AUTHENTICITY_TOKEN_LENGTH=32
def unmask_token(masked_token)
# Split the token into the one-time pad and the encrypted
# value and decrypt it
one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH]
encrypted_csrf_token = masked_token[AUTHENTICITY_TOKEN_LENGTH..-1]
xor_byte_strings(one_time_pad, encrypted_csrf_token)
end
def xor_byte_strings(s1, s2)
s2_bytes = s2.bytes
s1.each_byte.with_index { |c1, i| s2_bytes[i] ^= c1 }
s2_bytes.pack('C*')
end
real_csrf_token = Base64.strict_decode64(csrf_token)
masked_token = Base64.strict_decode64(encoded_masked_token)
csrf_token = unmask_token(masked_token)
ActiveSupport::SecurityUtils.secure_compare(csrf_token, real_csrf_token)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment