一。阻止跨站脚本攻击(XSS)
1. 对所有内容进行Html编码,对于Asp.Net MVC 而言,只需要在视图中使用Html.Encode或者Html.AttributeEncode方法就可实现对特定值的编码替换。
Razor视图默认输出内容采用Html编码,所以使用@Model.FirstName.显示的模型属性将被进行Html编码,而程序员不需要进行任何工作
2. Url.Encode或者Html.AttributeEncode方法: 对预期的URL进行编码
3. JavaScript编码:使用Ajax.JavaScriptStringEncode辅助函数对在JavaScript中使用的字符串进行编码
二。阻止跨站请求伪造(Cross-Site Request Forgery, CSRF)
1) 令牌验证
在每个表单请求中插入一个唯一的隐藏输入元素,代码如下:
@using (Html.BeginForm()) { @Html.AntiForgeryToken() }
用 @Html.AntiForgeryToken辅助方法会输出一个加密值作为隐藏的输入元素:
<input type="hidden" value="012386uuudefuye0123456" />
该值将于作为会话Cookie储存在用户浏览器中的另一个值进行匹配。在提交表单时,ActionFilter就会验证这两个值是否匹配
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "ID,Name")] Product product) { if (ModelState.IsValid) { db.Products.Add(product); db.SaveChanges(); return RedirectToAction("Index"); } return View(product); }
2) 幂等的Get请求
如果一个操作时幂等的,则执行多次而不会改变执行结果。一般情况下,仅仅通过Post请求来修改数据库或者网站中的内容,这里的修改包含Registration,Logout, Login
3) HttpReferrer验证
使用ActionFilter来查看提交表单值的客户端是否确实在目标站点
public class IsPostFromThisSiteAttribute: AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { if (filterContext.HttpContext != null) { if (filterContext.HttpContext.Request.UrlReferrer == null) { throw new System.Web.HttpException("Invalid submission"); } // 判断返回的url是否是自己所在站点 if (filterContext.HttpContext.Request.UrlReferrer.Host != "localhost") { throw new System.Web.HttpException("this form wasn‘t submitted from this site!"); } } } }
三。阻止Cookie盗窃
Cookie主要分为2种,
1. 会话Cookie: 储存在浏览器的内存中,在浏览器的每次请求中通过Http头进行传递
2.持久Cookie:持久性Cookie储存在计算机内存上的实际文本文件中,与会话Cookie采用同样的方式传递
二者的区别在与:会话Cookie通常在会话结束后忘记会话Cookie,而持久性Cookie则不同,在下一次站点时依然会记住它
若盗取某人在一个网站上的身份验证Cookie,就可以在站点上冒充某人进行此人权限内的所有操作
1. 用HttpOnly阻止Cookie盗窃
在web.config中对所有Cookie进行设置
<httpCookies domain="" httpOnlyCookies="true" requireSSL="false"/>
或者在程式中单独设置
Response.Cookies["MyCookies"].HttpOnly = true
四。使用Bind特性防止重复提交(Over-posting)攻击
防御重复提交攻击的最简单办法就是使用[Bind]属性显示的控制需要由模型绑定器绑定的属性。Bind特性既可以放到模型类上,或者放到控制器操作参数中。可以使用[Bind(Include="Name, Comment")]指定绑定哪些字段,也可以使用[Bind(Exclude="Name, Comment")]排除绑定的字段。
另一种方法可以使用UpdateModel或者TryUpdateModel方法中的一个重载版本来接收一个绑定列表,例如代码:
UpdateModel(review, "Review", new string{"Name", "Content"})