如何验证CrowdStrike发送至Python应用的Webhook签名?
CrowdStrike Webhook签名验证修正方案
CrowdStrike的Webhook签名并非仅对请求体进行哈希,而是将请求头中的时间戳与原始请求体拼接后,通过HmacSHA256生成签名。以下是正确的验证步骤和代码:
关键验证逻辑
- 从请求头中获取
X-Cs-Webhook-Timestamp字段值(这是签名生成时用到的时间戳) - 将时间戳与原始请求体用换行符
\n拼接成字节流(务必保持请求体的原始格式,不要解析后再序列化) - 使用共享密钥对拼接后的内容进行HmacSHA256哈希,再做Base64编码
- 将生成的签名与请求头中的
X-Cs-Webhook-Signature字段值对比,一致则验证通过
修正后的Python代码示例
import hmac import hashlib import base64 from flask import request def verify_crowdstrike_webhook(): # 获取关键参数 timestamp = request.headers.get('X-Cs-Webhook-Timestamp') raw_body = request.get_data() # 保持原始字节流,避免解析后格式变化 secret = "你的共享密钥".encode('utf-8') if not timestamp or not raw_body: return False # 拼接时间戳和请求体:时间戳转字节 + 换行符 + 原始请求体 message = f"{timestamp}\n".encode('utf-8') + raw_body # 生成HMAC哈希并Base64编码 hmac_hash = hmac.new(secret, message, hashlib.sha256).digest() computed_signature = base64.b64encode(hmac_hash).decode('utf-8') # 获取CrowdStrike发送的签名 received_signature = request.headers.get('X-Cs-Webhook-Signature') # 安全对比签名(避免时序攻击) return hmac.compare_digest(computed_signature, received_signature)
常见错误排查
- 仅哈希请求体:忽略时间戳是最常见的失败原因,必须将时间戳与请求体拼接后再哈希
- 修改请求体格式:如果先解析请求体为JSON对象再序列化回字符串,会因空格、换行符差异导致哈希不一致,务必用
request.get_data()获取原始字节流 - 密钥编码问题:确保共享密钥是UTF-8编码的字节类型,不要直接传入字符串
- 签名对比方式:使用
hmac.compare_digest()代替直接==,避免时序攻击风险
内容的提问来源于stack exchange,提问作者mark_3094
相关产品推荐
相关产品推荐

