XSS和CSRF

学习自:白帽子讲web安全 web前端黑客技术

TOP10攻击

同源限制

影响“源”的因素有:host(域名或IP地址,如果是IP地址则看做一个根域名)、子域名、端口、协议。

对于浏览器来说,除了DOM、Cookie、XMLHttpRequest会受到同源策略的限制外,浏览器加载的一些第三方插件也有各自的同源策略。最常见的一些插件如Flash、Java Applet、Silverlight、Google Gears等都有自己的控制策略。

之前文章

在浏览器中,<script>、<img>、<iframe>、<link>等标签都可以跨域加载资源,而不受同源策略的限制。这些带“src”属性的标签每次加载时,实际上是由浏览器发起了一次GET请求。不同于XMLHttpRequest的是,通过src属性加载的资源,浏览器限制了JavaScript的权限,使其不能读、写返回的内容。

浏览器的同源策略是浏览器安全的基础

浏览器发展出了多进程架构,从安全性上有了很大的提高。

浏览器进程包括:主进程、插件进程、GPU进程、渲染进程(浏览器内核),其中,渲染进程包括多个线程,如:GUI线程、js线程、事件触发线程、定时器线程、网络请求线程

XSS

XSS,它的全称为 Cross Site Scripting,即跨站脚本

XSS攻击,通常指黑客通过“HTML注入”篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。

<div><script>alert(/xss/)</script></div>

反射型XSS

反射型XSS(也叫非持久型XSS),发出请求时,XSS代码出现在URL中,作为输入提交到服务端,服务端解析后响应,在响应内容中出现这段XSS代码,最后浏览器解析执行。这个过程就像一次反射,故称为反射型XSS。

黑客往往需要诱使用户“点击”一个恶意链接,才能攻击成功。

存储型XSS

存储型XSS(也叫持久型XSS),存储型XSS和反射型XSS的差别仅在于:提交的XSS代码会存储在服务端(不管是数据库、内存还是文件系统等),下次请求目标页面时不用再提交XSS代码。

最典型的例子是留言板XSS,用户提交一条包含XSS代码的留言存储到数据库,目标用户查看留言板时,那些留言的内容会从数据库查询出来并显示,浏览器发现有XSS代码,就当做正常的HTML与JS解析执行,于是就触发了XSS攻击。

存储型XSS的攻击是最隐蔽的。

DOM XSS

和反射型XSS、存储型XSS的差别在于,DOM XSS的XSS代码并不需要服务器解析响应的直接参与,触发XSS靠的就是浏览器端的DOM解析,可以认为完全是客户端的事情。

防御XSS

XSS的本质还是一种“HTML注入”,用户的数据被当成了HTML代码一部分来执行,从而混淆了原本的语义,产生了新的语义。

如果网站使用了MVC架构,那么XSS就发生在View层——在应用拼接变量到HTML页面时产生。所以在用户提交数据处进行输入检查的方案,其实并不是在真正发生攻击的地方做防御。

想要根治XSS问题,可以列出所有XSS可能发生的场景,再一一解决。

防止XSS后的cookie劫持:浏览器禁止页面的JavaScript访问带有HttpOnly属性的Cookie。HttpOnly是在Set-Cookie时标记的

XSS Filter:输入检查一般是检查用户输入的数据中是否包含一些特殊字符,如<、>、’、”等。如果发现存在特殊字符,则将这些字符过滤或者编码。
比较智能的“输入检查”,可能还会匹配XSS的特征。比如查找用户数据中是否包含了“<script>”、“javascript”等敏感字符。

输出检查:除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS攻击。

防御DOM Based XSS:

CSRF

CSRF的全称是Cross Site Request Forgery,即跨站请求伪造。

浏览器所持有的Cookie分为两种:一种是“Session Cookie”,又称“临时Cookie”;另一种是“Third-party Cookie”,也称为“本地Cookie”。

两者的区别在于,Third-party Cookie是服务器在Set-Cookie时指定了Expire时间,只有到了Expire时间后Cookie才会失效,所以这种Cookie会保存在本地;而Session Cookie则没有指定Expire时间,所以浏览器关闭后,Session Cookie就失效了。

在浏览网站的过程中,若是一个网站设置了Session Cookie,那么在浏览器进程的生命周期内,即使浏览器新打开了Tab页,Session Cookie也都是有效的。Session Cookie保存在浏览器进程的内存空间中;而Third-party Cookie则保存在本地。

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

看看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参与、请求是身份认证后的。

请求是身份认证后的,这一点非常关键

HTML CSRF攻击

HTML中能够设置src/href等链接地址的标签都可以发起一个GET请求。还有通过JavaScript动态生成的标签对象或CSS对象发起的GET请求,而发出POST请求只能通过form提交方式。

JSON HiJacking攻击

攻击过程是CSRF,不过是对AJAX响应中最常见的JSON 数据类型进行的劫持攻击

Flash CSRF攻击

发起的CSRF攻击是通过ActionScript脚本来完成的,说到Flash CSRF时,我们通常会想到以下两点:
· 跨域获取隐私数据。
· 跨域提交数据操作,一些如添加、删除、编辑等操作的请求,这里并不会获取到隐私数据。

防御CSRF

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

验证码被认为是对抗CSRF攻击最简洁而有效的防御方法。出于用户体验考虑,网站不能给所有的操作都加上验证码。因此,验证码只能作为防御CSRF的一种辅助手段

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

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

现在业界针对CSRF的防御,一致的做法是使用一个Token

攻击者只有预测出URL的所有参数与参数值,才能成功地构造一个伪造的请求;反之,攻击者将无法攻击成功。

出于这个原因,可以想到一个解决方案:把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值。这是“不可预测性原则”的一种应用

使用安全的随机数生成器生成Token。 Token可以放在用户的Session中,或者浏览器的Cookie中。

username=abc&item=123&token=[random(seed)]

在使用Token时,应该尽量把Token放在表单中。把敏感操作由GET改为POST,以form表单(或者AJAX)的形式提交,可以避免Token泄露。

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