Laravel Insecure Random Numbers: How to Replace rand() and mt_rand() with Cryptographic Alternatives
Using rand() or mt_rand() for tokens, passwords, or security decisions creates predictable values that attackers can guess or reproduce.
The Problem
PHP's rand() and mt_rand() functions use predictable pseudo-random number generators (PRNGs). An attacker who observes a few outputs can predict future values — and in some cases, reconstruct past values. If you use these functions to generate password reset tokens, API keys, session identifiers, CSRF tokens, or any security-sensitive value, attackers can predict them and gain unauthorized access. PHP provides cryptographically secure alternatives that should always be used instead.
How to Fix
-
1
Find insecure random usage in your code
Search for rand() and mt_rand() in security-sensitive contexts:
grep -rn 'rand(\|mt_rand(\|array_rand(\|shuffle(' app/ --include='*.php'Look specifically for usage in: - Token generation - Password/PIN creation - OTP codes - Nonce or salt generation - Random filename generation for uploads - Lottery/selection logic with financial impact
-
2
Replace with cryptographically secure alternatives
Use these replacements:
// Random integers // BEFORE: rand(100000, 999999) // AFTER: random_int(100000, 999999);// Random strings/tokens // BEFORE: md5(mt_rand()) // AFTER: Str::random(40); // Laravel helper (uses random_bytes) bin2hex(random_bytes(20)); // Raw PHP// Random bytes // BEFORE: mt_rand() based // AFTER: random_bytes(32);// Shuffling arrays securely // BEFORE: shuffle($array) // AFTER: Use a Fisher-Yates shuffle with random_int() -
3
Use Laravel helpers for common patterns
Laravel provides secure random generation out of the box:
// Random string use Illuminate\Support\Str; Str::random(40); // 40-char random string Str::uuid(); // UUID v4 Str::orderedUuid(); // Time-ordered UUID// Token generation $token = hash('sha256', Str::random(60));// Unique filenames $filename = Str::uuid() . '.' . $file->extension();All of these use random_bytes() internally.
How to Verify
Search for remaining insecure usage:
grep -rn 'mt_rand(\|\brand(' app/ --include='*.php' | grep -v '// safe\|// non-security'
Run php artisan stackshield:scan --check=SS040 to verify.
Prevention
Use Str::random(), random_int(), or random_bytes() for all security-sensitive randomness. rand() and mt_rand() are acceptable only for non-security uses like UI element positioning or test data generation. Add a code review rule to flag rand()/mt_rand() usage.
Frequently Asked Questions
Is mt_rand() safe for non-security purposes?
Yes. For non-security uses like randomizing display order, generating test data, or adding visual variation, mt_rand() is fine. The key distinction is: will predictable values cause a security issue? If not, mt_rand() is acceptable and faster.
Is Str::random() cryptographically secure?
Yes. Laravel's Str::random() uses random_bytes() internally, which is cryptographically secure. It is safe for generating tokens, passwords, and other security-sensitive values.
Related Guides
Laravel Weak Password Hashing: How to Replace md5 and sha1 with bcrypt
Using md5() or sha1() for password hashing is trivially crackable. Laravel uses bcrypt by default — make sure your application does too.
Laravel APP_KEY Security: How to Generate, Rotate, and Protect Your Encryption Key
A missing, short, or committed APP_KEY compromises session encryption, signed URLs, and all data encrypted with Crypt. Generate a strong key and keep it out of Git.
Laravel Session Security: Fix Insecure Cookie Config (Secure, HttpOnly, SameSite)
Laravel session cookies missing Secure, HttpOnly, or SameSite flags? Fix your config/session.php to prevent session hijacking, cookie theft, and CSRF attacks.
Is your Laravel app exposed right now?
34% of Laravel apps we scan have at least one critical issue. Most teams don't find out until something breaks. Our free scan checks your live application in under 60 seconds.