a.png

写在前面的话

在深入了解漏洞奖励计划中的安全漏洞时,我们往往需要寻找一些用户不可见的功能下手。支付Webhook就是一种典型例子,像Stripe或Braintree这样的支付服务提供商都会使用这种技术来将用户的订购细节告知网站。重要的是,用户根本不会跟这些Webhook节点进行交互,所有的通信都是在支付提供商和服务器之间完成的。这也就意味着,很多漏洞Hunter可能从来都不会想到要去测试Webhook功能,这也就会错过很多潜在的高危漏洞。

漏洞发现

当我在对一个提供了月度订购服务的网站进行测试时,我恰好得到了该网站内部API的开发文档。其中有一个节点吸引了我的注意力,这个节点(/api/webhooks/stripe)可以接收PUT请求,根据我之前对支付提供商进行安全测试的经验来看,我认为如果我可以向这个节点发送伪造请求并让网站认为我已经完成了支付。

我首先发送了一个空的JSON请求,随后服务器返回了一条错误信息。在对该网站Webhook所使用的Stripe格式进行了分析之后,我发送了包含下列内容(body)的JSON请求:

{
  "payment": {
    "status":"success",
    "provider":"stripe"   },
  "id":"..." } 

此时服务器返回的响应信息显示状态为“成功”:

{
  "id":"...",
  "amount":1,
  "status":"success",
  "provider":"stripe" } 

就这样,我的账号授权成功了,并且显示已经成功支付了订阅服务。这就不得不让我思考了:现在还有多少网站存在这样的漏洞?支付服务提供商如何防止这种漏洞出现呢?

解决方案

实际上,支付提供商是有能力防止这种漏洞出现的,所以我才会惊讶这些节点竟然没有受到相应的安全保护。Braintree的实现方案就是正确的:用户必须通过Braintree的代码来对传入的Webhook数据进行解析,代码会自动验证请求的合法性,并提取出JSON body。这样一来,Webhook节点就会非常的安全,而且也不会被攻击者的伪造请求所欺骗。

该网站所使用的支付服务提供商-Stripe在面对Webhook安全性问题时,并不能保证“万无一失”。虽然Stripe确实提到了验证Webhook的签名,但这只是一种安全建议,他们也并没有强调这一点对Webhook安全性的整体安全性有多么重要的影响。除此之外,API文档中给出的代码样例中并没有包含任何的Webhook签名认证,而是直接对JSON请求进行了解析。

b.png

默认情况下Webhook都是不安全的,这就非常棘手了。在开发整合了支付的服务时,用户往往会采取“阻力”最小的实现方法,因此这意味着很多网站都不会对输入请求的签名进行验证。

另一个订阅支付服务提供商Recurly利用了HTTP基础认证来在服务器之间共享一个密钥,现在可能有人又要问了,难道验证共享密钥就不麻烦了吗…除此之外,Recurly还提供了一个IP地址列表,只有来自这个IP地址列表的Webhook请求才会被认为是有效的。但是,这还远远不够。比如说,攻击者可以创建一个单独的Recurly账号,然后发送有效但恶意的Webhook请求,这同样会引起安全问题。

漏洞线索

在测试跟支付相关的Webhook漏洞时,我们可以先对那些提供了月度订阅服务的网站进行分析,这是一条非常有效的线索,因为绝大多数的支付服务提供商都没有针对Webhook来实现足够有效的安全保护。

下面我们给出几种寻找Webhook节点的方法:

1.   搜索跟“Webhook”或“payment”相关的JavaScript文件,很多支付网站可能会直接暴露内部节点;

2.   搜索目标组织的GitHub代码库或相关文档,寻找关于Webhook的相关引用内容;

3.   大多数Webhook节点的数据格式可能都比较相似,所以我们可以尝试访问不同的API节点来寻找Webhook节点,比如说/api/stripe/webhook、/api/payments/webhook或/api/stripeWebhook。

总结

毫无疑问,如果支付网站想要检测任何可疑的网络行为,那么验证支付Webhook请求绝对是要默认进行的。虽然有些支付提供商会给用户提供一些方法来防止这种攻击,但这仍然需要提供商和客户的共同努力。

* 参考来源:lightningsecurity,FB小编Alpha_h4ck编译