asp.net-mvc - 如何为.net core mvc应用程序集中防止脚本注入(inject)

标签 asp.net-mvc validation asp.net-core xss

我只需要一些关于实现逻辑的意见来集中检查是否没有脚本添加到输入中。

我计划使用 antiXSS (Sanitizer.GetSafeHtmlFragment("value")) 并检查输出是否为空,这意味着它可以包含脚本并处理错误。 我可以想出一个逻辑来遍历模型属性并检查值,如果有任何可疑的地方就会抛出错误。

我想知道是否有一种更好的方法来一次性处理所有输入字段的注入(inject),而不是为每个字段添加验证。

假设我有一个像这样的模型:

public class Login {
   public string Email {get; set;}
   public string Password {get; set;}
}

我可以在执行操作之前添加某种过滤来检查输入是否包含任何脚本,而不是向模型或验证表达添加一些属性,然后对每个字段单独进行 html 编码,然后抛出错误.

我想要一些非常重要的东西,这样我就不会遍历每个操作或模型并进行一些更改。

最佳答案

我使用了过滤器操作并添加了这样的代码来检查请求中任何模型的字符串类型并对其进行编码。它对我们来说工作得很好。

public static class HttpEncode
{
    public static void ParseProperties(this object model)
    {
        if (model == null) return;

        if (IsPropertyArrayOrList(model.GetType()))
        {
            ParsePropertiesOfList(model);
        }
        else
        {
            GetAllProperties(model).ForEach(t => EncodeField(t, model));
        }
    }

    private static void ParsePropertiesOfList(object model)
    {
        foreach (var item in (IEnumerable) model)
        {
            ParseProperties(item);
        }
    }

    private static List<PropertyInfo> GetAllProperties(object value) => value?.GetType()?.GetProperties()?.ToList();

    private static void EncodeField(PropertyInfo p, object arg)
    {
        try
        {
            if (p.GetIndexParameters().Length != 0 || p.GetValue(arg) == null)
                return;

            if (IsUserDefinedClass(p.PropertyType) && p.CanWrite)
            {
                ParseProperties(p.GetValue(arg));
            }
            else if (IsPropertyArrayOrList(p.PropertyType) && p.CanWrite)
            {
                ParseArrayOrListProperty(p, arg);
            }
            else if (p.PropertyType == typeof(string) && p.CanWrite)
            {
                var encodedValue = HtmlEncode(p.GetValue(arg)?.ToString());
                SetPropertyValue(p, arg, encodedValue);
            }
        }
        catch (Exception ex)
        {
            // ignored
        }
    }

    private static void ParseArrayOrListProperty(PropertyInfo p, object arg)
    {
        if (p.GetValue(arg) is string[] || p.GetValue(arg) is List<string>)
        {
            SetPropertyValueOfStaringArrayType(p, arg);
        }
        else
        {
            ParsePropertiesOfList(p.GetValue(arg));
        }
    }

    private static void SetPropertyValueOfStaringArrayType(PropertyInfo propertyInfo, object arg)
    {
        if (propertyInfo.GetValue(arg) is string[] stringValue)
        {
            var result = new List<string>();
            stringValue.ToList().ForEach(l => result.Add(HtmlEncode(l)));
            SetPropertyValue(propertyInfo, arg, result.Any() ? result.ToArray() : null);
        }
        else if (propertyInfo.GetValue(arg) is List<string> listValue)
        {
            var result = new List<string>();
            listValue.ForEach(l => result.Add(HtmlEncode(l)));
            SetPropertyValue(propertyInfo, arg, result.Any() ? result : null);
        }
    }

    private static bool IsUserDefinedClass(Type type) =>
        type.IsClass &&
        !type.FullName.StartsWith("System.");

    private static bool IsPropertyArrayOrList(Type type) =>
        type.IsArray && type.GetElementType() == typeof(string) ||
        (type != typeof(string) && type.GetInterface(typeof(IEnumerable<>).FullName) != null);

    private static void SetPropertyValue(PropertyInfo propertyInfo, object allValue, object value)
    {
        propertyInfo.SetValue(allValue, value);
    }

    private static string HtmlEncode(string value) => HttpUtility.HtmlEncode(value);

}

   public class EncodeInputsActionFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(
        ActionExecutingContext context,
        ActionExecutionDelegate next)
    {
        ProcessHtmlEncoding(context);
        var resultContext = await next();
        // do something after the action executes; resultContext.Result will be set
    }

    private static void ProcessHtmlEncoding(ActionExecutingContext context)
    {
        context.ActionArguments.ToList().ForEach(arg => { arg.Value.ParseProperties(); });
    }
}

关于asp.net-mvc - 如何为.net core mvc应用程序集中防止脚本注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54411295/

相关文章:

asp.net-mvc - Azure AD Identity 似乎没有提供用于自动链接 Umbraco 用户的电子邮件

ruby - 仅在输入值时验证 Rails3 模型

asp.net-core - ASP.Net Core Razor 页面中的 Bootstrap Multiselect 在单击时不显示下拉列表

c# - 需要能够将丹麦小数传递给 MVC Controller

c# - 将枚举传递给强类型部分 View

asp.net - MVC 4 应用程序服务层中的单元测试

javascript - 引导模式+ajax+jquery+验证+.net core 2.0

java - GraphQL-SPQR 中返回错误的正确方法

c# - 如何使用类验证属性在属性上动态设置验证消息

c# - 为什么 Application Insights 依赖关系时间线存在间隙?