70 votes

Angular contre Asp.Net WebApi, implémentez CSRF sur le serveur.

Je me suis mise en œuvre d'un site web Angular.js qui frappe un ASP.NET WebAPI backend.

Angular.js a quelques fonctionnalités intégrées pour aider avec des anti-csrf de protection. Sur chaque requête http, il va chercher un cookie appelé "XSRF-TOKEN" et de le présenter comme un en-tête "X-XSRF-JETON" .

Cela repose sur le serveur web capable de définir la XSRF-JETON de cookie après l'authentification de l'utilisateur, puis la vérification de la X-XSRF-JETON-tête pour les requêtes entrantes.

L' Angulaire de la documentation états:

Pour bénéficier de cette fonction, votre serveur doit mettre un jeton dans un JavaScript lisible cookie de session appelé XSRF-JETON sur la première requête HTTP GET. Sur les non-demandes GET le serveur peut vérifier que le témoin correspond à X-XSRF-JETON en-tête HTTP, et donc être sûr que le code JavaScript s'exécutant sur votre nom de domaine pourrait avoir lu le jeton. Le jeton doit être unique pour chaque utilisateur et doit être vérifiable par le serveur (pour éviter le JavaScript de faire ses propres jetons). Nous recommandons que le jeton est un condensé de votre site cookie d'authentification avec le sel pour plus de sécurité.

Je ne pouvais pas trouver tout de bons exemples de ce pour ASP.NET WebAPI, donc j'ai roulé mon propre avec l'aide de diverses sources. Ma question est, peut-on voir quelque chose de mal avec le code?

J'ai d'abord défini une simple classe helper:

public class CsrfTokenHelper
{
    const string ConstantSalt = "<ARandomString>";

    public string GenerateCsrfTokenFromAuthToken(string authToken)
    {
        return GenerateCookieFriendlyHash(authToken);
    }

    public bool DoesCsrfTokenMatchAuthToken(string csrfToken, string authToken) 
    {
        return csrfToken == GenerateCookieFriendlyHash(authToken);
    }

    private static string GenerateCookieFriendlyHash(string authToken)
    {
        using (var sha = SHA256.Create())
        {
            var computedHash = sha.ComputeHash(Encoding.Unicode.GetBytes(authToken + ConstantSalt));
            var cookieFriendlyHash = HttpServerUtility.UrlTokenEncode(computedHash);
            return cookieFriendlyHash;
        }
    }
}

Puis j'ai la méthode suivante dans mon autorisation du contrôleur, et je l'appelle après j'appelle FormsAuthentication.SetAuthCookie():

    // http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks
    // http://docs.angularjs.org/api/ng.$http
    private void SetCsrfCookie()
    {
        var authCookie = HttpContext.Current.Response.Cookies.Get(".ASPXAUTH");
        Debug.Assert(authCookie != null, "authCookie != null");
        var csrfToken = new CsrfTokenHelper().GenerateCsrfTokenFromAuthToken(authCookie.Value);
        var csrfCookie = new HttpCookie("XSRF-TOKEN", csrfToken) {HttpOnly = false};
        HttpContext.Current.Response.Cookies.Add(csrfCookie);
    }

Ensuite, j'ai un attribut personnalisé qui je peux ajouter des contrôleurs de les faire vérifier le csrf en-tête:

public class CheckCsrfHeaderAttribute : AuthorizeAttribute
{
    //  http://stackoverflow.com/questions/11725988/problems-implementing-validatingantiforgerytoken-attribute-for-web-api-with-mvc
    protected override bool IsAuthorized(HttpActionContext context)
    {
        // get auth token from cookie
        var authCookie = HttpContext.Current.Request.Cookies[".ASPXAUTH"];
        if (authCookie == null) return false;
        var authToken = authCookie.Value;

        // get csrf token from header
        var csrfToken = context.Request.Headers.GetValues("X-XSRF-TOKEN").FirstOrDefault();
        if (String.IsNullOrEmpty(csrfToken)) return false;

        // Verify that csrf token was generated from auth token
        // Since the csrf token should have gone out as a cookie, only our site should have been able to get it (via javascript) and return it in a header. 
        // This proves that our site made the request.
        return new CsrfTokenHelper().DoesCsrfTokenMatchAuthToken(csrfToken, authToken);
    }
}

Enfin, je effacer le jeton Csrf lorsque l'utilisateur se déconnecte:

HttpContext.Current.Response.Cookies.Remove("XSRF-TOKEN");

Quelqu'un peut-il repérer toute évidente (ou pas si évident) problèmes avec cette approche?

8voto

vittore Points 8364

Votre code semble aller pour le mieux. La seule chose est, vous n'avez pas besoin de plus de code que vous avez en tant que web.l'api fonctionne "au dessus" de asp.net mvc, et ce dernier a un support intégré pour la lutte anti-contrefaçon jetons.

http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-les attaques

Jetez également un œil à cette question AngularJS ne pouvez pas trouver XSRF-JETON de cookie

-4voto

Gaur Puneet Points 1
public class CheckCsrfHeaderAttribute : AuthorizeAttribute
{
    //  http://stackoverflow.com/questions/11725988/problems-implementing-validatingantiforgerytoken-attribute-for-web-api-with-mvc
    protected override bool IsAuthorized(HttpActionContext context)
    {
        // get auth token from cookie
        var authCookie = HttpContext.Current.Request.Cookies[".ASPXAUTH"];
        if (authCookie == null) return false;
        var authToken = authCookie.Value;

        // get csrf token from header
        var csrfToken = context.Request.Headers.GetValues("X-XSRF-TOKEN").FirstOrDefault();
        if (String.IsNullOrEmpty(csrfToken)) return false;

        // Verify that csrf token was generated from auth token
        // Since the csrf token should have gone out as a cookie, only our site should have been able to get it (via javascript) and return it in a header. 
        // This proves that our site made the request.
        return new CsrfTokenHelper().DoesCsrfTokenMatchAuthToken(csrfToken, authToken);
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X