LOGIN
Fullstack Ruby Developer
 · HanoiVietnam
Share
Report
Get Link
TUTORIAL

Preventing brute force attack & securely encrypt your back-end API's Authorization header

1. What is a brute force attack:
A brute-force attack is an attempt to discover a password/token by systematically trying every possible combination of letters, numbers, and symbols until you discover the one correct combination that works.
Nowaday, there’re a lot of APIs that requires only weak token for Authorization header and can easily a target.

2. My task’s case:
We’ve a system for controling your smart home. You can add your family’s member and send them a generated link that allow members quickly access to unlocking the door. Each door must have an activated and plugged device (we call it controller).
Firstly, let’s make a simple test:

require 'securerandom'

system "printf 'with invalid door_id\n'"
system "curl -i -X POST -H 'Authorization: testing' -H 'Accept: application/json' https://api.website.com/doors/invalid_door_id/access"
system "printf '\n\n\n'"

50.times do
  token = SecureRandom.hex(16)
  system "printf 'with: #{token}\n'"
  system "curl -i -X POST -H 'Authorization: #{token}' -H 'Accept: application/json' https://api.website.com/doors/door_id/access"
  system "printf '\n\n\n'"
end

token = 'this_is_a_valid_token' # my correct token
system "printf 'with: #{token}\n'"
system "curl -i -X POST -H 'Authorization: #{token}' -H 'Accept: application/json' https://api.website.com/doors/door_id/access"
system "printf '\n\n\n'"

First request returns 404 - Not Found. Next 50 requests return 401 - Unauthorized response. And the last one returns successful response. So you can see, after you got a valid door_id, you can brute force the token to unlock that door. Dangerous, right?

3. Solution:
My idea is:
making the token is so complicated that stop the thought of brute forcing it.
encrypting token with other information, so just by checking it’s structure, we can stop a lot of attempts without accessing database.
Let’s first make an encryption library:

class Encryption
  CIPHER_IV  = Base64.decode64(Rails.application.secrets.cipher_iv)
  CIPHER_KEY = Base64.decode64(Rails.application.secrets.cipher_key)

  class << self
    def encrypt_attr(attribute_value)
      cipher = OpenSSL::Cipher.new('AES256')
      cipher.encrypt
      cipher.iv = CIPHER_IV
      cipher.key = CIPHER_KEY

      Base64.encode64(cipher.update(attribute_value) + cipher.final).delete("\n")
    rescue RuntimeError => e
      raise e.message
    end

    def decrypt_attr(encrypted_attribute_value)
      encrypted_attribute_value = Base64.decode64(URI.decode(encrypted_attribute_value))

      cipher = OpenSSL::Cipher.new('AES256')
      cipher.decrypt
      cipher.iv = CIPHER_IV
      cipher.key = CIPHER_KEY

      cipher.update(encrypted_attribute_value) + cipher.final
    rescue RuntimeError => e
      raise e.message
    end
  end
end

Now, our token is not a simple random hex string, it is: Encryption.encrypt_attr("#{door_id}-#{member_email}-#{door_token}")
So after decrypting with Encryption.decrypt_attr(authorization_header), we can easily check the structure if it’s a valid combination of an integer, a valid email and a token string. Without accessing database, you can fastly deny a lot of requests.

4. Extra information:
Of course, we also use an amazing gem https://github.com/kickstarter/rack-attack. Check it out, it’s simple to setup and config.

2 likes 
Like
Award Contribution
Areous Ahmadtj
43
Community Expert
student
 · JosNigeria
Share
Report
Get Link

cool

Like
0 like 
Award Contribution
Leave a reply...
DISCOVER
CHAT
HIRE
ACTIVITY
FEED
Chat with us!
Help
Write something before you submit it!
Photo updated
Request Sent!
Updated
Copied to Clipboard