# Flask Session Forgery via Hardcoded SECRET_KEY

Language: Python
Severity: Critical
CWE: CWE-798

## Source
5

## Flow
5-8-9-24

## Sink
8-9, 24

## Vulnerable Code
```python
from flask import Flask, session, request, jsonify
from functools import wraps

iot_hub = Flask(__name__)
iot_hub.secret_key = 'iot-device-mgmt-2024'

def requires_device_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not session.get('device_id') or not session.get('is_provisioned'):
            return jsonify({'error': 'Device not authenticated'}), 401
        return f(*args, **kwargs)
    return decorated

@iot_hub.route('/provision', methods=['POST'])
def provision_device():
    device_mac = request.json.get('mac_address')
    device_type = request.json.get('type')
    session['device_id'] = device_mac
    session['is_provisioned'] = True
    session['device_role'] = 'standard'
    return jsonify({'status': 'provisioned', 'device': device_mac})

@iot_hub.route('/firmware/update', methods=['POST'])
@requires_device_auth
def push_firmware():
    if session.get('device_role') == 'admin':
        firmware_url = request.json.get('firmware_url')
        return jsonify({'status': 'updating', 'url': firmware_url})
    return jsonify({'error': 'Insufficient privileges'}), 403
```

## Explanation

The Flask application uses a hardcoded SECRET_KEY ('iot-device-mgmt-2024') which allows attackers to forge session cookies. Since authentication and authorization rely solely on session data (device_id, is_provisioned, device_role), an attacker can craft a malicious session cookie with device_role='admin' to bypass privilege checks and access administrative firmware update functions.

## Remediation

The fix replaces the hardcoded SECRET_KEY with a value sourced from an environment variable (FLASK_SECRET_KEY), falling back to a cryptographically secure random 32-byte key generated by os.urandom(). This prevents attackers from knowing the secret key and forging session cookies to escalate privileges from 'standard' to 'admin' device role.

## Secure Code
```python
import os
from flask import Flask, session, request, jsonify
from functools import wraps

iot_hub = Flask(__name__)
iot_hub.secret_key = os.environ.get('FLASK_SECRET_KEY') or os.urandom(32)

def requires_device_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not session.get('device_id') or not session.get('is_provisioned'):
            return jsonify({'error': 'Device not authenticated'}), 401
        return f(*args, **kwargs)
    return decorated

@iot_hub.route('/provision', methods=['POST'])
def provision_device():
    device_mac = request.json.get('mac_address')
    device_type = request.json.get('type')
    session['device_id'] = device_mac
    session['is_provisioned'] = True
    session['device_role'] = 'standard'
    return jsonify({'status': 'provisioned', 'device': device_mac})

@iot_hub.route('/firmware/update', methods=['POST'])
@requires_device_auth
def push_firmware():
    if session.get('device_role') == 'admin':
        firmware_url = request.json.get('firmware_url')
        return jsonify({'status': 'updating', 'url': firmware_url})
    return jsonify({'error': 'Insufficient privileges'}), 403
```
