CSRF防御之ASP.NET MVC
MVC中的Html.AntiForgeryToken()是用来防止跨站请求伪造(CSRF:Cross-site request forgery)攻击的一个措施。
举个简单例子,譬如整个系统的公告在网站首页显示,而这个公告是从后台提交的,我用最简单的写法:
网站后台(Home/Index页面)设置首页公告内容,提交到HomeController的Text Action
@using (Html.BeginForm("Text","Home",FormMethod.Post))
{
@:网站公告:<input type="text" name="Notice" id="Notice" />
<input type="submit" value="Submit" />
}
HomeController的Text Action
[HttpPost]
public ActionResult Text()
{
ViewBag.Notice = Request.Form["Notice"].ToString();
return View();
}
填写完公告,提交,显示
此时提供给了跨站攻击的漏洞,CSRF一般依赖几个条件
(1)攻击者了解受害者所在的站点
(2)攻击者的目标站点具有持久化授权cookie或者受害者具有当前会话cookie
(3)目标站点没有对用户在网站行为的第二授权此时
具体参见http://baike.baidu.com/view/1609487.htm
现假设我知道我要攻击的网站的地址,譬如是http://localhost:6060/Home/Text,且也满足2,3的情况。
于是我新建一个AntiForgeryText.html文件,内容如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title></title>
</head>
<body>
<form name="badform" method="post" action="http://localhost:6060/Home/Text">
<input type="hidden" name="Notice" id="Notice" value="你的网站被我黑了。。" />
<input type="submit" value="黑掉这个网站" />
</form>
</body>
</html>
在这个html中加了一个隐藏的字段,Name和Id和网站要接收的参数名一样。
我点击了“黑掉这个网站”,呈现如下
这个就是利用了漏洞把首页的公告给改了,这就是一个简单的跨站攻击的例子。
MVC中通过在页面上使用 Html.AntiForgeryToken()配合在对应的Action上增加[ValidateAntiForgeryToken]特性来防止跨站攻击。
把上面的代码改成
@using (Html.BeginForm("Text","Home",FormMethod.Post))
{
@Html.AntiForgeryToken()
@:网站公告:<input type="text" name="Notice" id="Notice" />
<input type="submit" value="Submit" />
}
对应的Action
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Text()
{
ViewBag.Notice = Request.Form["Notice"].ToString();
return View();
}
这样子我在AntiForgeryText.html中点"黑掉这个网站",就会出现
这样就防止了跨站攻击。
页面上的Html.AntiForgeryToken()会给访问者一个默认名为__RequestVerificationToken的cookie
为了验证一个来自form post,还需要在目标action上增加[ValidateAntiForgeryToken]特性,它是一个验证过滤器,
它主要检查
(1)请求的是否包含一个约定的AntiForgery名的cookie
(2)请求是否有一个Request.Form["约定的AntiForgery名"],约定的AntiForgery名的cookie和Request.Form值是否匹配
其中主要涉及到System.Web.WebPages.dll中的静态类AntiForgery
Html.AntiForgeryToken()调用了AntiForgery静态类的GetHtml方法,它产生一个随机值然后分别存储到客户端cookie和页面的hidden field中,
(1)Request.Cookies[antiForgeryTokenName](默认也是Request.Cookies["__RequestVerificationToken"])
(2)页面上的hiddenfield
<input name="__RequestVerificationToken" type="hidden" value="9rUlMYvsH6eMcFN9tn/wRwAG07eROraVaeTn9hHMXKkMmDbR8jLw5DKdVnZBJ9siQHeGyl1w4rSB141LnxMp2ahV0qP1lElPeukqfcUFYoxrm/EfpSJjZavykmzn15VeGFMKkmgFj5a1UFhZFaW2aZgeN38x9lt0OFSoca7eMVU=" />
其中cookie的key的名字和页面hidden field的名字是一样的,默认都是"__RequestVerificationToken",如果有提供ApplicationPath的话,那就是由"__RequestVerificationToken"和经过处理后的ApplicationPath组成。
Controller端则通过在Action上增加[ValidateAntiForgeryToken]特性来验证,
ValidateAntiForgeryTokenAttribute继承了FilterAttribute和IAuthorizationFilter,通过传递匿名委托方法,
委托调用AntiForgery类的Validate方法来实现验证。
Validate方法中主要验证Request.Cookies[antiForgeryTokenName]和<input name=antiForgeryTokenName ...>两个的值是否相同,
如果页面没有<input name=antiForgeryTokenName ...>,或者两个值不相等,就会抛出异常。
使用该方法的缺点是:
1. 这种方法是依赖于 cookie的,如果客户端禁止了 cookie ,那么这种防范就会失效。
2. 该方法是对 post请求有效,对 Get 请求无效
3. 对于 AJAX请求,MVC 框架不会自动传递 cookie和隐藏域。需要自己实现传输和读取。
最新文章
- linux安装php
- C/C++入门基础----指针(1)
- wav转aac
- c# 获取系统版本,获取net framework 版本(Environment 类)
- 怎样解决MySQL数据库主从复制延迟的问题---流行网站的解决办法(转载)
- Behavior Designer中Wait节点的坑
- 如何使用SQL Server链接服务器访问DB2 Server
- SQL Server 2005中约束
- 174. Dungeon Game
- 网页设定固定背景图片(抄袭自百度FM)
- 【转】android开发 dts、各种接口porting----不错
- js识别终端类型
- Web前端总结(小伙伴的)
- [vijos 1642]班长的任务 [树形dp]
- Uva10129 - Play on Words 欧拉通路 DFS
- JavaScript定时器详解
- 《CSS世界》读书笔记(十一)
- swift 实践- 01 -- UItableView的简单使用
- 过渡与动画 - 逐帧动画&;steps调速函数
- RMQ算法区间最值
热门文章
- 在cocos2dx和unity3d之间选择
- Oracle日期语言修改
- png图片尺寸大小调整
- MyBatis学习总结(八)&mdash;&mdash;Mybatis3.x与Spring4.x整合
- Atitit (Sketch Filter)素描滤镜的实现 &#160;图像处理 &#160;attilax总结
- Atititcmd cli环境变量的调用设置与使用
- atitit.事件驱动的总结attilax
- salesforce 零基础开发入门学习(一)Salesforce功能介绍,IDE配置以及资源下载
- 《BI那点儿事》Microsoft 神经网络算法
- javaweb -- 获取请求IP(附实现源码)