利用ModelBinder防止XSS一次尝试

Web开发中不可避免的要防止XSS,防止XSS当然要进行Encode(这里是广义,表示Encode和过滤掉特殊标签,下面不再解释),分为输出和输入。各有用处,比如,您提交保存并显示一块内容,那么多数情况下,您需要对输出进行Encode;对于搜索功能,您需要对查询条件进行(输入)Encode,例如:当在查询参数里面输入<scrpit>之类的东西时候您可能需要去掉它,得到所谓安全的参数,也就是查询id=111和查询id=111><script>出来的结果是一样的。我今天暂时尝试了对输入进行Encode。


MVC里面有一个机制非常有用,您可以利用它完成很多事情---ModelBinder。一个场景如下:注册账户(为了简单,仅仅有用户名和密码两个字段)。

 
  
public class User
{
public string UserName { get ; set ; }

public string PassWord { get ; set ; }
}

我们需要对post到action里面的内容进行Encode。利用ModerBinder,我们可以绑定参数值,当然我们重写一个ModerBinder,就可以进行Encode了。

ContractedBlock.gif ExpandedBlockStart.gif 原始的ModelBinder
 
   
public class ForbiddenXSSModelBinder : IModelBinder
{
#region IModelBinder 成员

public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
var valueProviderResult
= bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == null )
return null ;

return Encoder.HtmlEncode(valueProviderResult.AttemptedValue);
}

#endregion
}

这里忽略了异常处理,和一些入口检查。简单的代码,完成了功能。

很快问题出来了:

1、我们对所以的参数都进行Encode,这是不对的。因为有些我们是不需要过滤(有些是不能,比如PassWord字段),比如创建时间字段

2、对所有字段进行Encode无疑是浪费性能的事情

那么,我们能不能根据定制进行Encode呢?我想到了Attribute,思路如下:

1、我们对User类需要Encode的属性进行标识

2、在ModerBinder的时候对类型的属性进行判断,进行确定是否要Encode

思路有了,代码实现很简单。先定义一个Attribute:

ContractedBlock.gif ExpandedBlockStart.gif AllowEncodeAttribute
 
   
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true , Inherited = true )]
public class AllowEncodeAttribute : Attribute
{
/// <summary>
/// 判断是否需要Encode
/// </summary>
public bool AllowEncode { get ; set ; }

public AllowEncodeAttribute( bool allow)
{
AllowEncode
= allow;
}
}

将User类更改:

 
  
[AllowEncode( true )]
public string UserName { get ; set ; }

在ModerBinder中这样操作:

ContractedBlock.gif ExpandedBlockStart.gif 改进后的ModerlBinder
 
   
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
DealInputValue(controllerContext.HttpContext.Request.QueryString);
DealInputValue(controllerContext.HttpContext.Request.Form);

var valueProviderResult
= bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == null )
return null ;

Type type
= bindingContext.ModelMetadata.ContainerType;
var propertyInfo
= type.GetProperty(bindingContext.ModelName);
var attribute
= Attribute.GetCustomAttribute(propertyInfo,
typeof (AllowEncodeAttribute)) as AllowEncodeAttribute;

if (attribute != null && attribute.AllowEncode == true )
{
return Encoder.HtmlEncode(valueProviderResult.AttemptedValue);
}

return valueProviderResult.AttemptedValue;
}

至此,尝试便结束了,初步达到了要求。

依然有一些问题存在:

1、对于参数并没有经过ModerBinder的我们怎么办?需要一个一个的Encode吗?

2、对于输出需要进行Encode的我们要如何?用HtmlHelper的Encode方法操作吗?

这是我下面要进行尝试的东西。

转载于:https://www.cnblogs.com/WillMeng/archive/2011/04/18/ModelBinder-XSS.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值