{"title":"Insecure HMAC Comparison via == Timing Leak","language":"Python","severity":"High","cwe":"CWE-208","source_lines":[6],"flow_lines":[6,8],"sink_lines":[8],"vulnerable_code":"import hmac\nimport hashlib\nfrom flask import request, jsonify\n\ndef validate_iot_device_signature(device_id, payload, shared_secret):\n    expected_sig = hmac.new(shared_secret.encode(), f\"{device_id}:{payload}\".encode(), hashlib.sha256).hexdigest()\n    received_sig = request.headers.get('X-Device-Signature', '')\n    if received_sig == expected_sig:\n        return jsonify({\"status\": \"authorized\", \"device_id\": device_id})\n    return jsonify({\"status\": \"unauthorized\"}), 403","explanation":"The code uses a direct string comparison (==) to validate HMAC signatures instead of a constant-time comparison function like hmac.compare_digest(). This creates a timing side-channel vulnerability where attackers can perform timing attacks to gradually discover the correct signature byte-by-byte, as the comparison fails faster when earlier bytes do not match.","remediation":"The fix replaces the direct string comparison operator (==) with hmac.compare_digest(), which performs a constant-time comparison. This eliminates the timing side-channel by ensuring the comparison takes the same amount of time regardless of how many bytes match, preventing attackers from incrementally guessing the correct signature.","secure_code":"import hmac\nimport hashlib\nfrom flask import request, jsonify\n\ndef validate_iot_device_signature(device_id, payload, shared_secret):\n    expected_sig = hmac.new(shared_secret.encode(), f\"{device_id}:{payload}\".encode(), hashlib.sha256).hexdigest()\n    received_sig = request.headers.get('X-Device-Signature', '')\n    if hmac.compare_digest(received_sig, expected_sig):\n        return jsonify({\"status\": \"authorized\", \"device_id\": device_id})\n    return jsonify({\"status\": \"unauthorized\"}), 403"}