SiberianGuy
SiberianGuy

Reputation: 25292

AntiXss protection Html model properties

Some of my model properties are marked by AllowHtml attribute. Is there any way to automatically apply AntiXss protection (i. e. filter only allowed tags) to these fields?

Upvotes: 10

Views: 2210

Answers (4)

VJAI
VJAI

Reputation: 32758

I would go for replacing those AllowHtml attributes with RegularExpression data-annotation validations. The advantage is by this way you can trap the error and show to the user what went wrong while the former one fires the error at a global level.

For ex.

public class MyViewModel
{
    [DataType(DataType.MultilineText)]
    [RegularExpression(@"^[^\<\>]*$", ErrorMessage = "May not contain <,>")]
    public string Text { get; set; }
}

Ref: RegularExpression validator encoding regex < & > symbols as &lt; &gt;, causing jQuery validation to fail

Upvotes: 1

Shaddix
Shaddix

Reputation: 6109

First, afaik, nothing is built-in for that. But MVC allows to do such things easily via custom ModelBinders, you could define your

public class CustomAntiXssAttribute : Attribute { }

and decorate your properties with it (and even inherit from AllowHtmlAttribute if you wish). Then with a model binder you could add your specific anti-xss protection:

    public class CutstomModelBinder : DefaultModelBinder
    {
        protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
        {
            if (propertyDescriptor.Attributes.OfType<CustomAntiXssAttribute>().Any())
            {
                var valueResult = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);
                var filteredValue = SOME_CUSTOM_FILTER_FUNCTION_HERE(valueResult.AttemptedValue);
                propertyDescriptor.SetValue(bindingContext.Model, filteredValue);
            }
            else // revert to the default behavior.
            {
                base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
            }
        }
    }

Then inside that SOME_CUSTOM_FILTER_FUNCTION_HERE you could use what @Yogiraj suggested, or use a Regexp, or even apply HtmlAgilityPack-based filtering.

P.S. Don't forget to add ModelBinders.Binders.DefaultBinder = new CutstomModelBinder(); to Application_Start (I forgot :))

Upvotes: 10

Untested Code,

public class ADefaultModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelMetadata.RequestValidationEnabled)
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;
            value = value.Replace("&", "");// replace existing & from the value
            var encodedValue = Microsoft.Security.Application.Encoder.HtmlEncode(value);
            bindingContext.ModelMetadata.RequestValidationEnabled = encodedValue.Contains("&"); // Whether AntiXss encoded a char to &..
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}
public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        ModelBinders.Binders.DefaultBinder = new ADefaultModelBinder();

Upvotes: 0

Yogiraj
Yogiraj

Reputation: 1982

There is no automatic way. The closest you can do is to get AntiXss Nuget package. Then you can use it like below in your controller :

  Microsoft.Security.Application.Sanitizer.GetSafeHtml("YourHtml");

OR

  Microsoft.Security.Application.Encoder.HtmlEncode("YourHtml");

If you use you can decode it using

  Server.HtmlDecode("HtmlEncodedString");

Hope this helps.

Upvotes: 4

Related Questions