希望有人能告诉我我在这里做错了什么。
我设置了一个 Discourse Webhook,在没有 Secret 的情况下,它的工作符合预期。然后,我在 Secret 中写入一个字符串,然后像这样将该字符串复制到接收 Webhook 的 Header 中:
X-Discourse-Event-Signature: secret_here
当发送 Webhook 发送时,这会在 Body 中产生以下错误:
{"code":"rest_forbidden","message":"Sorry, you are not allowed to do that.","data":{"status":401}}
我猜是我没有正确操作,所以请指教!
我知道 Secret 使用 sha256 进行加密,所以发送的 Header 是:
X-Discourse-Event-Signature: sha256=XXX
但我不知道在接收 Webhook 的安全 Header 中应该如何处理这些信息。
RGJ
(Richard - Communiteq)
2
我不确定这只是你写帖子的方式,但实际的标头应该是
X-Discourse-Event-Signature: XXX
你可以在接收端(可选地)使用它来验证 webhook 是否确实由 Discourse 发送。如果你不进行验证,那么恶意方可能会伪造 webhook 事件。
这是什么意思?
所以你的建议是接收 webhook 中的 Signature 应该是加密后的 secret,而不是未加密的选定 secret?
我确实是这样在接收应用程序中编写 Header 的:
X-Discourse-Event-Signature: XXX
但是,当我使用 Secret 时,我一直收到 401 禁止访问错误。
RGJ
(Richard - Communiteq)
4
截图来自哪里?
也许你可以更详细地介绍一下你的设置。
我的 Wordpress 网站。我正在使用一个 Wordpress 插件来接收 Webhooks。如果我不添加安全标头(Secret),Webhook 可以正常工作。只有当我添加 Secret 时,问题才会出现。
这是插件:Incoming Webhook Triggers - Uncanny Automator
感谢您的时间和 Richard!
我后来缩小了问题范围:
传入的 webhook 触发器可能包含自定义安全标头,但有一个重要说明是 WordPress 如何将连字符更改为下划线。例如,尝试使用“x-api-key”可能需要改用“x_api_key”。
不过,我有一个相关问题 @RGJ。假设我的密钥是“1234”。在接收的 webhook 中,X-Discourse-Event-Signature 的值应该是:
- 1234;
- sha256=encrypted_value_here;
- encrypted_value_here
?
RGJ
(Richard - Communiteq)
7
它是#2,sha256=XXX。
看起来您正在使用的WordPress插件只能与静态标头值进行比较,而不能与动态签名进行比较。这是Discourse特有的东西。
simon
8
看看WP Discourse插件是如何处理密钥的:
我后来发现,每次发送 webhook 时 sha 值都会改变,所以将 sha 值放在接收 webhook 中是行不通的。我认为它必须是示例 #1,而且正如您可能建议的那样(重新静态标头),插件实际上是否需要在生成标头响应之前解码哈希?
总之,我认为我无法在此插件中使用哈希的 X-Discourse-Event-Signature,因为它只接受静态值。
使用没有 Secret 的 webhook 是否不安全?我将从我的 Discourse 发送用户事件到我的主网站,使用一个不明显的 URL,例如 main-site.com/wp-json/fol/fil/532563-5312534。我还可以添加必须在接收钩子上匹配的静态标头。
您能否给我一个可以处理动态变化的 hmac 的应用程序示例?
simon
10
该值是根据 webhook 的 payload 计算的,因此每次请求都会不同。
这是一个有趣的问题。我所知道的唯一应用程序是 WP Discourse 插件,但它是专门配置来处理 Discourse webhook 的。如果 Discourse 的实现阻止人们使用 secret 验证 webhook,那么可能需要对此进行调查。
我将把这个问题留给其他人来回答。
如果您担心不验证 webhook,那么 Incoming Webhook Triggers 插件在其接收 webhook 的代码中可能有一个操作钩子,该钩子在处理 webhook 数据之前触发。如果存在,应该可以编写一个函数来挂接到它,检查数据是否是 Discourse webhook 的,然后使用我之前帖子中链接的代码之类的东西来验证 secret。
simon
11
我很好奇,所以对此进行了一些研究。我不确定有哪些应用程序被配置为处理_接收_动态HMAC签名,但使用针对负载计算的HMAC签名来验证Webhook请求,对于_发送_Webhook的应用程序来说是一种相当标准的做法。例如,GitHub、Stripe和Shopify都使用这种方法。
还有相当多的流行应用程序使用秘密令牌方法来验证Webhook。例如(截至2021年),Mailchimp、Trello、Slack和Discord都采用了这种方法。看起来Slack仍在沿用这种方法:Slack developer FAQ | Slack Developer Docs
我想在安全性和便利性之间进行权衡,以决定发送方应用程序将使用哪种方法。我对Discourse的HMAC签名方法感到担忧,因为它可能会导致人们为了绕过处理动态HMAC签名的困难而配置没有密钥的Webhook。例如,在Meta上有一些关于将Discourse Webhook发送到Zapier的参考,但没有提到如何在Zapier上验证签名。(尽管在技术上应该可以在Zapier上验证签名。我目前没有设置来测试这一点。)
我完全同意这一点。也许这是开发人员可以探索的事情——一种更简单、更兼容的方法来保护网络钩子数据。
另外,我不太确定 Zapier 是否有能力验证签名。
Falco
(Falco)
13
Webhook 密钥功能是根据以下内容实现的:
您想要的软件似乎不支持此标准安全通信功能,但您仍然可以不使用它来利用 Discourse Webhooks。
没有计划添加带有共享密钥的固定标头,因为其安全价值值得怀疑。但是,如果您需要此功能,应该可以在插件中实现。