爱惜ASP.NET 应用免受 CSRF 攻击

CSRF是什么?

  CSRF(Cross-site request
forgery),普通话名称:跨站请求伪造,也被称作:one click attack/session
riding,缩写为:CSRF/XSRF。CSRF(Cross Site Request Forgery,
跨站域请求伪造)是一种网络的攻击形式,它在 2007 年曾被列为互联网 20
大安全隐患之一。其余安全隐患,比如 SQL
脚本注入,跨站域脚本攻击等在目前已经日趋为人们熟谙,很多网站也都针对他们进行了防守。但是,对于大多数人来说,CSRF
却如故是一个素不相识的定义。固然是享誉的 Gmail, 在 2007 年终也设有着
CSRF 漏洞,从而被黑客攻击而使 Gmail 的用户造成巨大的损失。

CSRF可以做如何?

  你那可以那样精晓CSRF攻击:攻击者盗用了您的地点,以你的名义发送恶意请求。CSRF可以做的工作包涵:以你名义发送邮件,发音信,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的难题概括:个人隐衷败露以及资产安全。

CSRF攻击原理

图片 1

从上图可以寓目,要形成三次CSRF攻击,受害者必须逐项达成五个步骤:

  1.登录受信任网站A,并在地点生成Cookie。

  2.在不登出A的状态下,访问危险网站B。

  看到那里,你也许会说:“假设自身不满足上述八个标准化中的一个,我就不会见临CSRF的抨击”。是的,确实如此,但您不能够保险以下意况不会生出:

  1.您不可能确保你登录了一个网站后,不再打开一个tab页面并走访此外的网站。

  2.您不可能有限支撑你关闭浏览器了后,你本地的Cookie立即过期,你上次的对话已经收尾。(事实上,关闭浏览器不可以截至一个会话,但一大半人都会错误的以为关闭浏览器就相当于退出登录/甘休会话了……)

  3.上图中所谓的攻击网站,可能是一个存在任何漏洞的可靠任的平常被人拜访的网站。

地点几乎地讲了一晃CSRF攻击的思考,下边我将用个例证详细说说具体的CSRF攻击,那里自己以一个银行转化的操作作为例子(仅仅是例证,真实的银行网站没那样傻:>)

  银行网站A,它以GET请求来成功银行转化的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000

  危险网站B,它其中有一段HTML的代码如下:

  <img
src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000&gt;

  首先,你登录了银行网站A,然后访问危险网站B,噢,那时你会发觉你的银行账户少了1000块……

  为何会这么吧?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在拜访危险网站B的事先,你曾经报到了银行网站A,而B中的<img>以GET的措施呼吁第三方资源(那里的第三方就是指银行网站了,原本那是一个法定的请求,但那里被不法分子采用了),所以您的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfer.php?toBankId=11&money=1000”,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作……

当下防卫 CSRF 的二种政策

在业界近来防卫 CSRF 攻击首要有二种政策:验证 HTTP Referer
字段;在央浼地址中添加 token 并证实;在 HTTP
头中自定义属性并证实。上面就各自对那二种政策进行详细介绍。

验证 HTTP Referer 字段

基于 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP
请求的发源地址。在普通景况下,访问一个平安受限页面的哀告来自于同一个网站,比如须求拜访
http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆
bank.example,然后经过点击页面上的按钮来触发转账事件。这时,该转帐请求的
Referer 值就会是转载按钮所在的页面的 URL,日常是以 bank.example
域名早先的地点。而只要黑客要对银行网站实施 CSRF
攻击,他不得不在他协调的网站协会请求,当用户通过黑客的网站发送请求到银行时,该请求的
Referer 是指向黑客自己的网站。因而,要守护 CSRF
攻击,银行网站只必要对此每一个倒车请求验证其 Referer 值,如若是以
bank.example
初叶的域名,则证实该请求是来自银行网站自己的哀告,是官方的。假若 Referer
是其余网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。

那种办法的强烈的便宜就是简单易行,网站的平凡开发人士不要求操心 CSRF
的纰漏,只必要在最终给所有安全敏感的伸手统一增添一个拦截器来检查 Referer
的值就足以。更加是对于近日现有的系统,不必要变更近来系统的其余已有代码和逻辑,没有危机,分外轻便。

可是,那种措施毫无万无一失。Referer 的值是由浏览器提供的,即便 HTTP
协议上有明确的渴求,可是每个浏览器对于 Referer
的有血有肉落到实处可能有异样,并无法有限辅助浏览器自身没有安全漏洞。使用验证 Referer
值的主意,就是把安全性都珍贵于第三方(即浏览器)来维持,从理论上来讲,那样并不安全。事实上,对于某些浏览器,比如
IE6 或 FF2,近期曾经有局部主意可以篡改 Referer 值。假设 bank.example
网站匡助 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以
bank.example 域名开首的地点,那样就足以由此认证,从而举行 CSRF 攻击。

纵使是接纳新型的浏览器,黑客不可以篡改 Referer
值,那种格局依旧有难题。因为 Referer
值会记录下用户的访问来源,有些用户觉得这么会侵略到他俩自己的隐衷权,更加是有些协会担心
Referer
值会把集体内网中的某些新闻外泄到外网中。由此,用户自己能够安装浏览器使其在发送请求时不再提供
Referer。当她们健康访问银行网站时,网站会因为请求没有 Referer 值而以为是
CSRF 攻击,拒绝法定用户的走访。

在呼吁地址中添加 token 并说明

CSRF
攻击之所以能够得逞,是因为黑客可以完全伪造用户的央浼,该请求中装有的用户验证音信都是存在于
cookie 中,因而黑客可以在不知晓那些评释音讯的图景下直接动用用户自己的
cookie 来通过安全阐明。要抵御
CSRF,关键在于在呼吁中放入黑客所无法伪造的音信,并且该音信不存在于
cookie 之中。可以在 HTTP 请求中以参数的款型进入一个肆意爆发的
token,并在服务器端建立一个拦截器来证实这么些 token,若是请求中绝非 token
或者 token 内容不正确,则以为可能是 CSRF 攻击而推辞该请求。

那种方法要比检查 Referer 要安全一些,token 可以在用户登陆后爆发并放于
session 之中,然后在每便请求时把 token 从 session 中拿出,与请求中的
token 进行比对,但那种格局的困难在于怎么样把 token
以参数的样式进入请求。对于 GET 请求,token 将附在请求地址然后,那样 URL
就成为 http://url?csrftoken=tokenvalue。 而对此 POST 请求来说,要在 form
的最终加上 <input type=”hidden” name=”csrftoken”
value=”tokenvalue”/>,那样就把 token
以参数的方式进入请求了。不过,在一个网站中,可以接受请求的地点分外多,要对此每一个呼吁都丰盛token
是很麻烦的,并且很简单漏掉,寻常使用的方式就是在历次页面加载时,使用
javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后进入
token。那样可以解决半数以上的呼吁,可是对于在页面加载之后动态变化的 html
代码,那种方法就从不出力,还必要程序员在编码时手动添加 token。

该形式还有一个毛病是难以管教 token
本身的吴忠。更加是在一些论坛之类匡助用户自己发布内容的网站,黑客可以在上头发表温馨个人网站的地点。由于系统也会在这些地方前面加上
token,黑客可以在大团结的网站上获得那么些 token,并及时就能够发动 CSRF
攻击。为了避免那或多或少,系统可以在抬高 token
的时候伸张一个判断,如若那个链接是链到自己本站的,就在后头添加
token,假使是通向外网则不加。不过,固然那一个 csrftoken
不以参数的款型附加在伸手之中,黑客的网站也如出一辙能够经过 Referer
来收获那一个 token 值以发动 CSRF 攻击。那也是一对用户喜爱手动关闭浏览器
Referer 成效的来头。

在 HTTP 头中自定义属性并证实

那种艺术也是采用 token 并拓展认证,和上一种方法不一致的是,这里并不是把
token 以参数的方式置于 HTTP 请求之中,而是把它放到 HTTP
头中自定义的属性里。通过 XMLHttpRequest
那一个类,可以四次性给所有此类请求加上 csrftoken 这些 HTTP 头属性,并把
token 值放入其中。这样解决了上种方法在伏乞中进入 token
的困顿,同时,通过 XMLHttpRequest
请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer
败露到别的网站中去。

但是那种艺术的局限性卓殊大。XMLHttpRequest 请求寻常用于 Ajax
方法中对此页面局地的异步刷新,并非所有的请求都符合用那几个类来倡导,而且经过此类请求得到的页面无法被浏览器所记录下,从而进行发展,后退,刷新,收藏等操作,给用户带来不便。其它,对于从未进展
CSRF 防护的残存系统的话,要选拔这种办法来开展预防,要把装有请求都改为
XMLHttpRequest 请求,那样大约是要重写整个网站,那代价无疑是不可以经受的。

 

CSRF的防御

  我计算了一晃看到的资料,CSRF的防守可以从服务端和客户端两上边开始,防御机能是从服务端发轫效果相比较好,现在一般的CSRF防御也都在服务端举办。那里给大家介绍一个开源项目,具体的内容可以参照小编的博客《Protecting
ASP.NET Applications Against CSRF
Attacks
》。

1、通过Nuget 安装ARMOR Web Framework

PM> Install-Package Daishi.Armor.WebFramework

2、添加几个布局项

<add key=“IsArmed” value=“``true``” />

<add key=“ArmorEncryptionKey” value=“{Encryption Key}” />

<add key=“ArmorHashKey” value=“{Hashing Key}” />

<add key=“ArmorTimeout” value=“1200000” />

IsArmed: 打开或者关闭ARMOR 功能开关

ArmorEncryptionKey:ARMOR 的加密密钥,用于加密和解密Token

ArmorHashKey:用于转移和验证ARMOR 哈希值,包蕴在令牌内。ARMOR
用那么些完成是不是token被篡改过。

ArmorTimeout:以微秒为单位的ARMOR 的token有效期

能够用上面的那段代码去变通

byte``[] encryptionKey = ``new byte``[32];

byte``[] hashingKey = ``new byte``[32];

using (``var provider = ``new RNGCryptoServiceProvider()) {

``provider.GetBytes(encryptionKey);

``provider.GetBytes(hashingKey);

3、应用程序中加入 一个ARMOR 钩子

ARMOR主要有Authorization Filter、 Fortification Filter 和 ARMOR UI
Components,匡助ASP.NET MVC和ASP.NET Web
API具体的使用方法可以参见Protecting ASP.NET Applications Against CSRF
Attacks

 

参照小说:

[1].Preventing CSRF

[2].Security Corner: Cross-Site Request
Forgeries

[3].《深切剖析跨站请求伪造漏洞:原理分析》

[4].《Web安全测试之跨站请求伪造(CSRF)》

[5].《深切剖析跨站请求伪造漏洞:实例讲解》

相关文章