Transient System.Security.Cryptography.CryptographicException в TwilioRequestValidator - PullRequest
0 голосов
/ 15 февраля 2019

Итак, у нас есть наша настройка обратных вызовов Twilio для проверки входящих запросов через документально подтвержденный TwilioRequestValidator здесь .

Однако мы видим, что рабочий сервер будет работать неделямибез проблем, а затем вдруг начать сбой с CryptographicException.Это приводит к сбою всех входящих запросов Twilio.

У нас есть стек вызовов (благодаря Azure Application Insights):

    System.Security.Cryptography.CryptographicException:
   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Security.Cryptography.Utils.HashData (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Security.Cryptography.SHA1CryptoServiceProvider.HashCore (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Security.Cryptography.HashAlgorithm.TransformBlock (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Security.Cryptography.HMAC.HashCore (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at System.Security.Cryptography.HashAlgorithm.ComputeHash (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at Twilio.Security.RequestValidator.GetValidationSignature (Twilio, Version=5.14.1.0, Culture=neutral, PublicKeyToken=null)
   at Misc.TwilioRequestValidator.ValidateTwilioRequestAttribute.IsValidRequest (RCHHRATool, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)
   at Misc.TwilioRequestValidator.ValidateTwilioRequestAttribute.OnActionExecuting (RCHHRATool, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker+AsyncInvocationWithFilters.InvokeActionMethodFilterAsynchronouslyRecursive (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker+AsyncInvocationWithFilters.InvokeActionMethodFilterAsynchronouslyRecursive (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__31 (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1.Begin (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeActionMethodWithFilters (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass21.<BeginInvokeAction>b__19 (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1.Begin (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Controller.<BeginExecuteCore>b__1c (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncVoid`1.CallBeginDelegate (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1.Begin (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Controller.BeginExecuteCore (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1.Begin (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Controller.BeginExecute (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4 (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncVoid`1.CallBeginDelegate (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.Async.AsyncResultWrapper+WrappedAsyncResultBase`1.Begin (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest (System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Web.HttpApplication+<>c__DisplayClass285_0.<ExecuteStepImpl>b__0 (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Web.HttpApplication.ExecuteStepImpl (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
   at System.Web.HttpApplication.ExecuteStep (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)

И у нас есть некоторый код приложения, здесь:

[AttributeUsage(AttributeTargets.Method)]
public class ValidateTwilioRequestAttribute : ActionFilterAttribute
{
    private readonly RequestValidator _requestValidator;

    public ValidateTwilioRequestAttribute()
    {
        var authToken = ConfigurationManager.AppSettings["TwilioAuthToken"];
        _requestValidator = new RequestValidator(authToken);
    }

    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        var context = actionContext.HttpContext;
        if (!IsValidRequest(context.Request))
        {
            actionContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
        }

        base.OnActionExecuting(actionContext);
    }

    private bool IsValidRequest(HttpRequestBase request)
    {
        var signature = request.Headers["X-Twilio-Signature"];
        Debug.WriteLine(request.Headers["X-Twilio-Signature"]);
        //var requestUrl = request.RawUrl;
        var requestUrl = rewriteUri(request.Url.AbsoluteUri);
        Debug.WriteLine("URI is: " + rewriteUri(request.Url.AbsoluteUri));

        return _requestValidator.Validate(requestUrl, request.Form, signature);
    }

    private string rewriteUri(string absoluteUri)
    {
        //check to make sure we're not replacing 'https' with 'httpss'
        if (!absoluteUri.Contains("https"))
        {
            return Regex.Replace(absoluteUri, @"http", "https");
        }
        return absoluteUri;
    }
}

Есть идеи о том, что может быть причиной этого?В идеале я хотел бы обработать это состояние исключения, но я не уверен, как обработать исключение, не зная, в чем причина.

РЕДАКТИРОВАТЬ: я получаю это сообщение об ошибке, когда я вхожу висключение в понимании приложения:

«Хэш недействителен для использования в указанном состоянии.»

РЕДАКТИРОВАТЬ # 2: быстрый поиск по этим сообщениям об ошибках выкапывает это интересное обсуждениепо безопасности потока объекта Криптография.

1 Ответ

0 голосов
/ 15 февраля 2019

Похоже, что это ошибка в библиотеке Twilio-csharp.Я полагаю, что они используют свой член Sha1 не потокобезопасным способом.

Я взломал решение для повторного запуска класса в случае CryptographicException.Поскольку перезапуск сервера устраняет проблему, я думаю, что принудительное повторное инициирование класса необходимо.

    try
    {
        return _requestValidator.Validate(requestUrl, request.Form, signature);
    }
    catch (CryptographicException e)
    {
        //if the request fails, re-init the class and try again
        var authToken = ConfigurationManager.AppSettings["TwilioAuthToken"];
        _requestValidator = new RequestValidator(authToken);
        return IsValidRequest(request);
    }
...