Webhook 密钥问题

希望有人能告诉我我在这里做错了什么。

我设置了一个 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 中应该如何处理这些信息。

我不确定这只是你写帖子的方式,但实际的标头应该是

X-Discourse-Event-Signature: XXX

你可以在接收端(可选地)使用它来验证 webhook 是否确实由 Discourse 发送。如果你不进行验证,那么恶意方可能会伪造 webhook 事件。

这是什么意思?

1 个赞

所以你的建议是接收 webhook 中的 Signature 应该是加密后的 secret,而不是未加密的选定 secret?

我确实是这样在接收应用程序中编写 Header 的:
X-Discourse-Event-Signature: XXX

但是,当我使用 Secret 时,我一直收到 401 禁止访问错误。

截图来自哪里?
也许你可以更详细地介绍一下你的设置。

我的 Wordpress 网站。我正在使用一个 Wordpress 插件来接收 Webhooks。如果我不添加安全标头(Secret),Webhook 可以正常工作。只有当我添加 Secret 时,问题才会出现。

这是插件:Incoming Webhook Triggers - Uncanny Automator

感谢您的时间和 Richard!

1 个赞

我后来缩小了问题范围:

传入的 webhook 触发器可能包含自定义安全标头,但有一个重要说明是 WordPress 如何将连字符更改为下划线。例如,尝试使用“x-api-key”可能需要改用“x_api_key”。

不过,我有一个相关问题 @RGJ。假设我的密钥是“1234”。在接收的 webhook 中,X-Discourse-Event-Signature 的值应该是:

  1. 1234;
  2. sha256=encrypted_value_here;
  3. encrypted_value_here

它是#2,sha256=XXX

看起来您正在使用的WordPress插件只能与静态标头值进行比较,而不能与动态签名进行比较。这是Discourse特有的东西。

1 个赞

看看WP Discourse插件是如何处理密钥的:

5 个赞

我后来发现,每次发送 webhook 时 sha 值都会改变,所以将 sha 值放在接收 webhook 中是行不通的。我认为它必须是示例 #1,而且正如您可能建议的那样(重新静态标头),插件实际上是否需要在生成标头响应之前解码哈希?

总之,我认为我无法在此插件中使用哈希的 X-Discourse-Event-Signature,因为它只接受静态值。

使用没有 Secret 的 webhook 是否不安全?我将从我的 Discourse 发送用户事件到我的主网站,使用一个不明显的 URL,例如 main-site.com/wp-json/fol/fil/532563-5312534。我还可以添加必须在接收钩子上匹配的静态标头。

您能否给我一个可以处理动态变化的 hmac 的应用程序示例?

该值是根据 webhook 的 payload 计算的,因此每次请求都会不同。

这是一个有趣的问题。我所知道的唯一应用程序是 WP Discourse 插件,但它是专门配置来处理 Discourse webhook 的。如果 Discourse 的实现阻止人们使用 secret 验证 webhook,那么可能需要对此进行调查。

我将把这个问题留给其他人来回答。

如果您担心不验证 webhook,那么 Incoming Webhook Triggers 插件在其接收 webhook 的代码中可能有一个操作钩子,该钩子在处理 webhook 数据之前触发。如果存在,应该可以编写一个函数来挂接到它,检查数据是否是 Discourse webhook 的,然后使用我之前帖子中链接的代码之类的东西来验证 secret。

2 个赞

我很好奇,所以对此进行了一些研究。我不确定有哪些应用程序被配置为处理_接收_动态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上验证签名。我目前没有设置来测试这一点。)

2 个赞

我完全同意这一点。也许这是开发人员可以探索的事情——一种更简单、更兼容的方法来保护网络钩子数据。

另外,我不太确定 Zapier 是否有能力验证签名。

Webhook 密钥功能是根据以下内容实现的:

您想要的软件似乎不支持此标准安全通信功能,但您仍然可以不使用它来利用 Discourse Webhooks。

没有计划添加带有共享密钥的固定标头,因为其安全价值值得怀疑。但是,如果您需要此功能,应该可以在插件中实现。

4 个赞