Get a Pentest and security assessment of your IT network.

Cyber Security

Password Leak Response: Client-Side Hashing

TL;DR

Client-side hashing can improve security after a password leak if implemented correctly, but it’s not a silver bullet. It adds complexity and relies on users re-hashing their passwords with new salts. It’s best used as part of a broader response plan including forced resets and monitoring.

1. Understanding the Problem

When a password database is leaked, attackers have access to hashed passwords. If the hashing algorithm is weak or uses common salts, these can be cracked relatively easily. Even strong hashes are vulnerable over time with increasing computing power. Client-side hashing aims to mitigate this by adding another layer of protection after the leak.

2. How Client-Side Hashing Works

Normally, passwords are hashed on the server before being stored. Client-side hashing involves hashing the password in the user’s browser *before* it’s sent to the server. This means even if the server is compromised, attackers only get hashes generated with a salt known by each individual user.

3. Steps for Implementing Client-Side Hashing After a Leak

  1. Generate New Salts: Each affected user needs a new, unique salt. This is the most critical step. Do not reuse old salts!
  2. Update Client-Side Code: Modify your website’s JavaScript to incorporate a hashing function (e.g., SHA256) and use the newly generated salt for each user. Libraries like bcrypt.js or scrypt.js can be used, but ensure they are properly vetted for security vulnerabilities.
  3. Prompt Users to Re-Hash: Users must re-submit their passwords (or a password confirmation). This is because the server only has the old hashes. The client-side code will hash the new input with the user’s unique salt before sending it to the server.
  4. Store New Hashes: Replace the compromised hashes on the server with the newly generated hashes from the client.
  5. Invalidate Old Hashes (Optional): If possible, mark the old hashes as invalid in your database. This prevents accidental use of the leaked data if it falls into the wrong hands again.

4. Example JavaScript Code Snippet

async function hashPassword(password, salt) {
  const encoder = new TextEncoder();
  const encodedPassword = encoder.encode(password);
  const hashed = await crypto.subtle.digest('SHA-256', encodedPassword);
  const hexArray = Array.from(new Uint8Array(hashed)).map(b => b.toString(16).padStart(2, '0')).join('');
  return salt + hexArray;
}

Important: This is a simplified example. Real-world implementations require careful handling of salts and secure key management.

5. Considerations & Limitations

  • User Adoption: Getting users to re-hash their passwords can be difficult. Forced resets are more reliable but less user-friendly.
  • Complexity: Client-side hashing adds significant complexity to your application.
  • Man-in-the-Middle Attacks: A malicious actor could intercept the JavaScript code and replace it with their own, potentially stealing passwords before they are hashed. Use HTTPS and Subresource Integrity (SRI) to mitigate this risk.
  • Browser Compatibility: Ensure your chosen hashing function is supported by all browsers used by your users.
  • Salt Storage: Securely store the salts associated with each user. If an attacker gains access to these, client-side hashing is defeated.

6. Best Practices

  • Combine with Other Measures: Client-side hashing should be part of a broader security response plan that includes forced password resets, multi-factor authentication (MFA), and monitoring for compromised credentials.
  • Regular Audits: Regularly audit your code and infrastructure for vulnerabilities.
  • Rate Limiting: Implement rate limiting to prevent brute-force attacks during the re-hashing process.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation