来源:自学PHP网 时间:2015-04-17 14:11 作者: 阅读:次
[导读] CSRF 的基本概念特性跨站请求伪造(CSRF)的是Web 应用程序一种常见的漏洞,其攻击特性是危害性大但非常隐蔽,尤其是在大量Web 2.0 技术的应用的背景下,CSRF 攻击完全可以在用户法毫无...
CSRF 的基本概念特性
跨站请求伪造(CSRF)的是Web 应用程序一种常见的漏洞,其攻击特性是危害性大但非常隐蔽,尤其是在大量Web 2.0 技术的应用的背景下,CSRF 攻击完全可以在用户法毫无察觉的情况下发起攻击。国际上并未对CSRF 攻击做出一个明确的定义,同时,攻击的发起手段方式繁多,下文会做详细介绍。可以解释的是发起的目标都是通过伪造一个用户请求,该请求不是用户想发出去的请求,而对服务器或服务来说这个请求是完全合法的一个请求,但是却完成了一个攻击者所期望的操作,比如添加一个用户到管理者的群组中,或将一个用户的现金转到另外的一个帐户中。通常开发人员对CSRF 攻击的理解是有误区的,分为以下几方面,第一是如何攻击的,第二是危害到底在那里,第三是如何防范就才是一个完整的解决方案。本文就是要对这些基本的问题做一个详细的阐述,并且给出检测的有效方法。 CSRF 的危害实例 大部分网站往往对脚本注入有严格的防范,但是对CSRF 的防范做的就差很多。 实例1:假设某网站高级会员会享有某些特殊权限。而当一个普通用户付款完毕就可以让管理员将自己升级为高级会员。假设管理员将一个普通用户升级为高级会员的请求是: http://www.2cto.com /promoteUser.jsp?username=aaaaa 我们再假设普通用户有在网站某个论坛发表话题的权限,这样一个普通用户可以将这个URL 发表在某些话题之中,然后用我们称为社会工程学的方法引诱网站管理员点击这个链接。当管理员点击这个链接时,这个请求就会从浏览器发送到后台服务器,从而完成身份的升级。当然,在实际攻击过程中,有很多手段使得让管理员不点击也能发送这样的请求,比如将这个URL 设置为某个图片的源。 实例2:以一个二手跳蚤市场为例子,比如某商业交易网站注册用户Hacker01 和Customer01。Hacker01 在上交易频道摆上1 辆9 成新的宝马,投标价格是20000$,另外再摆上另外一量废旧车型标价1000$,然而网站是允许加载图片显示车的状况的。所以宝马车主可以上载一个自己的图片,废旧车主也可以上载一个自己的图片。 宝马图片url:http://myrepository/BMW.jpg car id 100000001 废旧车图片url:http://myrepository/oldCar.jpg car id 100000002 而该拍卖网站是通过投标决定车的最终价格,假设是竞买者参加竞买宝马的时候点击购买按钮浏览器是通过发一个GET 请求到http://e-bussiness-car/bid?value=20000$&carid=100000001 来提交自己的竞标价格。那么Hacker01 则可以把废旧车图片修改为http://e-bussiness-car/bid?value=20000$&carid=100000001(或者其他的value 参数的数值)。 这时候的情况是:Customer01 访问宝马能看见正确的图片,并且没有任何问题。而访问废旧车发现图片是一个无法看到的图片,但当Customer01 浏览旧车图片的时候,浏览器已经向宝马车发送了一个竞标请求。这样在用户的控制之外发出了一个合法的请求,并且被服务器接收。Hack01 可以在Customer01 不知觉的情况下将自己的宝马车卖出。通过此例可以发现CSRF 有着非常严重的危害性。 CSRF 攻击的基本路径及方法 HTTP 协议中定义了,GET/POST/PUT/DELETE 四种基本操作方法如图1 标记-1 所示GET/POST 是所有网站或服务器必须使用的操作方法,而PUT/DELETE 功能强大,但是在以往的应用中并没有被广泛的使用,直到Web 2.0 的出现,Ajax 的引用导致PUT/DELETE 在REST 框架下被发扬光大,大量使用,也使CSRF 的攻击手段中多了一种攻击方式。本文以常用的GET/POST 为实例,这两者是被浏览器用作与服务起进行数据交互的主要手段,并包含Ajax 框架下的攻击介绍。 CSRF 攻击的方法多种多样,而对这些攻击方法的认识将更有助于去检查或在产品设计中加入对CSRF 攻击的防范使整个产品的开发的代价更小。按照攻击的方式来看,分为显式攻击和隐式攻击。显示攻击对用户来说是可以察觉的,例如通过各种方法向受害者发送链接,而隐式攻击则很难察觉,往往是访问了一个有漏洞的页面,或者一个恶意的页面,使用频率更多的则是隐性攻击,因为其更具备可操作性。下边介绍到的攻击方法都可以采取隐式攻击方法。要注意的是,用户网站是否存在脚本注入的漏洞,并不影响CSRF 攻击,通过使用第3 方存在安全隐患的网站一样可以完成CSRF 攻击。 对图1 的基本解释,标记-1 是合法用户对用户网站的访问,执行合法有效的操作;标记-2 是通过邮件系统对用户发动攻击;标记3 是利用Web 的网站,包括用户的操作网站,普通网站,以及黑客网站,标记-4、5、6 指的是有害用户(标记-3)利用的3 种方式来攻击受害用户。 图1. CSRF 攻击示意图 对GET 请求的CSRF 漏洞的攻击方式 GET 请求使用的频率最高,隐式的GET 请求,例如<img> <script><frame><iframe>,在页面中引入上述页面元素,并且设置SRC 属性就能在用户未知的情况下发出一个GET 请求到想去攻击的网站。 以IMG 标签为例,攻击者可以通过在图1 中的标记-5、标记-6、标记-2、标记-4 的途径发起攻击。这种攻击的特征是无明显提示,但是已经发出一个具有完整合法的用户请求。 <img src=http:// www.2cto.com /admin/deletepage?id=74NBCDSEFG/> 对于一个大量采用GET 请求的网站,隐式的通过http 标签发出一个GET 请求将是致命的。 具体的可执行情形描述将在如何检测部分给出。 对POST 请求的CSRF 漏洞的攻击方式 对CSRF 有一种理解是把GET 改为POST 请求就认为是可以防止被攻击实际上是一种错误的理解,通过使用<iframe> 一样可以完成一个隐式的CSRF 攻击,具体脚本写法如下。 清单1. Frame1.html 脚本 <script> function post(url, fields) { var p = document.createElement('form'); p.action = url; p.innerHTML = fields; p.target = '_self'; p.enctype = 'multipart/form-data'; p.method = 'post'; document.body.appendChild(p); p.submit(); } function csrf_hack() { var fields; var csrf="<addMember dnName="CN=manager 9/OU=Managers/OU=Users/O=QDSVT/DC=CN/DC=IBM/DC=COM" accessLevel="Author" isPerson="1" isLocal="0"/>"; fields += "<input type='' name='action' value='"+csrf+"'>"; unescape(fields); post('http://usersite:80/dm/services/DocumentService?do401=true',fields); alert("csrf_end"); } csrf_hack(); alert('end') </script> 清单2. IFrame.html <IFRAME src=./frame1.html width=0 height=0></IFRAME> 这段代码通过脚本构造一个表单提交,通过IFRAME 加载页面自动执行本例,IFRAME 宽高属性设置成零的目的是为了达到隐式攻击的效果,JAVASCRIPT 只对窗口的大小有不成文的规范,宽高不能小于50 像素点,但是对iframe 并没有要求,这为隐式的跨域Post 攻击提供了一个量好的途径。写成脚本的形式并不是说明只要被检测的站点没有脚本注入就没有任何问题,POST 隐式攻击方式一样可以通过第3 方,如图1,4,5,6 攻击路径都适合本例的使用。 Web 2.0 攻击方式 Web 2.0 技术因其能大幅度提升用户的体验,已经被非常广泛的使用,并且Web 2.0 技术对跨站请求的提交有严格的检查,所以一般不用担心来自第三方的xmlhttp 发出的CSRF 攻击。Web 2.0 技术如果在本站点存在脚本注入漏洞,将会产生严重的CSRF 攻击问题;另外一条攻击路径则是通过邮件系统,向受害用户发送带有xmlhttp 请求的脚本文件,是否产生危害取决于用户是否执行该文件,危害性明显低于前两种。 对于发邮件,或者网站上传的文件发起攻击的案例是由IE 的特性造成,由于IE 允许从本地域(local domain) 对任意域发送,一个包含Web 2.0 代码的例子就能使IE 完成成一次离线状态的攻击,IE 允许通过对策略的修改以达到严格的安全配置,从而禁止对同域内容的访问。 以下是通常使用的对Web 2.0 类型的跨站漏洞的攻击代码。 清单3. 通常使用的对Web 2.0 类型的跨站漏洞的攻击代码 <script> alert('start delete'); var payload="<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Header> <serviceVersion>8.0.0 </serviceVersion></soap:Header><soap:Body><deleteDocument xmlns="http://webservices.clb.content.ibm.com"> <path>/@Pcsrftestplace/@RMain.nsf/@F/@DE44FD4FF0956D07648257570002C42DA </path> </deleteDocument></soap:Body></soap:Envelope>"; alert(message); var client = new XMLHttpRequest(); client.open("POST", "http://usercite.com /files/form/api/collections/ 2d0f6188-8872-4722-8922-3a3c842aa443/entry?format=xml "); client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); client.setRequestHeader("x-method-override","DELETE"); client.setRequestHeader("x-requested-with","XMLHttpRequest"); (you can customized the header if you need) client.send(""); </script> <html> 登陆CSRF 攻击方式 登陆式的跨站请求伪造是一种较新的攻击方式,让用户错误的以为是用自己的帐户密码登陆,实际上是登录到一个Hacker 的账户。这种攻击方式的最显著的特征是,Hacker 可以监听到用户的实际操作,通过查询历史记录可以知道用户做了那些操作,如果是在商业网站则会在历史记录中留下信用卡号,如果是在个人信息相关系统则会留下用户的隐私操作。 回页首 使用Rational AppScan 对CSRF 的检测 APPSCAN 是IBM 收购WatchFire 之后获得一款强大的网络安全的检测工具,目前属于Rational 产品线,功能集中在网络应用产品的检测防范上,分静态与动态两种不同的功能,覆盖代码与产品的两端检测需求。 APPSCAN 自从7.7 的版本以后加入对CSRF 的防范,基本原理是通过对同一个需要检测的URL 或者SERVICE 按照顺序发出两次请求,发送两次请求之间会做一次退出登录状态的操作,如果一个对CSRF 已经进行防范的网站是会发送回两个不同的回应内容。实例的说明如下。 请求1 GET/POST http://myproduct.com/services?action=remove&id=10002 Headers ….. ….. Content: …… 返回内容1 Response 200 Headers …. ….. Content:….. 请求2 GET/POST http://myproduct.com/services?action=remove&id=10002 Headers ….. ….. Content: …… 返回内容2 Response 200 Headers …. ….. Content:….. 返回内容1 和返回内容2 如果是完全一致的则可以认为是有问题的,反之则可以认为是没有问题。看似简单的原理,在实际操作中有个很繁琐的逻辑问题,比如请求1 是一个删除动作,那么如何去构造一个请求2,并且获得一个一致的结果呢?解决的办法是,要先做一个操作1,然后再创建一个同样的1,再做操作2。 从上述的简单例子就可以发现有效监测CSRF 是一个较为繁琐的过程。AppScan 的检测前提就是对目标资源的操作在不同的一个Session 中返回的内容肯定是应该不一样的。 这里要注意的问题是误报,Web 应用程序操作大多都是对一个固定的URL 的请求,包含一些资源文件,以及一些功能性的请求。对于资源文件的操作,很多情况下都是一个静态的请求,在未使用PUT/DELETE 的应用程序,是无需对GET 请求进行CSRF 测试,在这种情况下是不存在CSRF 漏洞的。而如果使用了Ajax 框架的应用程序如果存在DELETE/PUT 操作则需注意很可能出现严重的CSRF 问题。未使用Ajax 的产品则集中在GET/POST 请求,需要注意的是GET/POST 请求对CSRF 来说是同样具有可操作性的,对产品的危害性是一致的。 对CSRF 测试的两个主要方向是路径覆盖测试,和精确测试。之所以是要做如此分类的原因是一个产品有大量的URL 如果一一测试需要大量的时间精力,覆盖测试是由工具去完成的是为了保证覆盖到产品的各个路径,有些产品实际上已经对CSRF 有很深的认识,在这种情况下大多数资源已经被很好的保护起来,没有CSRF 的问题,这时候一个对全路径的测试就是很必要的。 精确测试是由人来完成的通过分析产品功能和开发人员的沟通,阅读设计文档来完成的。为何要做精确测试的原因是,所有Web 应用程序非常关注的问题之一就是产品的性能,而对所有请求都做CSRF 防范的话就比如在一个高速公路上设置一个人工收费站一样会大大影响性能,一个好的Web 应用在对CSRF 防范是有针对性的,对一个没有CSRF 保护的产品,一个良好的CSRF 保护开端可以是由精确测试的结果为发起的。通过对固定功能的检测,以及对设计文档的了解,基本就可以断定产品是否做了CSRF 保护。 一个正常的使用Appscan 来检测CSRF 的流程如图2 所示。 图2. 一个正常的使用Appscan 来检测CSRF 的流程 AppScan 使用流程,AppScan 执行过程的一个分解,如图3。 图3. AppScan 执行过程的一个分解 精确测试的方法,目的是为了检测是否存在CSRF 保护。对CSRF 保护有个范围约束的问题,并不是所有的请求都需要对CSRF 攻击做防范。对静态资源除非有DELETE/PUT 操作允许的情况下,才需要进行测试;而对于关键的业务逻辑,比如银行转帐,确认收货人信息,参加竞标,删除一个用户,赋予用户高级权限,等等,对这类定性问题的约束是根据不同的商业产品各异,要具体问题具体分析。 本例以常见的页面删除为实例,阐述一个可以的测试方法。大概分为以下几种情况: 使用GET 来删除页面的,使用DELETE/PUT 来删除页面的,使用POST 来删除页面的,都是服务器与客户端的交互过程,具体的实例分析起来要远比分类更为复杂,一个操作可能带有很多各样的请求,找到有威胁的请求才是最终目的,有时候哪怕是AppScan 已经定位到具体是那个请求,也还需要通过手工将这个案例找出加以描述成为有实际操作价值的场景,这里就需要引入手工测试工具加以支持。 手工工具的介绍,做精确测试需要对HTTP 请求做频繁的操作,如果需要查看请求的内容,还有对具体请求的操作的观察,推荐使用Fiddler 或者WebScarab。 开始手动验证之前,还需要清楚CSRF 发生的条件。所有的问题的发生有个前提条件是用户常用的浏览器中有一个与目标服务器处于激活状态的会话。这个条件需要的原因是,CSRF 攻击的模式是用户A 被恶意用户B 所攻击,攻击是B 发起的被用户A 执行实现的。 而B 往往是在A 常去的网站注入代码,或者发送链接或者包含附件的文件给A,而包含着恶意代码或者链接的页面要被执行,条件是用户A 已经处在和服务器的会话之中,这也是CSRF 发生的前提条件,也是手工测试的基础。 对GET CSRF 漏洞的测试 GET 请求的情况下,请求如http://mysite/service?action=delete&pageid=100001 这类问题的验证最为直接,并且无需写脚本和使用fiddler 工具去观察实际的请求的格式。检测方法就是在维持一个与服务器连接的前提下,在浏览器地址栏输入如下网址,如果实际的页面被删除了就是CSRF 攻击成功了。对于如此清楚的实例基本看到URL 已经可以证明没有任何CSRF 保护。 可关联的攻击场景如下,在任何可以显示图片的地方写入如下<img src=http://mysite/service?action=delete&pageid=100001 width=0 height=0/>,另外只需要指引有删除权限的用户访问一下包含这个图片标签的网页,往往是通过发一个邮件或者MSN 一个简单的链接就可以完成删除页面的操作。 对POST CSRF 漏洞的测试 POST 请求的操作并不能免除CSRF 的攻击。在浏览器中要发出POST 请求,可以使用两种方法,一个是通过脚本调用页面文档元素form 直接进行提交操作,特点是可以进行跨域的脚本提交,隐式攻击。另一种是通过使用Ajax 对象直接发出请求,但是由于不能跨域发出请求,可执行的力度并不高,但是还是有可能性。同样是一个删除页面的操作,如下所示结构。 POST http://mysite/service Headers…. Action=delete&pageid=100001 这个不同于GET 之处是不能简单的通过在浏览器直接输入一个链接就能测试。需要借助一下预设好的HTTP 服务器如IBM HTTP Server、Domino,或者IIS。将IFrame.html 的清单拷贝到服务器的一个目录。通过修改frame1.html 中的csrf_hack() 如下。 清单4. 修改frame1.html 中的csrf_hack() function csrf_hack() { var fields; fields += "<input type='' name='action' value='"+"delete"+"'>"; fields += "<input type='' name=pageid value='"+"1000001" +"'>"; unescape(fields); post('http://mysite/service ',fields); alert("csrf_end"); } 可关联的攻击场景如下 ,通过邮件或者MSN 发送一个链接http://hackerWebServer/iframe 给可以删除页面的用户,该操作就会被执行,如果页面删除,攻击成功。通过在其他网站可以做脚本注入的将 iframe.html 脚本写在该网站,一样可以达到攻击效果。 另一类通过Ajax 提交的post 请求,这类结构中多采用SOAP message 或者类似的XML 消息体,或者Jason 消息体提交请求。结构如下。 POST http://www.2cto.com /service Headers…. <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Header> <serviceVersion>8.0.0</serviceVersion> </soap:Header><soap:Body> <deleteDocument xmlns="http://webservices.clb.content.ibm.com"> <path>/@Pcsrftestplace/@RMain.nsf/@F/@DE44FD4FF0956D07648257570002C42DA </path></deleteDocument></soap:Body></soap:Envelope> 在此类情况下,需要修改form 的表单的enctype 属性为multipart/form-data,因为在默认的情况下是application/x-www-form-urlencoded,所有字符都会做URL 编码转换,提交的数据是不合法的无法被服务器端识别,所以需要修改enctype 属性,在multipart/formdata 的情况下,数据是不会被编码的,而在很多服务器的接收端有的就是使用multipart/formdata 去接受数据。由于javascript 出于对安全的考虑禁止脚本自动修改form 中提交的file 属性的输入的值,所以想通过脚本修改控制enctype 是不允许的,这样不同于第一类POST 请求。但是并不影响场景的合理性,通过在有漏洞的网站伪造表单请求,form 指向我们要操作的URL 即可。这种情况下,需要构造一个完整的表单,并通过用户点击一个任意方式发送的链接达到攻击效果。 对DELETE/PUT CSRF 漏洞的测试 DELETE/PUT 请求依赖于Web 2.0 技术,由于本身的限制,自由发出跨站的伪造请求是不可能的。更多使用的是离线攻击,或者本站点的脚本注入攻击。在存在本站点脚本注入攻击的情况下,所有这4 种情况下,都可以完成隐式的攻击方式。代码请参照Web 2.0 攻击章节的实例。 回页首 CSRF 的防范 CSRF 的防范机制有很多种,防范的方法也根据CSRF 攻击方式的不断升级而不断演化。常用的有检查Refer 头部信息,使用一次性令牌,使用验证图片等手段。出于性能的考虑,如果每个请求都加入令牌验证将极大的增加服务器的负担,具体采用那种方法更合理,需要谨慎审视每种保护的优缺点。 1. 检查HTTP 头部Refer 信息,这是防止CSRF 的最简单容易实现的一种手段。根据RFC 对于HTTP 协议里面Refer 的定义,Refer 信息跟随出现在每个Http 请求头部。Server 端在收到请求之后,可以去检查这个头信息,只接受来自本域的请求而忽略外部域的请求,这样就可以避免了很多风险。当然这种检查方式由于过于简单也有它自身的弱点: a) 首先是检查Refer 信息并不能防范来自本域的攻击。在企业业务网站上,经常会有同域的论坛,邮件等形式的Web 应用程序存在,来自这些地方的CSRF 攻击所携带的就是本域的Refer 域信息,因此不能被这种防御手段所阻止。 b) 同样,某些直接发送HTTP 请求的方式(指非浏览器,比如用后台代码等方法)可以伪造一些Refer 信息,虽然直接进行头信息伪造的方式属于直接发送请求,很难跟随发送cookie,但由于目前客户端手段层出不穷,flash,javascript 等大规模使用,从客户端进行refer 的伪造,尤其是在客户端浏览器安装了越来越多的插件的情况下已经成为可能了。 2. 使用一次性令牌,这是当前Web 应用程序的设计人员广泛使用的一种方式,方法是对于Get 请求,在URL 里面加入一个令牌,对于Post 请求,在隐藏域中加入一个令牌。这个令牌由server 端生成,由编程人员控制在客户端发送请求的时候使请求携带本令牌然后在Server 端进行验证。但在令牌的设计上目前存在着几个错误的方案: a) 使用和Session 独立的令牌生成方式。这种令牌的值和Session 无关,因此容易被其他用户伪造。这里的其他用户指的是当前Web 应用程序的其他用户和活跃在网络传输阶段各个设置上的监听者,这种恶意用户可能使用自己的令牌来进行替换以便达到伪造的目的。 b) 完全使用Session 认证信息作为令牌的生成方式。这种保护方式对于保护CSRF 是起了作用的,但是可能会造成其他危害,具体来说,如果某些URL 或者网页被拷贝下来与其他人共享,那么这些URL 或者拷贝下来的网页中可能会含有用户的会话信息,这种信息一旦被恶意用户获得,就能造成极大的危害。 因此,一个正确的令牌设计应该是使用Session 信息做Hash,用得出的哈希值来做CSRF 的令牌。 3. 使用验证图片,这种方法的出现的作用是对于机器人暴力攻击的防止。但在CSRF 的防范上,也有一些安全性要求比较高的的应用程序结合验证图片和一次性令牌来做双重保护。由于这种图片验证信息很难被恶意程序在客户端识别,因此能够提高更强的保护。当客户端的浏览器可能已经处于一种不安全的环境中的情况下(比如客户端的安全级别设置较低,客户端浏览器安装了不安全的插件等)。 以上给的这些只是防范CSRF 的比较通用的一些方法,Web 开发人员可以根据自己对自己的应用程序的功能的理解来确定安全级别的要求从而选择使用不同的保护措施,也推荐在同一应用程序内部结合使用多种方法来进行保护。 总结 CSRF 攻击作为一个存在已久的攻击方式,在大量的商业网站上都可以找出,应用本文的知识作出一个合理的分析,有针对性的提出改进方案才是本文作者希望看到的,在即不损害应用程序的性能的前提下,提高安全性;而对即将开发的网络应用程序来说,深刻理解其的危害性,在设计阶段就考虑到对CSRF 的防范,无疑能收到更好的效果 |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com