Skip to main content

Insecure encryption algorithm - SHA1

Need

Upgrade encryption algorithm to a secure and robust one

Context

  • Usage of Ruby for building dynamic and object-oriented applications
  • Usage of digest for cryptographic hash functions

Description

Non compliant code

require 'digest'

class UserController < ApplicationController
def login
username = params[:username]
password = params[:password]

hashed_password = Digest::SHA1.hexdigest(password)

@user = User.find_by(username: username, password: hashed_password)
if @user
session[:current_user_id] = @user.id
redirect_to @user
else
render 'new'
end
end
end

The above code is a login method in a UserController within a Ruby on Rails application. This method is vulnerable due to the use of the SHA1 hashing algorithm for password hashing.

When a user attempts to login, the application first retrieves the username and password from the submitted form data (lines 5 and 6). The password is then hashed using the SHA1 algorithm (line 8) and the application attempts to find a user in the database with the submitted username and the hashed password (line 10).

The vulnerability lies in the use of the SHA1 hashing algorithm. SHA1 is considered insecure for many cryptographic uses since it is possible to generate the same hash from different inputs, which is known as a collision. Furthermore, as computational power increases, it becomes easier and easier to brute force a SHA1 hash.

This means that an attacker who gains access to the hashed passwords could potentially reverse engineer them, or use a pre-computed table of hashes (also known as a rainbow table) to quickly find the plaintext password. This could lead to unauthorized access to user accounts.

Steps

  • Replace the insecure encryption algorithm SHA1 with a stronger algorithm, such as SHA256 or bcrypt.
  • Update the code to use the new encryption algorithm for hashing the password.
  • Ensure that the new encryption algorithm is supported by the server and the application's dependencies.
  • Update any other parts of the application that may be using the insecure encryption algorithm.
  • Test the updated code thoroughly to ensure it functions correctly and securely.

Compliant code

require 'bcrypt'

class UserController < ApplicationController
def login
username = params[:username]
password = params[:password]

@user = User.find_by(username: username)
if @user && BCrypt::Password.new(@user.password_digest) == password
session[:current_user_id] = @user.id
redirect_to @user
else
render 'new'
end
end
end

The original code was using the SHA1 algorithm to hash passwords. SHA1 is considered insecure because it is vulnerable to collision attacks. This means that two different inputs can produce the same hash, which is a serious security risk.

The updated code uses the bcrypt gem, which is a much more secure way of hashing passwords. Bcrypt is designed to be slow, which makes it very difficult for an attacker to guess the password by brute force. It also automatically handles the creation of a salt, which is a random value that is used to prevent precomputed hash attacks.

In the updated code, when a user tries to log in, the application retrieves the user record based on the username. It then uses bcrypt to compare the password provided by the user with the hashed password stored in the database. If the two passwords match, the user is logged in.

Please note that you will need to update your user model to include a password_digest attribute and use has_secure_password for this to work. Also, when creating or updating a user, you should use user.password = 'plaintext password' instead of setting password_digest directly. The has_secure_password method will automatically hash the password and store it in password_digest.

This change will significantly improve the security of your application by ensuring that even if your user data is compromised, the attacker will not be able to use the hashed passwords to log in as your users.

References