Skip to content

Instantly share code, notes, and snippets.

@mfakhrusy
Last active February 7, 2026 07:18
Show Gist options
  • Select an option

  • Save mfakhrusy/df202afe19f25efcaf3a2fb726b0ed99 to your computer and use it in GitHub Desktop.

Select an option

Save mfakhrusy/df202afe19f25efcaf3a2fb726b0ed99 to your computer and use it in GitHub Desktop.

I'll analyze this Flask authentication code for security vulnerabilities. This is a comprehensive review without needing external tools. Security Assessment: Moderate Risk ⚠️

This code has several good security practices but also contains critical vulnerabilities that would make it unsafe for production use.

πŸ”΄ Critical Vulnerabilities

  1. Weak Password Hashing (SHA-256)
password_hash = hashlib.sha256((password + salt).encode()).hexdigest()

Problem: SHA-256 is designed for speed, making it vulnerable to brute-force attacks with modern GPUs (billions of guesses/second).

Fix: Use bcrypt, Argon2, or PBKDF2:

from werkzeug.security import generate_password_hash, check_password_hash
# Store: generate_password_hash(password, method='pbkdf2:sha256:600000')
# Verify: check_password_hash(stored_hash, password)
  1. Timing Attack on Password Verification
return hash_obj.hexdigest() == stored_hash

Problem: Standard string comparison leaks timing information, allowing attackers to guess passwords byte-by-byte.

Fix: Use constant-time comparison:

import hmac
return hmac.compare_digest(hash_obj.hexdigest(), stored_hash)
  1. Hardcoded Demo Credentials
'admin': {'password_hash': hashlib.sha256('admin123'.encode()).hexdigest()}

Problem: Hardcoded weak passwords (admin123, user123) in source code will end up in git history.

Fix: Remove all default credentials; require setup wizard or environment-based initialization.

🟑 High Severity Issues

  1. In-Memory Rate Limiting Bypass
login_attempts = {}  # Global dictionary

Problem: Reset on every server restart/deploy Doesn't work across multiple server instances (load balancing) Memory exhaustion DoS possible (unbounded IP storage) Fix: Use Redis with expiration:

# Redis EXPIRE automatically cleans old entries
redis.setex(f"login:{ip}", 3600, attempt_count)
  1. X-Forwarded-For IP Spoofing
if request.headers.get('X-Forwarded-For'):
    return request.headers.get('X-Forwarded-For').split(',')[0].strip()

Problem: Client can spoof any IP by sending X-Forwarded-For: <fake_ip>, bypassing rate limits on others or causing self-blocks. Fix: Only trust specific proxy hops or use request.access_route with trusted proxy configuration.

  1. Missing Session Validation The code generates session tokens but never validates them on subsequent requests. There's no @require_auth decorator or session verification middleware. 🟠 Medium Severity Issues

  2. Debug Mode in Production Template

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

Problem: debug=True exposes stack traces and interactive debugger (PIN-based console) on errors.

  1. Weak Password Policy
elif len(password) < 6:
    errors.append('Password must be at least 6 characters')

Problem: 6 characters is insufficient (NIST recommends minimum 8, ideally 12+).

  1. No CORS Protection No CORS configuration allows malicious websites to make requests to this API (though SameSite=Lax mitigates cookie-based CSRF).

  2. Information Leakage in Registration

if username in USERS_DB:
    return jsonify({'error': 'username_exists'}), 409  # Confirms existence

Problem: Allows user enumeration attacks. Should return generic "registration failed" message.

Feature Implementation Status
Rate limiting Per-IP attempt tracking βœ… (but flawed)
Account lockout 5 min after 5 fails βœ…
Secure cookies HttpOnly, Secure, SameSite βœ…
Input sanitization Null byte/control char removal βœ…
Generic auth errors "Invalid username or password" βœ…
Security headers X-Frame-Options, nosniff βœ…
Token generation secrets.token_urlsafe βœ…

Recommended Fixes (Priority Order)

  1. Replace SHA-256 with bcrypt/Argon2 immediately
  2. Add constant-time comparison for password verification
  3. Implement proper session middleware to validate tokens on protected routes
  4. Move to Redis for rate limiting storage
  5. Fix IP extraction to prevent spoofing
  6. Remove hardcoded credentials and require secure initialization
  7. Increase minimum password length to 12 characters
  8. Add request signing or CSRF tokens for state-changing operations

Overall Verdict Not production-ready. The cryptographic weaknesses (SHA-256 + timing attacks) alone are deal-breakers. The code shows security awareness but needs hardening before handling real user data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment