下面转的两篇文章分别说明了以下两个概念和一些解决方法:
-
CSRF - Cross-Site Request Forgery - 跨站请求伪造
-
CORS - Cross Origin Resourse-Sharing - 跨域资源共享
一、 CSRF
转自:http://www.h3c.com.cn/About_H3C/Company_Publication/IP_Lh/2012/04/Home/Catalog/201208/751467_30008_0.htm
从下面文章中可以知道为什么要设置csrf_token,以及为什么一些网站把csrf_token放入header或url。
1.CSRF漏洞简介
CSRF(Cross-Site Request Forgery,跨站点伪造请求)是一种网络攻击方式,该攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在未授权的情况下执行在权限保护之下的操作,具有很大的危害性。具体来讲,可以这样理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
CSRF攻击方式并不为大家所熟知,实际上很多网站都存在CSRF的安全漏洞。早在2000年,CSRF这种攻击方式已经由国外的安全人员提出,但在国内,直到2006年才开始被关注。2008年,国内外多个大型社区和交互网站先后爆出CSRF漏洞,如:百度HI、NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站)和YouTube等。但直到现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”,其威胁程度由此“美誉”便可见一斑。
2.CSRF攻击原理及实例
2.1 CSRF攻击原理
CSRF攻击原理比较简单,如图1所示。其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。
图1 CSRF攻击原理
-
1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
-
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
-
3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
-
4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
-
5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
2.2 CSRF攻击分类
CSRF漏洞一般分为站外和站内两种类型。
CSRF站外类型的漏洞本质上就是传统意义上的外部提交数据问题。通常程序员会考虑给一些留言或者评论的表单加上水印以防止SPAM问题(这里,SPAM可以简单的理解为垃圾留言、垃圾评论,或者是带有站外链接的恶意回复),但是有时为了提高用户的体验性,可能没有对一些操作做任何限制,所以攻击者可以事先预测并设置请求的参数,在站外的Web页面里编写脚本伪造文件请求,或者和自动提交的表单一起使用来实现GET、POST请求,当用户在会话状态下点击链接访问站外Web页面,客户端就被强迫发起请求。
CSRF站内类型的漏洞在一定程度上是由于程序员滥用REQUEST类变量造成的。在一些敏感的操作中(如修改密码、添加用户等),本来要求用户从表单提交发起POST请求传递参数给程序,但是由于使用了_REQUEST等变量,程序除支持接收POST请求传递的参数外也支持接收GET请求传递的参数,这样就会为攻击者使用CSRF攻击创造条件。一般攻击者只要把预测的请求参数放在站内一个贴子或者留言的图片链接里,受害者浏览了这样的页面就会被强迫发起这些请求。
2.3 CSRF 漏洞检测
检测CSRF漏洞是一项比较繁琐的工作,最简单的方法就是抓取一个正常请求的数据包,去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。
随着对CSRF漏洞研究的不断深入,不断涌现出一些专门针对CSRF漏洞进行检测的工具,如CSRFTester,CSRF Request Builder等。
以CSRFTester工具为例,CSRF漏洞检测工具的测试原理如下:使用CSRFTester进行测试时,首先需要抓取我们在浏览器中访问过的所有链接以及所有的表单等信息,然后通过在CSRFTester中修改相应的表单等信息,重新提交,这相当于一次伪造客户端请求。如果修改后的测试请求成功被网站服务器接受,则说明存在CSRF漏洞,当然此款工具也可以被用来进行CSRF攻击。
CSRF攻击实例
下面以Axous 1.1.1 CSRF Add Admin Vulnerability(漏洞CVE编号:CVE-2012-2629)为例,介绍CSRF攻击具体实施过程。
Axous是一款网上商店应用软件。Axous 1.1.1以及更低版本在实现上存在一个CSRF漏洞,远程攻击者可以通过构造特制的网页,诱使该软件管理员访问,成功利用此漏洞的攻击者可以添加系统管理员。利用此漏洞主要包含以下三个过程:
-
攻击者构造恶意网页。在实施攻击前,攻击者需要构造一个与正常添加管理员用户基本一样的网页,在该恶意网页中对必要的参数项进行赋值,并将该网页的action指向正常添加管理员用户时访问的URL,核心代码如图2所示;
-
攻击者利用社会工程学诱使Axous系统管理员访问其构造的恶意网页;
-
执行恶意代码。当系统管理员访问恶意网页时,恶意代码在管理员不知情的情况下以系统管理员的合法权限被执行,攻击者伪造的管理员账户添加成功。
图2 CSRF攻击添加管理员核心代码
2.4 CSRF漏洞防御
CSRF漏洞防御主要可以从三个层面进行,即服务端的防御、用户端的防御和安全设备的防御。
2.4.1 服务端的防御
目前业界服务器端防御CSRF攻击主要有三种策略:验证HTTP Referer字段,在请求地址中添加token并验证,在HTTP头中自定义属性并验证。下面分别对这三种策略进行简要介绍。
(1) 验证HTTP Referer字段
根据HTTP协议,在HTTP头中有一个字段叫Referer,它记录了该HTTP请求的来源地址。在通常情况下,访问一个安全受限页面的请求必须来自于同一个网站。比如某银行的转账是通过用户访问http://bank.test/test?page=10&userID=101&money=10000页面完成,用户必须先登录bank. test,然后通过点击页面上的按钮来触发转账事件。当用户提交请求时,该转账请求的Referer值就会是转账按钮所在页面的URL(本例中,通常是以bank. test域名开头的地址)。而如果攻击者要对银行网站实施CSRF攻击,他只能在自己的网站构造请求,当用户通过攻击者的网站发送请求到银行时,该请求的Referer是指向攻击者的网站。因此,要防御CSRF攻击,银行网站只需要对于每一个转账请求验证其Referer值,如果是以bank. test开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果Referer是其他网站的话,就有可能是CSRF攻击,则拒绝该请求。
(2) 在请求地址中添加token并验证
CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的Cookie来通过安全验证。由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。鉴于此,系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。
(3) 在HTTP头中自定义属性并验证
自定义属性的方法也是使用token并进行验证,和前一种方法不同的是,这里并不是把token以参数的形式置于HTTP请求之中,而是把它放到HTTP头中自定义的属性里。通过XMLHttpRequest这个类,可以一次性给所有该类请求加上csrftoken这个HTTP头属性,并把token值放入其中。这样解决了前一种方法在请求中加入token的不便,同时,通过这个类请求的地址不会被记录到浏览器的地址栏,也不用担心token会通过Referer泄露到其他网站。
2.4.2 用户端的防御
对于普通用户来说,都学习并具备网络安全知识以防御网络攻击是不现实的。但若用户养成良好的上网习惯,则能够很大程度上减少CSRF攻击的危害。例如,用户上网时,不要轻易点击网络论坛、聊天室、即时通讯工具或电子邮件中出现的链接或者图片;及时退出长时间不使用的已登录账户,尤其是系统管理员,应尽量在登出系统的情况下点击未知链接和图片。除此之外,用户还需要在连接互联网的计算机上安装合适的安全防护软件,并及时更新软件厂商发布的特征库,以保持安全软件对最新攻击的实时跟踪。
2.4.3 安全设备的防御
由于从漏洞的发现到补丁的发布需要一定的时间,而且相当比例的厂商对漏洞反应不积极,再加之部分系统管理员对系统补丁的不够重视,这些都给了攻击者可乘之机。鉴于上述各种情况,用户可以借助第三方的专业安全设备加强对CSRF漏洞的防御。
CSRF攻击的本质是攻击者伪造了合法的身份,对系统进行访问。如果能够识别出访问者的伪造身份,也就能识别CSRF攻击。研究发现,有些厂商的安全产品能基于硬件层面对HTTP头部的Referer字段内容进行检查来快速准确的识别CSRF攻击。图3展示了这种防御方式的简图。目前H3C公司的IPS产品采用了特殊技术,支持对部分常用系统的CSRF漏洞攻击进行检测和阻断。
图3 安全设备传统防御方式
二、跨域资源共享(CORS)安全性浅析
(转自http://netsecurity.51cto.com/art/201311/419179.htm)
1.背景
提起浏览器的同源策略,大家都很熟悉。不同域的客户端脚本不能读写对方的资源。但是实践中有一些场景需要跨域的读写,所以出现了一些hack的方式来跨域。比如在同域内做一个代理,JSON-P等。但这些方式都存在缺陷,无法完美的实现跨域读写。所以在XMLHttpRequest v2标准下,提出了CORS(Cross Origin Resourse-Sharing)的模型,试图提供安全方便的跨域读写资源。目前主流浏览器均支持CORS。
2.技术原理
CORS定义了两种跨域请求,简单跨域请求和非简单跨域请求。当一个跨域请求发送简单跨域请求包括:请求方法为HEAD,GET,POST;请求头只有4个字段,Accept,Accept-Language,Content-Language,Last-Event-ID;如果设置了Content-Type,则其值只能是application/x-www-form-urlencoded,multipart/form-data,text/plain。说起来比较别扭,简单的意思就是设置了一个白名单,符合这个条件的才是简单请求。其他不符合的都是非简单请求。
之所以有这个分类是因为浏览器对简单请求和非简单请求的处理机制是不一样的。当我们需要发送一个跨域请求的时候,浏览器会首先检查这个请求,如果它符合上面所述的简单跨域请求,浏览器就会立刻发送这个请求。如果浏览器检查之后发现这是一个非简单请求,比如请求头含有X-Forwarded-For字段。这时候浏览器不会马上发送这个请求,而是有一个preflight,跟服务器验证的过程。浏览器先发送一个options方法的预检请求。下图是一个示例。如果预检通过,则发送这个请求,否则就不拒绝发送这个跨域请求。
下面详细分析一下实现安全跨域请求的控制方式。先看一下非简单请求的预检过程。浏览器先发送一个options方法的请求。带有如下字段:
Origin: 普通的HTTP请求也会带有,在CORS中专门作为Origin信息供后端比对,表明来源域。
Access-Control-Request-Method: 接下来请求的方法,例如PUT, DELETE等等
Access-Control-Request-Headers: 自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中
然后如果服务器配置了cors,会返回对应对的字段,具体字段含义在返回结果是一并解释。
Access-Control-Allow-Origin:
Access-Control-Allow-Methods:
Access-Control-Allow-Headers:
然后浏览器再根据服务器的返回值判断是否发送非简单请求。简单请求前面讲过是直接发送,只是多加一个origin字段表明跨域请求的来源。然后服务器处理完请求之后,会再返回结果中加上如下控制字段:
Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符"*"。这里要注意Origin规则只对域名有效,并不会对子目录有效。即http://foo.example/subdir/ 是无效的。但是不同子域名需要分开设置,这里的规则可以参照同源策略
Access-Control-Allow-Credentials: 是否允许请求带有验证信息,这部分将会在下面详细解释
Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息(貌似webkit没有实现这个)
Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数
Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开
Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感
然后浏览器通过返回结果的这些控制字段来决定是将结果开放给客户端脚本读取还是屏蔽掉。如果服务器没有配置cors,返回结果没有控制字段,浏览器会屏蔽脚本对返回信息的读取。
3.安全隐患
大家注意这个流程。服务器接收到跨域请求的时候,并没有先验证,而是先处理了请求。所以从某种程度上来说。在支持cors的浏览器上实现跨域的写资源,打破了传统同源策略下不能跨域读写资源。
再一个就是如果程序猿偷懒将Access-Control-Allow-Origin设置为允许来自所有域的跨域请求。那么cors的安全机制几乎就无效了。不过先别高兴的太早。其实这里在设计的时候有一个很好的限制。xmlhttprequest发送的请求需要使用“withCredentials”来带上cookie,如果一个目标域设置成了允许任意域的跨域请求,这个请求又带着cookie的话,这个请求是不合法的。(就是如果需要实现带cookie的跨域请求,需要明确的配置允许来源的域,使用任意域的配置是不合法的)浏览器会屏蔽掉返回的结果。javascript就没法获取返回的数据了。这是cors模型最后一道防线。假如没有这个限制的话,那么javascript就可以获取返回数据中的csrf token,以及各种敏感数据。这个限制极大的降低了cors的风险。
4.攻击模型
从思路上讲,有两种类型的攻击方式。一种是在攻击者自己控制的网页上嵌入跨域请求,用户访问链接,执行了跨域请求,从而攻击目标,比如访问了内网敏感资源。还有一种是正常的网页被嵌入了到攻击者控制页面的跨域请求,从而劫持用户的会话。
5.攻击场景
先看第一种思路的攻击场景:
-
1,复杂csrf。传统的csrf都是利用html标签和表单来发送请求。没有办法实现一些复杂步骤的csrf,比如模拟购物,先加购物车,结算,填写信息,等等。比如上传文件。具体可以参考利用csrf上传文件
-
2,访问内网敏感资源。这个在一定的条件下是可以实现的。比如内网的服务器配置了
Access-Control-Allow-Origin: * 允许任何来自任意域的跨域请求
用户访问恶意网页的时候,执行了到内网服务器192.168.1.123/password.txt的请求,脚本在接收到服务器返回之后,将内容发送到攻击者的服务器上。
第二种思路的场景:
1,交互式xss。参考揭密HTML5带来的攻击手法中讲到的shell of the future工具。通过cors,绕过一些反会话劫持的方法,如HTTP-Only限制的cookie,绑定IP地址的会话ID等,劫持用户会话。
2,程序猿在写ajax请求的时候,对目标域限制不严。有点类似于url跳转。facebook出现过这样一个案例。javascript通过url里的参数进行ajax请求。通过控制这个参数实现注入攻击。