# Insecure Randomness via random.random() for Session Token Generation

Language: Python
Severity: High
CWE: CWE-338

## Source
12

## Flow
12-14

## Sink
14

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

app = Flask(__name__)
iot_device_sessions = {}

@app.route('/api/iot/provision', methods=['POST'])
def provision_device():
    device_id = request.json.get('device_id')
    device_type = request.json.get('type')
    rand_seed = int(random.random() * 1000000000)
    nonce = random.randint(100000, 999999)
    auth_token = hashlib.sha256(f"{device_id}:{rand_seed}:{nonce}".encode()).hexdigest()
    iot_device_sessions[device_id] = {
        'token': auth_token,
        'type': device_type,
        'provisioned_at': str(random.random())
    }
    return jsonify({
        'status': 'provisioned',
        'auth_token': auth_token,
        'device_id': device_id
    })
```

## Explanation

The code uses Python's random.random() and random.randint() for generating cryptographic tokens, which are not cryptographically secure PRNGs. These functions use the Mersenne Twister algorithm that is predictable and can be cracked, allowing attackers to predict authentication tokens for IoT devices.

## Remediation

The fix replaces all uses of the insecure `random` module with Python's `secrets` module, which provides cryptographically secure random number generation suitable for authentication tokens. The `secrets.token_hex()` function generates unpredictable random bytes, making it infeasible for attackers to predict or reproduce generated tokens. Additionally, the `provisioned_at` field now uses `time.time()` instead of `random.random()` for a meaningful timestamp.

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

app = Flask(__name__)
iot_device_sessions = {}

@app.route('/api/iot/provision', methods=['POST'])
def provision_device():
    device_id = request.json.get('device_id')
    device_type = request.json.get('type')
    rand_seed = secrets.token_hex(32)
    nonce = secrets.token_hex(16)
    auth_token = hashlib.sha256(f"{device_id}:{rand_seed}:{nonce}".encode()).hexdigest()
    iot_device_sessions[device_id] = {
        'token': auth_token,
        'type': device_type,
        'provisioned_at': str(time.time())
    }
    return jsonify({
        'status': 'provisioned',
        'auth_token': auth_token,
        'device_id': device_id
    })
```
