{"title":"Blind Boolean-Based SQL Injection via String-Concatenated ORM Query","language":"Python","severity":"Critical","cwe":"CWE-89","source_lines":[5],"flow_lines":[5,7,8],"sink_lines":[8],"vulnerable_code":"from flask import request, jsonify\nfrom sqlalchemy import text\n\ndef check_iot_device_firmware(db_session):\n    device_mac = request.args.get('mac_address', '')\n    min_version = request.args.get('min_ver', '1.0')\n    query_str = f\"SELECT COUNT(*) as cnt FROM iot_devices WHERE mac_address='{device_mac}' AND firmware_version >= '{min_version}'\"\n    result = db_session.execute(text(query_str)).fetchone()\n    if result and result[0] > 0:\n        return jsonify({\"status\": \"compliant\", \"device_found\": True})\n    else:\n        return jsonify({\"status\": \"non_compliant\", \"device_found\": False})","explanation":"User-supplied parameters 'mac_address' and 'min_ver' from request.args are directly concatenated into an SQL query string using f-strings without sanitization or parameterization. This allows attackers to inject malicious SQL code that will be executed by db_session.execute(), enabling blind boolean-based SQL injection through the conditional response structure.","remediation":"The fix replaces the dangerous f-string SQL concatenation with parameterized queries using SQLAlchemy's named bind parameters (:mac_address and :min_version). The user-supplied values are passed as a separate dictionary to db_session.execute(), ensuring the database driver properly escapes them and prevents SQL injection.","secure_code":"from flask import request, jsonify\nfrom sqlalchemy import text\n\ndef check_iot_device_firmware(db_session):\n    device_mac = request.args.get('mac_address', '')\n    min_version = request.args.get('min_ver', '1.0')\n    query_str = text(\"SELECT COUNT(*) as cnt FROM iot_devices WHERE mac_address=:mac_address AND firmware_version >= :min_version\")\n    result = db_session.execute(query_str, {\"mac_address\": device_mac, \"min_version\": min_version}).fetchone()\n    if result and result[0] > 0:\n        return jsonify({\"status\": \"compliant\", \"device_found\": True})\n    else:\n        return jsonify({\"status\": \"non_compliant\", \"device_found\": False})"}