Blog | G5 Cyber Security

Slow Hash DDoS: Client-Side Hashing Solution

TL;DR

Client-side hashing can significantly reduce the impact of denial-of-service (DoS) attacks exploiting slow hash functions. By pre-hashing data in the browser, you offload the computationally expensive hashing process from your server to the client’s machine. This limits the server’s workload and makes it harder for attackers to overwhelm it with requests requiring lengthy hash calculations.

How Slow Hash DDoS Attacks Work

Slow hash attacks target applications that use cryptographic hash functions (like SHA-256 or bcrypt) on user-supplied data. Attackers send specially crafted input designed to take a very long time to hash, consuming server resources with each request. This can lead to service degradation or complete outage.

Client-Side Hashing: A Solution

The core idea is to move the hashing operation from your server to the user’s browser before sending the data. Here’s how:

  1. Choose a Suitable Hash Function: Select a hash function that is readily available in JavaScript (e.g., SHA-256). Avoid functions requiring native extensions if possible, to maximise compatibility.
  2. Implement Client-Side Hashing: Use JavaScript to hash the data before submitting it to your server. Libraries like jsSHA or built-in Web APIs can help.
    const encoder = new TextEncoder();
    const data = 'your input string';
    const encodedData = encoder.encode(data);
    const hashBuffer = await crypto.subtle.digest('SHA-256', encodedData);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join('');
    console.log(hashHex); // The hashed value
  3. Send the Hash to Your Server: Instead of sending the original data, send only the generated hash to your server.
  4. Server-Side Verification: On the server, store and verify hashes instead of raw data. When a user submits a hash, compare it against the stored hash.
    // Example in Python (Flask)
    from flask import Flask, request
    import hashlib
    
    app = Flask(__name__)
    
    @app.route('/verify', methods=['POST'])
    def verify():
      submitted_hash = request.form['hash']
      stored_hash = 'your stored hash'
      if submitted_hash == stored_hash:
        return 'Hash matches!'
      else:
        return 'Hash does not match.'
    
    if __name__ == '__main__':
      app.run(debug=True)
  5. Salt the Hash: Always use a unique, randomly generated salt for each user to prevent rainbow table attacks and improve security.
    // Example in JavaScript:
    const salt = 'your random salt';
    const saltedData = salt + data;
    hashValue = SHA256(saltedData);

Benefits

Considerations

Exit mobile version