【问题标题】:Azure/.NET CORE 3.1 - Github Webhook secret validation in Function AppAzure/.NET CORE 3.1 - Function App 中的 Github Webhook 机密验证
【发布时间】:2020-12-13 17:06:47
【问题描述】:

我正在尝试使用 .NET CORE 3.1 验证从 Github Webhook 传递的 Function App Secret Key。。 p>

在我的 Github webhook 中,我将 Azure 函数 中的默认密钥插入到 "Secret" 字段中。现在,我正在尝试在我的代码中验证它。由于某种原因,我的加密密钥与 webhook 中的不同。

注意:来自 Github Webhook 的 Secret 使用 SHA1 算法加密。

代码:

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    var secretKey = "my_key";
    StringValues outHeader;
    if (req.Headers.TryGetValue("x-hub-signature", out outHeader))
    {
        log.LogWarning("==========");
        log.LogWarning(outHeader);
        log.LogWarning(GetHash(secretKey));
        log.LogWarning("==========");
    }

    string responseMessage = "Everything went well!";
    return new OkObjectResult(responseMessage);
}

public static string GetHash(string input)
{
return "sha1=" + string.Join("", 
    (new SHA1Managed()
        .ComputeHash(Encoding.UTF8.GetBytes(input)))
        .Select(x => x.ToString("x2"))
        .ToArray());
}

输出:

2020-12-13T16:46:47.592 [Warning] ==========
2020-12-13T16:46:47.592 [Warning] sha1=f859bebbf5ec452a7ecd42efc69e0d86a4f25b16
2020-12-13T16:46:47.593 [Warning] sha1=fa1167715f137edff21d55d00adf63afb318b2a6
2020-12-13T16:46:47.593 [Warning] ==========

Official docs 仅涵盖 Node.js 解决方案。

.NET CORE 3.1 中验证 Github Webhook Secret 的正确方法是什么?感谢您的帮助。

【问题讨论】:

    标签: c# azure github .net-core webhooks


    【解决方案1】:

    您没有将此处的有效负载传递给您的 GetHash 方法,并且 GetHash 方法不接受密钥。这是我的实现:

    using Azure.Identity;
    using Azure.Security.KeyVault.Secrets;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Primitives;
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Mail;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace GitHubWebhooks
    {
        public static class Security
        {
            private const string ShaPrefix = "sha256=";
    
            private const string keyVaultUrl = "<keyvault URL or replace with some other security>";
            private const string gitHubWebhookSecretSecretName = "GitHubWebHookSecret";
    
            private static KeyVaultSecret gitHubWebhookSecret;
    
            private static async Task FetchSecrets(CancellationToken cancellationToken)
            {
                var client = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
                var gitHubWebHookSecretSecretResponse = await client.GetSecretAsync(gitHubWebhookSecretSecretName, cancellationToken: cancellationToken);
                gitHubWebhookSecret = gitHubWebHookSecretSecretResponse.Value;
            }
    
            // https://davidpine.net/blog/github-profanity-filter/
            // https://docs.github.com/en/developers/webhooks-and-events/securing-your-webhooks
            public static async Task<bool> IsGithubPushAllowedAsync(HttpRequest request, CancellationToken cancellationToken)
            {
                if (gitHubWebhookSecret == null)
                {
                    await FetchSecrets(cancellationToken);
                }
    
                request.Headers.TryGetValue("X-GitHub-Event", out StringValues eventName);
                request.Headers.TryGetValue("X-Hub-Signature-256", out StringValues signatureWithPrefix);
                request.Headers.TryGetValue("X-GitHub-Delivery", out StringValues delivery);
    
                if (string.IsNullOrWhiteSpace(eventName))
                {
                    return false;
                }
    
                if (string.IsNullOrWhiteSpace(signatureWithPrefix))
                {
                    return false;
                }
    
                if (string.IsNullOrWhiteSpace(delivery))
                {
                    return false;
                }
    
                string payload;
    
                // https://justsimplycode.com/2020/08/02/reading-httpcontext-request-body-content-returning-empty-after-upgrading-to-net-core-3-from-2-0/
                // Request buffering needs to be enabled in app startup configuration.
                // The snippet is:
                // app.Use((context, next) =>
                // {
                //     context.Request.EnableBuffering();
                //     return next();
                // });
    
                request.Body.Position = 0;
    
                // We don't close the stream as we're not the one who's opened it.
                using (var reader = new StreamReader(request.Body, leaveOpen: true))
                {
                    payload = await reader.ReadToEndAsync();
                }
    
                if (string.IsNullOrWhiteSpace(payload))
                {
                    return false;
                }
    
                string signatureWithPrefixString = signatureWithPrefix;
    
                if (signatureWithPrefixString.StartsWith(ShaPrefix, StringComparison.OrdinalIgnoreCase))
                {
                    var signature = signatureWithPrefixString.Substring(ShaPrefix.Length);
                    var secret = Encoding.ASCII.GetBytes(gitHubWebhookSecret.Value);
                    var payloadBytes = Encoding.UTF8.GetBytes(payload);
    
                    using (var sha = new HMACSHA256(secret))
                    {
                        var hash = sha.ComputeHash(payloadBytes);
    
                        var hashString = ToHexString(hash);
    
                        if (hashString.Equals(signature))
                        {
                            return true;
                        }
                    }
                }
    
                return false;
            }
    
    
            public static string ToHexString(byte[] bytes)
            {
                var builder = new StringBuilder(bytes.Length * 2);
                foreach (byte b in bytes)
                {
                    builder.AppendFormat("{0:x2}", b);
                }
    
                return builder.ToString();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-16
      • 2021-01-03
      • 1970-01-01
      • 2020-06-16
      • 2020-05-10
      • 2020-07-20
      • 2020-05-02
      • 2020-12-25
      相关资源
      最近更新 更多