# IDOR via Predictable Device Identifier Enumeration

Language: Python
Severity: Critical
CWE: CWE-89

## Source
2

## Flow
2-4-5

## Sink
5

## Vulnerable Code
```python
@app.route('/iot/thermostat/<int:device_num>/settings', methods=['GET'])
def fetch_thermostat_config(device_num):
    db_conn = get_database_connection()
    cursor = db_conn.cursor()
    query = f"SELECT device_id, owner_email, temp_schedule, api_key FROM smart_thermostats WHERE device_id = {device_num}"
    cursor.execute(query)
    thermostat_data = cursor.fetchone()
    if thermostat_data:
        return jsonify({
            'device_id': thermostat_data[0],
            'owner': thermostat_data[1],
            'schedule': thermostat_data[2],
            'api_key': thermostat_data[3]
        }), 200
    return jsonify({'error': 'Device not found'}), 404
```

## Explanation

The code suffers from SQL injection where user-controlled input 'device_num' from the URL parameter is directly concatenated into the SQL query without sanitization or parameterization. Additionally, there's an IDOR vulnerability as the endpoint lacks authorization checks to verify if the authenticated user owns the requested device, allowing attackers to enumerate and access other users' thermostat data including sensitive API keys.

## Remediation

The fix addresses both vulnerabilities: SQL injection is resolved by using parameterized queries with placeholder (%s) instead of string interpolation, preventing malicious SQL from being executed. The IDOR vulnerability is fixed by adding authentication enforcement via @login_required decorator and including an ownership check in the SQL query (AND owner_email = %s) so users can only access their own devices.

## Secure Code
```python
@app.route('/iot/thermostat/<int:device_num>/settings', methods=['GET'])
@login_required
def fetch_thermostat_config(device_num):
    current_user_email = get_authenticated_user_email()
    if not current_user_email:
        return jsonify({'error': 'Authentication required'}), 401

    db_conn = get_database_connection()
    cursor = db_conn.cursor()
    query = "SELECT device_id, owner_email, temp_schedule, api_key FROM smart_thermostats WHERE device_id = %s AND owner_email = %s"
    cursor.execute(query, (device_num, current_user_email))
    thermostat_data = cursor.fetchone()
    if thermostat_data:
        return jsonify({
            'device_id': thermostat_data[0],
            'owner': thermostat_data[1],
            'schedule': thermostat_data[2],
            'api_key': thermostat_data[3]
        }), 200
    return jsonify({'error': 'Device not found or access denied'}), 404
```
