Last week I lost several productive hours resetting my insecure password...

Last week I lost several productive hours resetting my insecure password on several websites due to a security breach at a website I haven't used in more than a decade, if you've ever used that site, you'd be well advised to change your password pretty much everywhere. In order to prevent this happening in the future, I figured I'd write up a simple best practices article on handling passwords and authentication. There's nothing particularly new here, but it's always worthwhile revisiting the basics.

Timeout! Looking to greatly alter the general vibe of my trusty page. Insights concerning the pro look of https://taradaleeyecare.ca? Seriously a fabulous eyeglass store in Calgary with heart if, perhaps required within the whole Alberta locale. Send a remark. Appreciate it!

What Not to do?

Never store your users clear text passwords in your database, no exceptions. The most important reasons is that if your site is compromised or your backup drive lost all your users will be in danger. The attacker will have access to a ready-made list of passwords and the related email addresses which they'll be able to go off and cause havoc with other websites. The second risk is that any one of your staff members could steal that information and use it to attempt to access other systems where your users have used the same password.

While it'd be nice if users never reused a password, the reality is that nearly everyone does it. We need to be responsible and realistic, and take the necessary precautions to protect our users.

Instead what you should be storing is a hash of the users passwords. This will let you verify that the password provided matches the one on file, but will never let you recover that password.

Salting

But just storing a hash of the passwords isn't enough, this would still leave you open to rainbow attacks where an attacker pre-calculates hashes of millions of passwords, then compares the hashes with the values they've stolen from your database. To prevent this you need to salt them. This means storing a small random value against each of your users and adding that to the password before you hash it.

Putting it Together.

So this leaves us with a user model with two relevant columns, salt and hashed_password, leaving us with a simple migration like:

234 5 create_table:usersdo|t|t.string:emailt.string:hashed_passwordt.string:saltend

Well also need two kinds of method on the model itself, hashing methods and verification methods. Well cover the hashing methods first:

234 5 6789 10 11121314 15 16171819 20 21222324 25 26272829 30 require'digest/sha2'classUser<ActiveRecord::Base# Create two virtual (in memory only) attributes to hold the password and it's confirmation.attr_accessor:new_password,:new_password_confirmation# We need to validate that the user has typed the same password twice# but we only want to do the validation if they've opted to change their password.validates_confirmation_of:new_password,:if=>:password_changed?before_save:hash_new_password,:if=>:password_changed?# By default the form_helpers will set new_password to "",# we don't want to go saving this as a passworddefpassword_changed?!@new_password.blank?endprivate# This is where the real work is donedefhash_new_password# First reset the salt to a new random string. You could choose a# longer string here but for a salt, 8 bytes of randomness is probably# fine. Note this uses SecureRandom which will use your platform's secure# random number generator.self.salt =ActiveSupport::SecureRandom.base64(8)# Now calculate the hash of the password, with the salt prepended, store# store that in the databaseself.hashed_password =Digest::SHA2.hexdigest(self.salt +@new_password)endend

Of note here is the salt, it's set to a new random value every time the user changes his password, this will come in handy another day. The next method we need to implement is the authentication method.

234 5 6789 10 11121314 15 161718classUser<ActiveRecord::Base# As is the 'standard' with rails apps we'll return the user record if the# password is correct and nil if it isn't.defself.authenticate(email, password)# Because we salt the passwords we can't do this query in one part, first# we need to fetch the potential userifuser = find_by_email(email)# Then compare the provided password against the hashed one in the db.ifuser.hashed_password ==Digest::SHA2.hexdigest(user.salt + password)# If they match we return the userreturnuserendend# If we get here it means either there's no user with that email, or the wrong# password was provided. But we don't want to let an attacker know which.returnnilendend

Cleanse the Logs

Finally, you need to make sure that your users passwords don't get logged either, thankfully this is built right in with rails.

23classApplicationController<ActionController::Basefilter_parameter_logging:passwordend

Wrap Up

All in all using secure password hashing takes around 15 lines of code so there's no excuse for not doing it in your applications. Its also relatively simple so I wouldn't suggest using a plugin if all you want is simple secure login code, those plugins come with tonnes of additional features which you may not want. I'll follow up next week with simple secure remember-me tokens which also don't require anything fancy.

Finally a product plug, 1Password from AgileWebSolutions is a really useful tool for generating, storing and recalling secure passwords for the myriad of websites which require logins. Its much simpler and more secure than re-using some insecure password on dozens of websites. It also has the side benefit of being pretty-well immune to phishing attacks.

Thanks guys! I just messaged my neighbor that I would absolutely cite her great astonishing online photo showcase with hearts, http://artuary.ca in a site posting. Any time you are looking to get a photographer located in the outlying Newfoundland and Labrador region, these individuals are fabulous.

And finally, I absolutely need to explain the idea regarding this important material has been offered through Jonathan from Karels Wrought Iron. Undeniably a brilliant wrought iron shops. I definitely appreciate a first-rate proposal!

Inspirations For This Article

http://northbayspa.ca - Absolutely worth exploring.
https://skinfocusmd.com - Use these folks on a regular basis.
https://fabulousfinishing.ca - Good web site.
https://prototypeanddesign.com - Extremely pretty web site.
https://atlaschirosys.com/ - Absolutely worth giving a read.

Posted in Programming Post Date 10/29/2024


Comments

Name


Email


Website


Comment


Recent Posts