{"title":"Insecure Password Hashing via Unsalted MD5","language":"Python","severity":"High","cwe":"CWE-327","source_lines":[9],"flow_lines":[9,11],"sink_lines":[11],"vulnerable_code":"import hashlib\nimport boto3\nfrom datetime import datetime\n\ndef provision_iot_device_credentials(device_id, admin_pin, device_type):\n    dynamodb = boto3.resource('dynamodb', region_name='us-east-1')\n    iot_table = dynamodb.Table('IoTDeviceRegistry')\n    pin_hash = hashlib.md5(admin_pin.encode()).hexdigest()\n    device_record = {\n        'DeviceID': device_id,\n        'DeviceType': device_type,\n        'AdminPinHash': pin_hash,\n        'ProvisionedAt': datetime.utcnow().isoformat(),\n        'Status': 'active'\n    }\n    iot_table.put_item(Item=device_record)\n    return {'success': True, 'device_id': device_id, 'hash': pin_hash}","explanation":"The code uses MD5 without salt to hash sensitive admin PINs. MD5 is cryptographically broken and vulnerable to rainbow table attacks and collision attacks. Without salting, identical PINs produce identical hashes, enabling attackers who gain database access to quickly crack passwords using precomputed hash tables.","remediation":"Replaced insecure unsalted MD5 hashing with bcrypt, which automatically generates a unique salt per hash and uses a computationally expensive key derivation function (with 12 rounds of work factor) that resists brute-force and rainbow table attacks. The hash is also no longer returned in the response to avoid unnecessary exposure of sensitive data.","secure_code":"import bcrypt\nimport boto3\nfrom datetime import datetime\n\ndef provision_iot_device_credentials(device_id, admin_pin, device_type):\n    dynamodb = boto3.resource('dynamodb', region_name='us-east-1')\n    iot_table = dynamodb.Table('IoTDeviceRegistry')\n    pin_hash = bcrypt.hashpw(admin_pin.encode(), bcrypt.gensalt(rounds=12)).decode('utf-8')\n    device_record = {\n        'DeviceID': device_id,\n        'DeviceType': device_type,\n        'AdminPinHash': pin_hash,\n        'ProvisionedAt': datetime.utcnow().isoformat(),\n        'Status': 'active'\n    }\n    iot_table.put_item(Item=device_record)\n    return {'success': True, 'device_id': device_id}"}