《白帽子讲Web安全》读书笔记(未完待续)


同源策略


所谓同源是指,域名,协议,端口相同。

同源策略(same origin policy)是一种约定,它是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能受到影响。可以说Web是构建在同源策略的基础之上的,浏览器只是针对同源策略的一种实现。

浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前“document”读取或设置某些属性。


跨站脚本攻击(XSS)


一、XSS简介

跨站脚本攻击,英文全称是Cross Site Script,本来缩写是CSS,但是为了和层叠样式表(Cascading Style Sheet,CSS)有所区别,所以在安全领域叫“XSS”。

XSS攻击,通常指黑客通过“HTML注入”篡改了网页,插入恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。在一开始,这种攻击的演示案例是跨域的,所以叫“跨站脚本”,但是发展至今,由于JavaScript的强大功能以及网站前端应用的复杂化,是否跨域已经不重要了。

二、XSS的类型:

1. 反射型XSS

反射性XSS只是简单地把用户输入的数据“反射”给浏览器。也就是说,黑客往往要诱使用户“点击”一个恶意链接,才能攻击成功。反射型XSS也叫做“非持久型XSS”

2.存储型XSS

存储型XSS会把用户输入的数据“存储”在服务端。这种XSS具有很强的稳定性。黑客把恶意的脚本保存到服务器,所以这种XSS攻击也叫做“存储型XSS”。存储型XSS通常也叫做“持久型XSS”,因为从效果上来说,它存在的时间是比较长的。

比较常见的一种场景就是,黑客写下一篇包含有恶意JavaScript代码的博客文章,博客发表后,所有访问该博客文章的用户,都会在他们的浏览器中执行这段恶意代码。

3.Dom Base XSS

通过修改页面的DOM节点形成的XSS,称之为Dom Based XSS。

Dom Based XSS从效果上来说也是反射型XSS,单独划分出来,是因为Dom Based XSS的形成原因比较特别,所以把它单独作为一个分类。

三、XSS Payload

XSS攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,通过恶意脚本,控制用户的浏览器——这些用以完成各种具体功能的恶意脚本,被称为“XSS Payload”。

XSS Payload实际上是JavaScript脚本(还可以是Flash或者其他客户端的脚本),所以任何JavaScript脚本能实现的功能,XSS PayLoad都能做到。

一个最常见的XSS PayLoad,就是通过读取浏览器的Cookie对象,从而发起“cookie劫持”攻击。

Cookie中一般加密保存了当前用户的登陆凭证。Cookie如果丢失,往往意味着用户的登陆凭证丢失,换句话说,攻击者可以不通过密码,而直接登陆用户的账户。


跨站点请求伪造(CSRF)


一、CSRF简介

跨站请求伪造(Cross Site Request Forgery),也被称为one-click attack或者session riding,通常缩写为CSRF或者XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

CSRF跟XSS相比,XSS利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

二、CSRF的防御

1.验证码

验证码被认为是对抗CSRF攻击最简洁而有效的防御方法。

CSRF攻击的过程,往往是在用户不知情的情况下构造了网络请求。而验证码,则强制用户必须与应用进行交互,才能完成最终请求。因此,通常情况下验证码能够很好地遏制CSRF攻击。

2.Referer Check

Referer Check在互联网中最常见的应用就是“防止图片盗链”。同理,Referer Check也可以用于检查请求是够来自合法的“源”。

常见的互联网应用,页面与页面之间都具有一定的逻辑关系,这就使得每个正常请求的Referer具有一定的规律。

比如一个“论坛发帖”的操作,在正常情况下需要先登录到用户后台,或者访问有发帖功能的页面。在提交“发帖”的表单时,Referer的值必然是发帖表单所在的页面。如果Referer值不是这个页面,甚至不是发帖网站的域,则极有可能是CSRF攻击。

Referer Check的缺陷在于,服务器并非什么时候能都取到Referer。很多用户处于保护隐私的考虑,限制了Referer的发送。在某些情况下,浏览器也不会发送Referer,比如从HTTPS跳转到HTTP,出于安全考虑,浏览器也不会发送Referer。

出于以上种种原因,我们还是无法依赖于Referer Check作为防御CSRF攻击的主要手段。但是,通过Referer Check来监控CSRF攻击的发生,倒是一种可行的方法

3.Anti CSRF Token
  • CSRF的本质

    CSRF为什么能够攻击成功?其本质原因是重要操作的所有参数都是可以被攻击者猜测到的。

    攻击者只有预测出URL的所有参数与参数值,才能成功地构造一个伪造的请求;反之,攻击者将无法攻击成功。出于这个原因,可以想到一个解决方法:把参数加密,或使用一些随机数,从而让攻击者无法猜测到参数值。

    但是这个方法也存在一些问题。首先,加密或者混淆后的URL将变得非常难度,对用户非常不友好。其次,如果加密的参数每次都要改变,某些URL将无法被用户收藏。最后,普通的参数,如果也被加密或哈希,将会给数据分析工作带来很大的困扰。(因为数据分析工作常常需要用到参数的明文)

    因此,我们需要一个通用的方法来解决这个问题,那就是Anti CSRF Token。这个token的值是随机的,不可预测的。

    Token需要足够随机,必须使用足够安全的随机数生成算法,或者采用真随机数生成器。另外,Token应该是一个秘密,为用户与服务器所共同持有,不能被第三者知晓。在实际应用中,Token可以放在用户的Session中,或者浏览器的Cookie中。

    Token需要同时放在表单和Session中,在提交请求时,服务器只需庁表单中的Token与Session(或CooKie)中的Token是否一致,如果一致,则认为是合法请求,如果不一致,或者有一个是空,则认为请求不合法,可能发生了CSRF攻击。

  • Token的使用原则

    • 防御CSRF的Token,是根据“不可预测性原则”设计的方案,所以Token的生成一定要足够随机,需要使用安全的随机数生成器来生成Token。

    • 这个Token的目的不是为了防止重复提交,所以为了使用方便,可以允许在一个用户的有效声明周期内,在Token消耗掉前都使用同一个Token。但是如果用户已经提交了表单,则这个Token已经消耗掉,应该再次重新生成一个新的Token。

    • 如果Token保存在Cookie中,而不是服务器端的Session中,则会带来一个新的问题。如果一个用户打开几个相同的页面同时操作,当某个页面消耗掉Token后,其它页面的表单内保存的还是被消耗掉的那个Token,因此其它页面的表单再次提交时,会出现Token错误。在这种情况下,可以考虑生成多个有效的Token,以解决多页面共存的场景。

    • 最后,使用Token时应该注意Token的保密性。Token如果出现在某个页面的URL中,则可能会通过Referer的方式泄露。因此在使用Token时,应该尽量把Token放在表单中,把敏感操作由GET改为POST,以form表单或者AJAX的形式提交,可以避免Token泄露。

CSRF的Token仅仅用于对抗CSRF攻击,当网站还同时存在XSS漏洞时,这个方案就会变得无效,因为XSS可以模拟客户端浏览器执行任意操作。在XSS攻击下,攻击者完全可以请求页面后,读出该内容里的Token值,然后再构造出一个合法的请求。这个过程可以称之为XSRF,和CSRF以示区分。

三、小结

  • CSRF攻击是攻击者利用用户的身份操作用户账户的一种攻击方式。设计CSRF的防御方案必须先理解CSRF攻击的原理和本质。

  • 根据“不可预测性原则”,我们通常使用Anti CSRF Token来防御CSRF攻击。在使用Token时,要注意Token的保密性和随机性。


点击劫持(ClickJacking)


1.什么是点击劫持

点击劫持是一种视觉上的欺骗手段,它与CSRF有异曲同工之妙,都是在用户不之情的情况下诱使用户完成一些动作。但是在CSRF攻击的过程中,如果出现用户交互的页面,则攻击可能无法顺利完成,而点击劫持利用的就是与用户产生交互的页面。

2.点击劫持多种多样
  • Flash点击劫持

  • 图片覆盖攻击

  • 拖拽劫持与数据窃取

  • 触屏劫持

3.防御点击劫持

ClickJacking是一种视觉上的欺骗,针对传统的ClickJacking,一般是通过禁止跨域的iframe来防范。

  • frame busting

    通常可以写一段JavaScript代码,以禁止iframe的嵌套,这种方法叫做frame busting。比如下面这段代码:

javascript if(top.location != location){ top.location = self.location; }

  • X-Frame-Options

    因为frame busting存在被绕过的可能,所以我们需要寻找其他更好的解决方案。一个比较好的方案是使用一个HTTP头-X-Frame-Options。

    X-Frame-Options可以说是为了解决ClickJacking而生的。它有三个可选的值。

    • DENY——拒绝当前页面加载任何frame页面;

    • SAMEORIGIN——frame页面的地址只能为同源域名下的页面;

  • ALLOW-FROM origin——可以定义允许frame加载的页面地址。

4.小结

ClickJacking相对于XSS与CSRF来说,因为需要诱使用户与页面产生交互行为,因此实施攻击的成本更高,在网络犯罪中比较少见。但ClickJacking在未来仍有可能被攻击者利用,不可不察。


HTML5安全


HTML5中新增的一些标签和属性,使得XSS等Web攻击产生了新的变化。

1.iframe的sandbox

在HTML5中,专门为iframe定义了一个新的属性,叫sandbox。使用sandbox这一属性后,<iframe>标签加载的内容被视为一个独立的”源“,其中的脚本将被禁止执行,表单被禁止提交,插件被禁止加载,指向其他浏览器对象的链接也会被禁止。

sandbox属性可以通过参数来支持更精确的控制,有一下几个值可以选择:

  • allow-same-origin:允许同源访问

  • allow-top-navigation:允许访问顶层窗口

  • allow-forms:允许提交表单

  • allow-script:允许执行脚本(有的行为,即使是设置了allow-script也是不允许的,比如“弹出窗扣”)

iframe的sandbox属性将极大地增强应用使用iframe的安全性

2.Link Types:noreferrer

标签指定noreferrer后,浏览器在请求该标签执行的地址时将不再发送Referer,这种设计是出于保护用户敏感信息和隐私的考虑。避免通过Refer泄露一些敏感信息。(这个标签需要开发者手动添加在页面的标签中)

HTTP Referer是header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。

3.Canvas的妙用

其它安全问题


1.Cross-Origin Resource Sharing

Origin Header用于标记HTTP发起的“源”,服务器通过识别浏览器自动带上这个Origin Header,来判断浏览器的请求是否来自一个合法的“源”。Origin Header可以用于防范CSRF,它不像Referer那么容易被伪造或者清空。

2.postMessage——跨窗口传递消息

postMessage允许每一个window(包括当前窗口、弹出窗口、iframes等)对象往其他的窗口发送文本信息,从未实现跨窗口的消息传递。并且,这个功能是不受同源策略限制的。

发送窗口负责发送事件,而接收窗口需要绑定一个“message”事件,监听其他窗口发来的消息。如果没有监听这个事件,则无法接收到消息。

在使用postMessage()时,有两个安全问题需要注意:

  • 必要时,可以在接收窗口验证Domain,甚至验证URL,以防止来自非法页面的消息。这实际上是在代码中实现一次同源策略的验证过程。

  • 根据“Secure By Default”原则, 在接收窗口不应该信任任何接收到的消息,而需要对消息进行安全检查。

3.Web Storage

Web Storage让Web开发更加的灵活多变,它的强大功能也为XSS Payload打开方便之门,攻击者有可能将恶意代码保存在Web Storage中,从而实现跨页面攻击。

推荐阅读更多精彩内容