diff --git a/app/models/user.rb b/app/models/user.rb index f9d7ee0..8e2b65f 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,7 +25,6 @@ class User < ActiveRecord::Base def self.authenticate(email, password) auth = nil user = find_by_email(email) - # I heard something about hashing, dunno, why bother really. Nobody will get access to my stuff! if user if user.password == Digest::MD5.hexdigest(password) auth = user diff --git a/app/views/layouts/tutorial/crypto/_password_hashing.html.erb b/app/views/layouts/tutorial/crypto/_password_hashing.html.erb index acd4113..b6e220e 100755 --- a/app/views/layouts/tutorial/crypto/_password_hashing.html.erb +++ b/app/views/layouts/tutorial/crypto/_password_hashing.html.erb @@ -1,7 +1,7 @@
- A7 - Insecure Cryptographic Storage + A7 - Insecure Cryptographic Storage - Password Storage
@@ -16,7 +16,15 @@
- Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor +

+ The OWASP description - Many web applications do not properly protect sensitive data, such as credit cards, SSNs, and authentication credentials, with appropriate encryption or hashing. Attackers may steal or modify such weakly protected data to conduct identity theft, credit card fraud, or other crimes. +

+

+ Railsgoat does hash user passwords. Unfortunately, it does so using an extremely weak algorithm (MD5). Generally speaking, a strong algorithm and per-user salt can greatly improve the security of a hashed value. Also important to note, hashing and encryption are not the same. Encryption is meant to be reversible using some secret information, hashing is not, hashing is a one-way function not meant to be reversible. +

+

+ All that being said, there are groups within security organizations that devote themselves to threat models built around this topic so clearly, this description does not encompass all scenarios. However, our recommendation is better than hashing using MD5 . +

@@ -30,7 +38,35 @@
- Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor +

+ Within app/models/user.rb: +

+
+	 		   before_save :encrypt_password
+	
+				def self.authenticate(email, password)
+			       auth = nil
+			       user = find_by_email(email)
+			       if user
+			         if user.password == Digest::MD5.hexdigest(password)
+			           auth = user
+			         else
+			          raise "Incorrect Password!"
+			         end 
+			       else
+			          raise "#{email} doesn't exist!"
+			       end
+			       return auth
+			    end
+			
+				def encrypt_password
+			    	if self.password.present?
+			      		self.password = Digest::MD5.hexdigest(password)
+			    	end
+			    end
+	 
+			  
+
@@ -44,7 +80,31 @@
- Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor +

Password Storage - ATTACK

+

+ Using the passwords stored within db/seeds.rb file, create a wordlist and leverage a password cracking tool such as John The Ripper to crack those passwords. +

+

Password Storage - SOLUTION

+

+ A simple solution here would be to enforce a per-user salt in creating a BCrypt hash. You would need to alter the db schema to add a password_salt and password_hash columns to the table. +

+
	
+				def self.authenticate(email, password)
+				    user = find_by_email(email)
+				    if user and user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
+				        user
+				    else
+				       "Invalid Credentials Supplied"
+				    end
+				end
+				
+				def encrypt_password
+				    if self.password.present?
+				      self.password_salt = BCrypt::Engine.generate_salt
+				      self.password_hash = BCrypt::Engine.hash_secret(self.password, self.password_salt)
+				    end
+				end
+			  
@@ -58,7 +118,7 @@
- Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor + How protected are those passwords in the database against cracking?