Email uniqueness not properly verified - Ruby

Email uniqueness not properly verified - Ruby

Need

Enforce strict email uniqueness verification during the registration process

Context

  • Usage of Ruby 2.0+ for developing Ruby applications
  • Usage of Rails framework for building web applications
  • Usage of ActiveRecord for Object-Relational Mapping (ORM) in database operations

Description

Non compliant code

        class User < ApplicationRecord
  validates :email, presence: true
end
        
        

In this Ruby on Rails application, the User model is being validated for the presence of an email. However, there is no validation to ensure that the email is unique. This means that the system will allow multiple users to register with the same email, as long as they append a '+' character followed by any string before the '@' symbol.

For example, an attacker could register multiple accounts with emails like attacker+1@gmail.com, attacker+2@gmail.com, attacker+3@gmail.com, etc. All these emails will be treated as unique by the system but in reality, all emails will be delivered to attacker@gmail.com.

This vulnerability could be exploited by an attacker to create multiple accounts and conduct fraudulent activities, while all the accounts point to the same email. It could also potentially bypass any rate limits or restrictions that are placed on a per-account basis.

Steps

  • Update the validation for email uniqueness in the User model.
  • Use a regular expression to validate the email format and disallow the plus character.
  • Add a database constraint to enforce email uniqueness at the database level.
  • Test the changes thoroughly to ensure the vulnerability is fixed.

Compliant code

        class User < ApplicationRecord
  validates :email, presence: true, uniqueness: { case_sensitive: false }, format: { without: /\\+/ }
end
        
        

The updated code includes a few changes to the User model to fix the vulnerability.

1. uniqueness: { case_sensitive: false }
- This validation ensures that the email is unique across all users. The case_sensitive: false option ensures that the uniqueness validation is not case sensitive. This means that "example@example.com" and "EXAMPLE@EXAMPLE.COM" are considered the same, preventing an attacker from creating multiple accounts with the same email using different cases.

2. format: { without: /\\+/ }
- This validation ensures that the email does not contain the plus character. The regular expression /\\+/ matches any string that contains the plus character. The without option ensures that the validation fails if the regular expression matches the email. This prevents an attacker from creating multiple accounts with the same email using the plus character.

3. It's also recommended to add a database constraint to enforce email uniqueness at the database level. This provides an extra layer of security in case the application-level validations fail or are bypassed. However, this change is not shown in the code snippet because it involves a database migration, which is outside the scope of the User model.

4. After making these changes, it's important to test them thoroughly to ensure the vulnerability is fixed. This includes testing the registration process with different email formats and cases, and checking that the database constraint works as expected.

References