# Insecure Randomness via random.randint for Password Reset Tokens

Language: Python
Severity: High
CWE: CWE-338

## Source
11

## Flow
11-12

## Sink
12

## Vulnerable Code
```python
import random
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/api/iot/device/reset-auth', methods=['POST'])
def reset_device_credentials():
    device_id = request.json.get('device_id')
    reset_code = random.randint(100000, 999999)
    auth_token = hashlib.sha256(f"{device_id}:{reset_code}".encode()).hexdigest()
    store_reset_token(device_id, auth_token, reset_code)
    send_sms_to_device_owner(device_id, reset_code)
    return jsonify({"status": "success", "message": "Reset code sent to registered mobile"})

def store_reset_token(dev_id, token, code):
    pass

def send_sms_to_device_owner(dev_id, code):
    pass
```

## Explanation

The code uses Python's random.randint() to generate a 6-digit password reset code, which relies on the Mersenne Twister PRNG that is cryptographically insecure and predictable. An attacker can predict future reset codes by observing previous codes, allowing unauthorized device credential resets and account takeover.

## Remediation

The fix replaces the insecure `random.randint()` with `secrets.randbelow()` from Python's `secrets` module, which uses a cryptographically secure random number generator (CSPRNG). The expression `secrets.randbelow(900000) + 100000` produces the same range of 6-digit codes (100000-999999) but with unpredictable randomness that cannot be reverse-engineered from observed outputs.

## Secure Code
```python
import secrets
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/api/iot/device/reset-auth', methods=['POST'])
def reset_device_credentials():
    device_id = request.json.get('device_id')
    reset_code = secrets.randbelow(900000) + 100000
    auth_token = hashlib.sha256(f"{device_id}:{reset_code}".encode()).hexdigest()
    store_reset_token(device_id, auth_token, reset_code)
    send_sms_to_device_owner(device_id, reset_code)
    return jsonify({"status": "success", "message": "Reset code sent to registered mobile"})

def store_reset_token(dev_id, token, code):
    pass

def send_sms_to_device_owner(dev_id, code):
    pass
```
