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.
Detect This Automatically with StackShield
StackShield continuously monitors your Laravel application from the outside and alerts you when security issues are found. No installation required.
Start Free Trial