# Insecure Session Token Generation via random.choice()

Language: Python
Severity: High
CWE: CWE-338

## Source
10

## Flow
10

## Sink
10

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

app = Flask(__name__)
app.secret_key = 'iot_device_mgmt_key'

@app.route('/api/device/provision', methods=['POST'])
def provision_iot_device():
    device_id = request.json.get('device_id')
    device_token = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(24))
    session['device_auth_token'] = device_token
    session['device_id'] = device_id
    return jsonify({'status': 'provisioned', 'auth_token': device_token, 'device': device_id})
```

## Explanation

The code uses Python's random.choice() which relies on the Mersenne Twister algorithm, a cryptographically insecure pseudo-random number generator. This makes the generated device authentication tokens predictable if an attacker can observe a sequence of tokens or knows the initial seed state, allowing them to forge valid tokens for unauthorized device access.

## Remediation

The fix replaces the insecure random.choice() with Python's secrets module, which uses a cryptographically secure random number generator (CSPRNG). Additionally, secrets.token_urlsafe(32) generates a 32-byte (256-bit) URL-safe token that is unpredictable and resistant to brute-force attacks. The hardcoded Flask secret_key was also replaced with a securely generated random key.

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

app = Flask(__name__)
app.secret_key = secrets.token_hex(32)

@app.route('/api/device/provision', methods=['POST'])
def provision_iot_device():
    device_id = request.json.get('device_id')
    device_token = secrets.token_urlsafe(32)
    session['device_auth_token'] = device_token
    session['device_id'] = device_id
    return jsonify({'status': 'provisioned', 'auth_token': device_token, 'device': device_id})
```
