{"title":"JWT Signature Verification Bypass via alg=none Acceptance","language":"Python","severity":"Critical","cwe":"CWE-347","source_lines":[8],"flow_lines":[8,9,10,11,12,13],"sink_lines":[13],"vulnerable_code":"import jwt\nimport json\nfrom flask import request, jsonify\n\ndef validate_iot_device_token(auth_header):\n    if not auth_header or not auth_header.startswith('Bearer '):\n        return {'authenticated': False, 'error': 'Missing token'}\n    device_token = auth_header.split(' ')[1]\n    try:\n        token_parts = device_token.split('.')\n        header = json.loads(jwt.utils.base64url_decode(token_parts[0]))\n        if header.get('alg') == 'none':\n            payload = json.loads(jwt.utils.base64url_decode(token_parts[1]))\n            return {'authenticated': True, 'device_id': payload.get('device_id'), 'permissions': payload.get('perms')}\n        decoded = jwt.decode(device_token, 'iot_secret_key_2024', algorithms=['HS256', 'RS256'])\n        return {'authenticated': True, 'device_id': decoded.get('device_id'), 'permissions': decoded.get('perms')}\n    except Exception as e:\n        return {'authenticated': False, 'error': str(e)}\n\n@app.route('/api/iot/telemetry', methods=['POST'])\ndef receive_telemetry():\n    auth_result = validate_iot_device_token(request.headers.get('Authorization'))\n    if not auth_result.get('authenticated'):\n        return jsonify({'status': 'unauthorized'}), 401\n    telemetry_data = request.json\n    return jsonify({'status': 'accepted', 'device': auth_result['device_id']}), 200","explanation":"The code explicitly accepts JWT tokens with 'alg=none' and manually decodes the payload without cryptographic verification. An attacker can forge arbitrary tokens by setting the algorithm to 'none', bypassing authentication entirely and impersonating any IoT device with fabricated permissions.","remediation":"The fix removes the entire block that checked for 'alg=none' and manually decoded the payload without signature verification. Now all tokens must be cryptographically verified using jwt.decode() with a strictly defined allowed algorithms list limited to 'HS256' only, preventing both the 'none' algorithm attack and algorithm confusion attacks with RS256.","secure_code":"import jwt\nfrom flask import request, jsonify\n\ndef validate_iot_device_token(auth_header):\n    if not auth_header or not auth_header.startswith('Bearer '):\n        return {'authenticated': False, 'error': 'Missing token'}\n    device_token = auth_header.split(' ')[1]\n    try:\n        decoded = jwt.decode(device_token, 'iot_secret_key_2024', algorithms=['HS256'])\n        return {'authenticated': True, 'device_id': decoded.get('device_id'), 'permissions': decoded.get('perms')}\n    except Exception as e:\n        return {'authenticated': False, 'error': str(e)}\n\n@app.route('/api/iot/telemetry', methods=['POST'])\ndef receive_telemetry():\n    auth_result = validate_iot_device_token(request.headers.get('Authorization'))\n    if not auth_result.get('authenticated'):\n        return jsonify({'status': 'unauthorized'}), 401\n    telemetry_data = request.json\n    return jsonify({'status': 'accepted', 'device': auth_result['device_id']}), 200"}