Blog | G5 Cyber Security

Weak Password Check: Fix Subset Attack

TL;DR

Your banking platform is letting users create passwords that are only part of their real password, making accounts vulnerable. This guide shows you how to fix this with stronger checks during registration and password changes.

Solution Guide

  1. Understand the Problem: Subset Attacks
    • A subset attack happens when a system accepts passwords that are just parts of a user’s actual password. For example, if someone’s real password is ‘P@$$wOrd123’, allowing ‘P@$$wOrd’ or ‘wOrd123’ as valid passwords creates a huge security risk.
    • Attackers can use this to guess the full password more easily, especially with common password patterns.
  2. Review Existing Password Validation
    • Check your current code for how it validates passwords during account creation and when users change their passwords. Look for any checks that might be too lenient.
    • Common mistakes include only checking length, character types (uppercase, lowercase, numbers), or using simple regular expressions that don’t prevent subsets.
  3. Implement Stronger Password Checks
    1. Minimum Length: Enforce a strong minimum password length (at least 12 characters is recommended).
    2. No Substrings Allowed: This is the core fix. You need to prevent passwords that are substrings of known data associated with the user.
      • User Data Check: Compare the new password against the user’s username, email address, full name, and any other personally identifiable information (PII) they’ve provided.
      • Previous Passwords: Prevent reuse of previous passwords. Store a hash of recent passwords (e.g., last 5-10) and compare against those.
        # Example Python code snippet (using hashing - replace with your framework's equivalent)
        import hashlib
        
        def check_password_history(new_password, password_hashes):
          hashed_new_password = hashlib.sha256(new_password.encode()).hexdigest()
          if hashed_new_password in password_hashes:
            return False # Password already used
          return True
        
    3. Regular Expression (Regex) Enhancement: Use a more robust regex to enforce complexity and prevent common patterns. However, don’t rely solely on regex; it’s easy to bypass.
      # Example Regex (adjust as needed)
      regex = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[@$!%*?&])[A-Za-zd@$!%*?&]{12,}$")
      
  4. Password Strength Meter:
    • Implement a password strength meter to give users feedback as they type. This encourages them to create stronger passwords.
    • Libraries are available for most frameworks (e.g., zxcvbn in JavaScript).
  5. Testing is Crucial
    • Positive Tests: Verify that strong, complex passwords are accepted.
    • Negative Tests: Thoroughly test with various weak passwords, including:
      • Substrings of usernames and email addresses
      • Previous passwords
      • Common dictionary words
      • Simple patterns (e.g., ‘password123’, ‘qwerty’)
  6. Rate Limiting: Implement rate limiting on password reset and login attempts to prevent brute-force attacks.
Exit mobile version