# 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.

**Severity:** medium | **Category:** Application Security

---

## The Issue

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.

## Steps 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.

## Verification

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.

