返回介绍

4.1 CSRF 概述

发布于 2024-01-20 15:41:04 字数 4403 浏览 0 评论 0 收藏 0

CSRF是跨站请求伪造,可能刚接触CSRF这个概念的人会很容易把它与XSS混淆。我们知道,攻击的发生是由各种请求造成的,对于CSRF来说,它的请求有两个关键点:跨站点的请求与请求是伪造的。

4.1.1 跨站点的请求

从字面上看,跨站点请求的来源是其他站点,比如,目标网站的删除文章功能接收到来自恶意网站客户端(JavaScript、Flash、HTML等)发出的删除文章请求,这个请求就是跨站点的请求,目标网站应该区分请求来源。

字面上的定义总是狭义的,这样恶意的请求也有可能来自本站。

4.1.2 请求是伪造的

伪造的定义很模糊,一般情况下,我们可以认为:如果请求的发出不是用户的意愿,那么这个请求就是伪造的。在第3章“前端黑客之XSS”中我们知道,对于XSS来说,发起的任何攻击请求实际上都是目标网站同域内发出的,此时已经没有同源策略的限制,虽然这样,我们同样可以认为这些请求也是伪造的,因为它们不是用户的意愿。

4.1.3 一个场景

对于CSRF来说,强调这两个关键点是想表达CSRF的安全风险在大多数场景中的共同点,而在大多数场景中,这种攻击是XSS无法完成的。

我们先来看这个“大多数场景”是什么。

目标网站A:www.a.com

恶意网站B:www.b.com

两个域不一样,目标网站A上有一个删除文章的功能,通常是用户单击“删除链接”时才会删除指定的文章,这个链接是www.a.com/blog/del?id=1,id号代表不同的文章。

我们知道,这样删除文章实际上就是发出一个GET请求,那么如果目标网站A上存在一个XSS漏洞,执行的JS脚本无同源策略限制,就可以按下面的方式来删除文章。

· 使用AJAX发出GET请求,请求值是id=1,请求目标地址是www.a.com/blog/del。

· 或者动态创建一个标签对象(如img、iframe、script)等,将它们的src指向这个链接www.a.com/blog/del?id=1,发出的也是GET请求。

· 然后欺骗用户访问存在XSS脚本的漏洞页面(在目标网站A上),则攻击发生。

如果不用这种方式,或者目标网站A根本不存在XSS漏洞,还可以如何删除文章?看看CSRF的思路,步骤如下:

· 在恶意网站B上编写一个CSRF页面(www.b.com/csrf.htm),想想有什么办法可以发出一个GET请求到目标网站A上?

· 利用AJAX?不行,它禁止跨域传输数据。

· 那么,用代码<img src=http://www.a.com/blog/del?id=1/>。

· 然后欺骗已经登录目标网站A的用户访问www.b.com/csrf.htm页面,则攻击发生。

这个攻击过程有三个关键点:跨域发出了一个GET请求、可以无JavaScript参与、请求是身份认证后的。

1)跨域发出了一个GET请求

在第1章中,我们提到Web层面上有一个非常重要的策略(即同源策略),这个策略用来限制客户端脚本的跨域请求行为,但实际上由客户端HTML标签等发出的跨域GET请求被认为是合法的,不在同源策略的限制中,但是这些请求发出后并没能力得到目标页面响应的数据内容。

很多网站其实都需要有这样的功能,比如,嵌入第三方资源:图片、JS脚本、CSS样式、框架内容,尤其是很多开放的Web 2.0网站有个mashup应用聚合概念,如Google的Gadgets或者SNS社区中的第三方Web应用与Web游戏,通过iframe嵌入第三方扩展应用,如果将这样的GET请求限制住,那么Web世界就过于封闭了。

安全风险总是出现在正常的流程中,现在我们发出的是一个删除文章的GET请求,对于合法的跨域请求,浏览器会放行。

2)可以无JavaScript参与

大家看到了,CSRF这个过程与XSS不一样,不需要JavaScript参与,当然也可以有JavaScript参与,比如在www.b.com/csrf.htm中使用JavaScript动态生成一个img对象:

<script>
new Image().src = 'http://www.a.com/blog/del?id=1'
</script>

同样可以达到攻击效果。需要特别注意的是:这里并不是JavaScript跨域操作目标网站A的数据,而是间接生成了img对象,由img对象发起一个合法的跨域GET请求而已,这个过程和上面直接用一个img标签一样。

3)请求是身份认证后的

这一点非常关键,跨域发出的请求类似这样:

GET /blog/del?id=1 HTTP/1.1
Host: www.a.com
User-Agent:Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0
Connection: keep-alive
Referer: http://www.b.com/csrf.htm
Cookie: sid=0951abe6d508dab60357804519a61b999;JSESSIONID=abcTePo2Ori_k-pW t5net;

而如果是目标网站A,用户自己单击删除链接时发出的请求类似这样:

GET /blog/del?id=1 HTTP/1.1
Host: www.a.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0
Connection: keep-alive
Referer: http://www.a.com/blog/
Cookie:sid=0951abe6d508dab60357804519a61b999;JSESSIONID=abcTePo2Ori_k-pW t5net;

可以看到两个请求中,除了请求来源Referer值不一样外,其他都一样,尤其是这里的Cookie值,该Cookie是用户登录目标网站A后的身份认证标志。跨域发出的请求也同样会带上目标网站A的用户Cookie,这样的请求就是身份认证后的,攻击才会成功。

看上去这个过程很容易理解,其实我们漏了一个非常关键的概念:在第2章详细提过的,Cookie分本地Cookie与内存Cookie,这两类Cookie在CSRF的过程中会存在一些差异,IE浏览器默认不允许目标网站A的本地Cookie在这样的跨域请求中带上,除非在HTTP响应头中设置了P3P(Plat-form for Privacy Preferences),这个响应头告诉浏览器允许网站(恶意网站B)跨域请求目标网站A的资源时带上目标网站A的用户本地Cookie。对于非IE浏览器,就没这样的限制。

好了,通过这个场景,我们已经知道了CSRF的过程,这个过程中只介绍了GET请求的情况,那么POST请求呢?比如,目标网站A的“写文章”功能,这是一个提交表单的操作,会发起POST请求。同样,这个POST请求可以从恶意网站B中发出,通过JavaScript自动生成一份表单,表单的action地址指向目标网站A的“写文章”表单提交地址,表单的相关字段都准备好后,即可发出请求。下面看一段代码:

<body></body>
<script>
function new_form(){ 
  // 创建表单函数
  var f = document.createElement("form");
  document.body.appendChild(f);
  f.method = "post";
  return f;
}

function create_elements(eForm, eName, eValue){
  // 创建表单项函数,eForm: 表单对象,eName: 表单项,eValue: 表单项值
  var e = document.createElement("input");
  eForm.appendChild(e);
  e.type = 'text';
  e.name = eName;
  if(!document.all){
    e.style.display = 'none';
    }
  else{
    e.style.display = 'block';
    e.style.width = '0px';
    e.style.height = '0px';
  } 
  // 兼容浏览器的隐藏设置,目的是让表单不可见
  e.value = eValue;
  return e;
}

var _f = new_form(); // 创建表单对象
create_elements(_f, "title", "hi"); // 创建表单项:title=hi
create_elements(_f, "content", "csrf_here"); // 创建表单项:
content=csrf_here
_f.action= "http://www.a.com/blog/add";
// 设置表单action提交地址为目标网站A的/blog/add页面
_f.submit(); // 自动提交
</script>

构造完成,当目标网站A的用户被欺骗访问了恶意网站B的该页面时,一个跨域的伪造的POST表单请求就发出了。同样,这个请求带上了目标网站A的用户Cookie。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文