Password Hashing Strength Analyzer
| Analyzer ID | Category | Severity | Time To Fix |
|---|---|---|---|
hashing-strength | 🛡️ Security | Critical | 15 minutes |
What This Checks
Validates that your Laravel application uses secure password hashing algorithms with appropriate security parameters. Checks for weak hashing drivers (MD5, SHA1, SHA256), insufficient bcrypt rounds, weak Argon2 parameters, and code-level vulnerabilities like md5() or sha1() usage for passwords.
Why It Matters
- Critical Security Risk: Weak password hashing allows attackers to crack passwords in seconds instead of years
- Real-World Breaches: LinkedIn (2012) - 90% of 6.5M passwords cracked in hours using weak SHA1
- Data Exposure: When databases are breached, weak hashing provides no protection against password cracking
- Compliance Violations: OWASP, PCI DSS, and NIST standards require strong password hashing
Weak password hashing is one of the most critical security vulnerabilities. Modern GPUs can crack billions of MD5/SHA1 hashes per second, making weak algorithms essentially equivalent to storing passwords in plain text. Strong algorithms like bcrypt (12+ rounds) or Argon2id make password cracking computationally infeasible, protecting users even after database breaches.
How to Fix
Quick Fix (5 minutes)
Scenario 1: Weak Bcrypt Rounds
// config/hashing.php - Update rounds
'bcrypt' => [
'rounds' => 12, // Increase from default 10 to minimum 12
]Scenario 2: Using MD5/SHA1 in Code
// BEFORE - Insecure
$user->password = md5($request->password);
// AFTER - Secure
use Illuminate\Support\Facades\Hash;
$user->password = Hash::make($request->password);Scenario 3: Weak Argon2 Parameters
// config/hashing.php - Strengthen parameters
'argon' => [
'memory' => 65536, // Increase from 1024 to 64 MB
'time' => 2, // Increase from 1
'threads' => 2, // Increase from 1
]Proper Fix (15 minutes)
Implement comprehensive password hashing security across your application:
1. Configure Strong Hashing
// config/hashing.php
return [
// Argon2id is recommended for new projects
'driver' => 'argon2id', // Or 'bcrypt' for compatibility
'bcrypt' => [
'rounds' => env('BCRYPT_ROUNDS', 12), // 2024 minimum
],
'argon' => [
'memory' => 65536, // 64 MB - resists GPU attacks
'time' => 2, // Iterations
'threads' => 2, // Parallel processing
],
];
// .env
BCRYPT_ROUNDS=12 # Production2. Replace All Weak Hashing Functions
// Find all instances of weak hashing
// grep -r "md5(" app/
// grep -r "sha1(" app/
// Replace with Hash facade
use Illuminate\Support\Facades\Hash;
// Registration/Password Updates
public function register(Request $request)
{
User::create([
'email' => $request->email,
'password' => Hash::make($request->password), // ✅ Secure
]);
}
// Password verification
if (Hash::check($request->password, $user->password)) {
// Authenticated
}3. Migrate Existing Users Gradually
// Migration strategy - rehash passwords on login
public function login(Request $request)
{
$user = User::where('email', $request->email)->first();
// Check if using old md5 format
if (md5($request->password) === $user->password) {
// Rehash with bcrypt and save
$user->password = Hash::make($request->password);
$user->save();
}
// Normal authentication
if (Hash::check($request->password, $user->password)) {
// Rehash if rounds increased
if (Hash::needsRehash($user->password)) {
$user->password = Hash::make($request->password);
$user->save();
}
Auth::login($user);
}
}4. Use Environment-Specific Settings
// .env - Fast hashing for tests
BCRYPT_ROUNDS=4
// .env - Production/Staging Secure settings
BCRYPT_ROUNDS=125. Verify Configuration
# Test hashing works correctly
php artisan tinker
>>> Hash::make('test-password')
>>> Hash::check('test-password', Hash::make('test-password'))
# Should return true
# Measure hashing time (target: 200-500ms)
>>> $start = microtime(true);
>>> Hash::make('test');
>>> echo (microtime(true) - $start) * 1000 . ' ms';6. Configure Legitimate MD5 Usage (Optional)
If you use MD5/SHA1 for non-password purposes (cache keys, checksums, ETags), publish the config:
php artisan vendor:publish --tag=shieldci-configThen in config/shieldci.php:
'hashing_strength' => [
// Minimum security parameters
'bcrypt_min_rounds' => 12,
'argon2_min_memory' => 65536,
'argon2_min_time' => 2,
'argon2_min_threads' => 2,
// Allow weak hashing for non-password use cases
'allowed_weak_hash_patterns' => [
'cache', // md5($data . '_cache')
'fingerprint', // md5($file . '_fingerprint')
'checksum', // md5($data . '_checksum')
'etag', // md5($content . '_etag')
],
// Ignore specific files
'ignored_paths' => [
'app/Utilities/CacheKeyGenerator.php',
],
],TIP
MD5 and SHA1 are acceptable for non-cryptographic purposes like cache keys and checksums. The analyzer only flags them when used for password hashing.
ShieldCI Configuration
This analyzer is automatically skipped in CI environments.
Why skip in CI?
- CI environments may use faster hashing settings for test performance
- Prevents false failures in CI pipelines
References
- Laravel Hashing Documentation
- OWASP Password Storage Cheat Sheet
- PHP password_hash() Manual
- NIST Digital Identity Guidelines
- Argon2 Specification
- Password Hashing Competition
Related Analyzers
- Authentication & Authorization Analyzer - Validates authentication implementation
- Debug Mode Analyzer - Ensures debug mode disabled in production
- Environment File Analyzer - Protects sensitive configuration
- Cookie Analyzer - Validates session cookie security configuration