Created
August 8, 2012 16:07
-
-
Save jkuemerle/3296254 to your computer and use it in GitHub Desktop.
CSRF Prevention Aspect for ASP.NET MVC and PostSharp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.IO; | |
| using System.Linq; | |
| using System.Reflection; | |
| using System.Web.Mvc; | |
| using PostSharp.Aspects; | |
| using PostSharp.Extensibility; | |
| namespace WebApplication.Aspects | |
| { | |
| public class OverrideCSRFValidation : Attribute { } | |
| [Serializable] | |
| public class CSRFAttribute : MethodLevelAspect { | |
| public override bool CompileTimeValidate(System.Reflection.MethodBase method) { | |
| if (method.MemberType == MemberTypes.Method && method.GetParameters().Count() > 0) { // only check methods that have parameters | |
| var attribs = method.GetCustomAttributes(true); | |
| if (attribs.Length > 0) { // only check methods that are decorated with some attributes | |
| var postAttribute = (from a in attribs where a.GetType() == typeof(System.Web.Mvc.HttpPostAttribute) select a).Count(); | |
| var bypassAttribute = (from a in attribs where a.GetType() == typeof(OverrideCSRFValidation) select a).Count(); | |
| if (postAttribute > 0 && bypassAttribute < 1) { // only bother looking for an anti-forgery attribute if this is a Post method and it does not have a bypass attribute | |
| var antiForgeryAttribute = (from a in attribs where a.GetType() == typeof(ValidateAntiForgeryTokenAttribute) select a).Count(); | |
| if (antiForgeryAttribute < 1) { | |
| var mi = method as MethodInfo; | |
| string solutionFile = PostSharpEnvironment.Current.CurrentProject.EvaluateExpression("{$SolutionFile}"); | |
| if (String.IsNullOrEmpty(solutionFile) || !File.Exists(solutionFile)) // use PostSharps experimental functionality to find the method location in the code | |
| Message.Write(PostSharp.MessageLocation.Of(mi), SeverityType.Error, "1000", "Security Error: method {0} in {1} is an HTTP Post without an anti-forgery validator.", mi.Name, method.DeclaringType.Namespace); | |
| else { // otherwise use CodeFreud and Project Roslyn to find the method location in the code | |
| var res = CodeFreud.Finder.FindMethod(solutionFile, method); | |
| if (null != res) | |
| Message.Write(PostSharp.MessageLocation.Explicit(res.SourceFile.FullName, res.LineNumber, res.ColumnNumber), SeverityType.Error, "1000", "Security Error, method {0} in {1} is an HTTP Post without an anti-forgery validator.", mi.Name, method.DeclaringType.Namespace); | |
| else | |
| Message.Write(PostSharp.MessageLocation.Unknown, SeverityType.Error, "1000", "Security Error: method {0} in {1} is an HTTP Post without an anti-forgery validator.", mi.Name, method.DeclaringType.Namespace); | |
| } | |
| return false; | |
| } | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment