{"title":"IDOR via Predictable Device Identifier Enumeration","language":"Python","severity":"Critical","cwe":"CWE-89","source_lines":[2],"flow_lines":[2,4,5],"sink_lines":[5],"vulnerable_code":"@app.route('/iot/thermostat/<int:device_num>/settings', methods=['GET'])\ndef fetch_thermostat_config(device_num):\n    db_conn = get_database_connection()\n    cursor = db_conn.cursor()\n    query = f\"SELECT device_id, owner_email, temp_schedule, api_key FROM smart_thermostats WHERE device_id = {device_num}\"\n    cursor.execute(query)\n    thermostat_data = cursor.fetchone()\n    if thermostat_data:\n        return jsonify({\n            'device_id': thermostat_data[0],\n            'owner': thermostat_data[1],\n            'schedule': thermostat_data[2],\n            'api_key': thermostat_data[3]\n        }), 200\n    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":"@app.route('/iot/thermostat/<int:device_num>/settings', methods=['GET'])\n@login_required\ndef fetch_thermostat_config(device_num):\n    current_user_email = get_authenticated_user_email()\n    if not current_user_email:\n        return jsonify({'error': 'Authentication required'}), 401\n\n    db_conn = get_database_connection()\n    cursor = db_conn.cursor()\n    query = \"SELECT device_id, owner_email, temp_schedule, api_key FROM smart_thermostats WHERE device_id = %s AND owner_email = %s\"\n    cursor.execute(query, (device_num, current_user_email))\n    thermostat_data = cursor.fetchone()\n    if thermostat_data:\n        return jsonify({\n            'device_id': thermostat_data[0],\n            'owner': thermostat_data[1],\n            'schedule': thermostat_data[2],\n            'api_key': thermostat_data[3]\n        }), 200\n    return jsonify({'error': 'Device not found or access denied'}), 404"}