{"title":"Timing Attack via Naive HMAC Comparison","language":"Python","severity":"High","cwe":"CWE-208","source_lines":[6],"flow_lines":[6,7],"sink_lines":[7],"vulnerable_code":"import hashlib\nimport hmac\n\ndef verify_iot_device_signature(device_id, payload, received_sig):\n    secret_key = get_device_secret(device_id)\n    expected_sig = hmac.new(secret_key.encode(), payload.encode(), hashlib.sha256).hexdigest()\n    if received_sig == expected_sig:\n        return {\"authenticated\": True, \"device\": device_id}\n    return {\"authenticated\": False, \"error\": \"Invalid signature\"}\n\ndef get_device_secret(device_id):\n    device_secrets = {\"sensor_001\": \"prod_key_9x7m2\", \"sensor_002\": \"prod_key_4k8n1\"}\n    return device_secrets.get(device_id, \"default_secret\")","explanation":"The code uses Python's standard string equality operator (==) to compare HMAC signatures on line 7, which performs character-by-character comparison and exits early on the first mismatch. This timing difference allows attackers to perform byte-by-byte brute force attacks by measuring response times to guess each byte of the valid signature sequentially.","remediation":"The fix replaces the naive string equality comparison (==) with hmac.compare_digest(), which is a constant-time comparison function designed to prevent timing attacks. This function always compares all bytes regardless of where mismatches occur, making it impossible for an attacker to deduce correct signature bytes by measuring response times.","secure_code":"import hashlib\nimport hmac\n\ndef verify_iot_device_signature(device_id, payload, received_sig):\n    secret_key = get_device_secret(device_id)\n    expected_sig = hmac.new(secret_key.encode(), payload.encode(), hashlib.sha256).hexdigest()\n    if hmac.compare_digest(received_sig, expected_sig):\n        return {\"authenticated\": True, \"device\": device_id}\n    return {\"authenticated\": False, \"error\": \"Invalid signature\"}\n\ndef get_device_secret(device_id):\n    device_secrets = {\"sensor_001\": \"prod_key_9x7m2\", \"sensor_002\": \"prod_key_4k8n1\"}\n    return device_secrets.get(device_id, \"default_secret\")"}