Mandrill Webhook - 安全性

Posted

技术标签:

【中文标题】Mandrill Webhook - 安全性【英文标题】:Mandrill Webhooks - Security 【发布时间】:2013-04-20 11:19:33 【问题描述】:

出于安全考虑,我尝试只允许 Mandrill 的 IP 访问这些 url。

有人认识他们吗?

【问题讨论】:

【参考方案1】:

Mandrill 的签名位于 HTTP 响应头中:Authenticating-webhook-requests

在请求头中找到:X-Mandrill-Signature。这是哈希码的 base64,使用 web-hook 密钥签名。此密钥仅对您的 webhook 保密。

【讨论】:

【参考方案2】:

我们有一系列用于 webhook 的 IP,但随着我们的扩展,它们可以(并且可能会)更改或添加新的 IP。另一种方法是将查询字符串添加到您在 Mandrill 中添加的 webhook URL,然后在 POST 进入时检查该查询字符串,以便验证它来自 Mandrill。

【讨论】:

哦,是的,好主意。对于其他人,它是关于元数据信息的。这是一个码头,我现在不喜欢你的帖子:)。谢谢 不能欺骗IP! @ankitjaininfo 偶然发现了这个问题,你的评论激起了我的好奇心。我的第一直觉是“不容易”。然后我在 IT Security Stack Exchange 上找到了这篇文章:security.stackexchange.com/questions/14505/…。我猜,迟到 3 年总比没有好。【参考方案3】:

只需替换常量并使用此功能:

<?php 

function generateSignature($post)
    
        $signed_data = WEB_HOOK_URL;
        ksort($post);
        foreach ($post as $key => $value) 
            $signed_data .= $key;
            $signed_data .= $value;
        

        return base64_encode(hash_hmac('sha1', $signed_data, WEB_HOOK_AUTH_KEY, true));
    

//---

if (generateSignature($_POST) != $_SERVER['HTTP_X_MANDRILL_SIGNATURE']) 
    //Invalid


?>

【讨论】:

【参考方案4】:

正如 mandrill 的 docs 中所述,它们提供了一个签名来检查请求是否真的来自它们。构建请求有几个步骤:

    从您的 webhook 的确切 url 开始(注意斜线和参数) 按键排序后变量(如果是 mandrill,您将只有一个后参数:mandrill_events) 在url中添加key和value,不带任何分隔符 使用您的密钥(您可以从 Web 界面获取密钥)和 base64 对 url 进行 hmac 处理。 将结果与X-Mandrill-Signature 标头进行比较

这里是python中的一个示例实现:

import hmac, hashlib

def check_mailchimp_signature(params, url, key):
    signature = hmac.new(key, url, hashlib.sha1)
    for key in sorted(params):
        signature.update(key)
        signature.update(params[key])
    return signature.digest().encode("base64").rstrip("\n")

【讨论】:

【参考方案5】:

205.201.136.0/16

我刚刚在我的服务器防火墙中将它们列入白名单。

【讨论】:

【参考方案6】:

我们不需要将他们使用的 IP 列入白名单。相反,他们提供了自己的方式来验证 webhook 请求。

当您创建 mandrill webhook 时,它将生成密钥。它将来自我们对 webhook 中提供的帖子 URL 的响应。

public async Task<IHttpActionResult> MandrillEmailWebhookResponse()
        
    string mandrillEvents = HttpContext.Current.Request.Form["mandrill_events"].Replace("mandrill_events=", "");

                // validate the request is coming from mandrill API
                string url = ConfigurationManager.AppSettings["mandrillWebhookUrl"];
                string MandrillKey = ConfigurationManager.AppSettings["mandrillWebHookKey"];
                url += "mandrill_events";
                url += mandrillEvents;
                byte[] byteKey = System.Text.Encoding.ASCII.GetBytes(MandrillKey);
                byte[] byteValue = System.Text.Encoding.ASCII.GetBytes(url);

                HMACSHA1 myhmacsha1 = new HMACSHA1(byteKey);
                byte[] hashValue = myhmacsha1.ComputeHash(byteValue);
                string generatedSignature = Convert.ToBase64String(hashValue);

                string mandrillSignature = HttpContext.Current.Request.Headers["X-Mandrill-Signature"].ToString();

                if (generatedSignature == mandrillSignature)
                
                    // validation = "Validation successful";
                    // do the updating using the response data
                

【讨论】:

以上是关于Mandrill Webhook - 安全性的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 验证 Mandrill Webhook

从 Mandrill Webhook 接收到的 JSON 字符串无效

将 Mandrill JSON webhook 入站电子邮件附件映射到 C# 类

如何在 .net 中处理 Mandrill WebHooks

ruby 中的 Mandrill 验证,在 php 和 ruby​​ 之间的翻译中丢失

怎么使用Coding提供的Webhook做持续集成测试的么