16 Jul
2009

Prüfen ob alle Post-Controller-Actions dass ValidateAntiForgeryTokenAttribute haben

 

Ein möglicher Angriff auf Web-Anwendungen ist Cross-Site Request Forgery (CSRF). Mit dem ASP.NET MVC Framework gibt es eine Möglichkeit solche Angriffe zu verhindern.

Siehe dazu auch diesen Blog-Eintrag: Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper.

Jedoch passiert es mir des Öfteren dass ich vergesse daran zu denken die Actions entsprechend zu attributieren.

Deshalb habe ich mir einen Unit-Test geschrieben der alle Controller-Action die auf POST reagieren überprüft ob sie dass ValidateAntiForgeryTokenAttribute haben.

Damit er nicht bei mir versauert, hier der Test zur allgemeinen Verwendung.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;

using DerAlbert.Community.Web.Controllers;

using MbUnit.Framework;

namespace DerAlbert.Community.Web.Tests.Controllers
{
    [TestFixture]
    public class ControllerTests
    {
        [Test]
        public void Controller_AllePostActions_NutzenValidateAntiForgeryTokenAttribute()
        {
            foreach (var controllerType in AllControllerTypes())
            {
                foreach (var methodInfo in GetActionMethods(controllerType))
                {
                    if (MethodAcceptsPost(methodInfo))
                    {
                        Assert.IsTrue(HasValidateAntiForgeryTokenAttribute(methodInfo),
                                      string.Format("{0}.{1} nutzt nicht das ValidateAntiForgeryTokenAttribute",
                                                    controllerType.FullName, methodInfo.Name));
                    }
                }
            }
        }

        private bool HasValidateAntiForgeryTokenAttribute(MethodInfo methodInfo)
        {
            return null != (from a in methodInfo.GetCustomAttributes(false)
                            where a is ValidateAntiForgeryTokenAttribute
                            select a).SingleOrDefault();
        }

        private bool MethodAcceptsPost(MethodInfo methodInfo)
        {
            var attribute = (AcceptVerbsAttribute) (from a in methodInfo.GetCustomAttributes(false)
                                                    where a is AcceptVerbsAttribute
                                                    select a).SingleOrDefault();

            return attribute != null && attribute.Verbs.Contains("POST");
        }

        private IEnumerable<Type> AllControllerTypes()
        {
            return from t in typeof (HomeController).Assembly.GetExportedTypes()
                   where typeof (Controller).IsAssignableFrom(t)
                   select t;
        }

        private IEnumerable<MethodInfo> GetActionMethods(Type controllerType)
        {
            return from mi in controllerType.GetMethods()
                   where typeof (ActionResult).IsAssignableFrom(mi.ReturnType)
                   select mi;
        }
    }
}
Technorati-Tags: ,,,

Der Eintrag ist mir etwas Wert
 
Comments have been closed on this topic.