{"title":"Timing Attack via Naive String Comparison in HMAC Verification","language":"Python","severity":"High","cwe":"CWE-208","source_lines":[5],"flow_lines":[5,6],"sink_lines":[6],"vulnerable_code":"import hmac\nimport hashlib\n\ndef validate_iot_device_signature(device_payload, received_sig, shared_secret):\n    computed_sig = hmac.new(shared_secret.encode(), device_payload.encode(), hashlib.sha256).hexdigest()\n    if computed_sig == received_sig:\n        return {\"authenticated\": True, \"device_id\": device_payload.split(':')[0]}\n    return {\"authenticated\": False, \"device_id\": None}\n\ndef process_telemetry_data(device_msg, signature, secret_key):\n    auth_result = validate_iot_device_signature(device_msg, signature, secret_key)\n    if auth_result[\"authenticated\"]:\n        telemetry = device_msg.split(':')[1]\n        return {\"status\": \"accepted\", \"data\": telemetry}\n    return {\"status\": \"rejected\", \"error\": \"Invalid signature\"}","explanation":"The code uses naive string comparison (==) to validate HMAC signatures instead of constant-time comparison. This allows timing attacks where an attacker can measure response times to deduce the correct signature byte-by-byte, as the comparison fails faster when earlier bytes are incorrect.","remediation":"The fix replaces the naive string comparison operator (==) with hmac.compare_digest(), which performs a constant-time comparison of the two strings. This prevents timing attacks because the function takes the same amount of time regardless of how many bytes match, making it impossible for an attacker to deduce the correct signature by measuring response times.","secure_code":"import hmac\nimport hashlib\n\ndef validate_iot_device_signature(device_payload, received_sig, shared_secret):\n    computed_sig = hmac.new(shared_secret.encode(), device_payload.encode(), hashlib.sha256).hexdigest()\n    if hmac.compare_digest(computed_sig, received_sig):\n        return {\"authenticated\": True, \"device_id\": device_payload.split(':')[0]}\n    return {\"authenticated\": False, \"device_id\": None}\n\ndef process_telemetry_data(device_msg, signature, secret_key):\n    auth_result = validate_iot_device_signature(device_msg, signature, secret_key)\n    if auth_result[\"authenticated\"]:\n        telemetry = device_msg.split(':')[1]\n        return {\"status\": \"accepted\", \"data\": telemetry}\n    return {\"status\": \"rejected\", \"error\": \"Invalid signature\"}"}