浏览器安全
同源策略
同源策略(Same Origin Policy)是一种约定,是浏览器最核心也是最基础的安全功能。
可以说web是构建在同源策略的基础之上的,浏览器只是针对同源策略的一种实现。
浏览器的同源策略,限制了来自不同源的document
或脚本,对当前document
读取或设置某些属性。
影响“源”的因素有:host(域名或ip)、子域名、端口、协议。
对于当前页面来说,页面内存放JavaScript文件的域并不重要,重要的是加载JavaScript的页面所在的域是什么。
在浏览器中,<script> <img> <iframe> <link>
等标签都可以跨域加载资源,而不受同源策略限制。这些带“src”属性的标签每次加载时,浏览器发起一次GET请求。
不同于XMLHttpRequest,通过src
属性加载的资源,浏览器限制了JavaScript的权限,使其不能读、写返回的内容。
Flash 主要是通过目标网站提供的crossdomain.xml
文件来判断是否允许当前“源”的Flash跨域访问目标资源。
浏览器沙箱
Sandbox 即沙箱,已经成为泛指“资源隔离类模块”的代名词。
Sandbox 的设计目的一般是为了让不可信任的代码运行在一定的环境中,限制不可信任的代码访问隔离区之外的资源。
如果一定要跨域Sandbox边界产生数据交换,则只能通过指定的数据通道,比如经过封装的API来完成,在这些API中严格检查请求的合法性。
恶意网址拦截
基于 黑名单 的。
恶意网址拦截主要是浏览器周期性地从服务器端获取一份最新的恶意网址名单,如果用户要访问的网址存在于黑名单,则弹出一个警告页面。
跨站脚本攻击(XSS)
XSS简介
XSS 全称是Cross Site Script,为与层叠样式表CSS区分,叫XSS。
XSS攻击,通常是指黑客通过“HTML注入”篡改了网页,插入恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击方式。
这种攻击的演示方式一开始是跨域的,由于现在JavaScript的强大功能以及网站前端应用的复杂化,是否跨域已经不再重要。
XSS分类
- 反射型XSS。简单地把用户输入的数据“反射”给浏览器。需要用户点击才能攻击成功。
- 存储型XSS。把用户输入数据“存储”在服务器端。也叫持久型XSS。
- DOM Based XSS。通过修改页面的DOM节点来形成XSS。称为DOM Based XSS。
XSS 攻击进阶
XSS攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,通过恶意脚本,控制用户的浏览器。这些用于完成各种具体功能的恶意脚本,被称为“XSS Payload ”。
Cookie 劫持
Cookie中一般加密保存了用户的登录凭证,通过读取浏览器的Cookie对象,攻击者可以不通过密码而直接登录进用户的账户。
攻击过程
- 攻击者先远程加载一段脚本,真正的XSS Payload 写在这个脚本里,避免在URL的参数里写入大量的JavaScript代码。
- 在脚本里读取Cookie对象,构建一个
img
元素,这个元素的URL里包含了Cookie,并指向恶意的服务器;插入HTML DOM,浏览器加载这个图像,就把Cookie发送到了攻击者的服务器。 - 攻击者在服务器上可以获取到用户Cookie,利用这个Cookie替换掉自己浏览器的Cookie就可以登录用户账户了。
应对措施
- 在Cookie里绑定客户端信息,如客户端IP、浏览器类型等。
- 利用Cookie的
HttpOnly
标识防止“Cookie劫持”。
构建Get与POST请求
这种攻击方式是指攻击者构建HTTP GET或POST请求来进行破坏。在具体的攻击中,攻击者通过XSS诱使用户执行XSS Payload 。
构建HTTP GET:
var img = document.createElement("img");
img.src = "http://bolg.sohu.com/manage/entry.do?m=delete&id=123456";
document.body.appendChild(img);
构建HTTP POST:
var dd= document.createElement("div");
document.body.apendChild(dd);
dd.innerHTML = '<form action="" method="post" id="xssform" name="mbform">' +
'<input type="hidden" value="JiUY" name="ck" />' +
'<input type="text" value="test value" name="mb_text" />' +
'</form>';
document.getElementById('xssform').submit();
通过构建GET与Post 请求,攻击者可以破坏用户数据,或者窃取用户数据并发送到自己的服务器。
XSS钓鱼
前面的攻击是通过脚本自动完成,缺少与用户的交互过程。
对于提交表单需要验证码的情况,XSS Payload 可以读取页面内容,讲验证码的图片URL发送到远程服务器,攻击者在远程XSS后台接收当前验证码,并将验证码的值返回给当前的XSS Payload ,从而绕过验证码。
XSS钓鱼是指攻击者利用XSS Payload 伪造出一些交互的页面,引诱用户输入他们想要的数据,如伪造登陆框,引诱用户输入密码。
充分发挥想象力,可以使得XSS攻击的威力更巨大。
识别用户浏览器
攻击者为了获取更大利益,往往需要准确地收集用户的个人信息。比如,如果知道用户使用的浏览器、操作系统,攻击者就有可能实施一次精准的浏览器内存攻击,最终给用户电脑植入一个木马。
通过JavaScript脚本识别浏览器,最直接的是通过XSS读取浏览器的UserAgent对象,但浏览器的UserAgent是可以伪造的。攻击者通过另一种方法识别浏览器。
由于浏览器之间的实现存在差异--不同浏览器会实现一些独特的功能,而同一个浏览器的不同版本之间也可能会存在细微差别。通过分辨这些浏览器之间的差异,就能准确地判断出浏览器版本。
识别用户安装的软件
在IE中,可以通过判断ActiveX控件的classid是否存在来推测用户是否安装了该软件。
Firefox的插件列表存放在一个DOM对象中,通过查询DOM对象可以遍历出所有的插件列表。
XSS Worm
XSS Worm是XSS的一种终极利用方式。
一般来说,用户之间发生交互行为的页面,如果存在存储型XSS,则比较容易发起XSS Worm攻击。
XSS 构造技巧
利用字符编码
百度搜藏在一个<Script>
标签中输出了一个变量,其中转义了双引号:var redirectUrl = "\";alert(/XSS/);";
一般来说,这里没有XSS漏洞,因为变量处于双引号之内,系统转义了双引号导致变量无法escape
。
但是百度返回的页面是GBK/GB2312
编码的,因此 "%c1\"
这两个字符组合在一起后,会变成一个Unicode字符。在Firefox下会被认为是一个字符。
所以构造: %c1";alert(/XSS/);";
。
这两个字节"%c1\"
组成一个新的Unicode字符,把转义符号\
给吃掉了,从而绕过了系统的安全检查。
绕过长度限制
产生XSS的地方会有变量的长度限制,这个限制可能是服务器端逻辑造成的。
绕过方法:
- 利用事件(event)来缩短需要的字节数。
- 把XSS Payload 写在别处,再通过简短的代码加载XSS Payload。
最常用的一个“藏代码”的地方,就是location.hash
。而且根据HTTP协议,location.hash
的内容不会在HTTP包中发送,所以服务器端的web日志并不会记录下 location.hash
的内容,从而更好隐藏黑客的真实意图。
构造一个地址: http://www.a.com/test.html#alert(1)
,对于直接输出的$var的html <input type="text" value="$var" />
,
可以构造一个注入:" onclick="eval(location.hash.substr(1))
,那么注入之后输出的html为: <input type="text" value="" onclick="eval(location.hash.substr(1))" />
。(因为location.hash的第一个字符是#
,所以必须先去除。)
使用<base>
标签
<base>
用于定义页面上所有使用“相对路径”的标签的hosting地址。<base>
标签可出现在页面的任何地方,并作用于位于该标签之后的所有标签。
攻击者如果在页面中插入了<base>
标签,就可以在远程服务器上伪造图片、链接或脚本,劫持当前页面中使用“相对路径”的标签。
如果用户能控制输入,则必然会产生XSS。
在标签选择上,应该使用白名单,避免使用黑名单。
XSS防御
XSS的本质是一种“HTML注入”,用户的数据被当作HTML代码的一部分来执行。
- 设置Cookie的
HttpOnly
属性,这个属性使浏览器禁止页面的JavaScript访问Cookie。 - 输入检查,输入检查的逻辑必须放在服务器端完成,主要检查用户输入的数据中是否包含特殊的字符,要根据具体语境进行处理。
- 输出检查,要对输出进行恰当的编码。
跨站点请求伪造(CSRF)
CRSF的全称的 Cross Size Request Forgery。
浏览器的Cookie策略
浏览器所持有的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,IE678,Safari浏览器禁止在<img>, <iframe>, <script>, <link>
等标签中发送,但Firefox2、3,Chrome,Opera则允许。
如果获取到Cookie就能进行CSRF,要特别留意不同浏览器的Cookie策略了。
P3P头的副作用
P3P Header,全称是The Plarform for Privacy Preferences。
如果网站返回给浏览器的HTTP头中包含P3P头,则在某种程度上来说,将允许浏览器发送第三方Cookie,在IE下即使是<iframe>, <script>
等标签也将不再拦截第三方Cookie的发送。
CSRF 防御
验证码
CSRF攻击的过程往往是在用户不知情的情况下构造了网络请求,验证码会强制用户必须与应用交互,才能完成最终的请求,因此通常情况下,验证码能够很好地防御CSRF攻击。
Referer Check
浏览器的Referer头一般用于告诉服务器链接是从哪个页面链接过来的,Referer Check在互联网中最常见的应用就是“防止图片盗链”。
常见的互联网应用,页面与页面之间都具有一定的逻辑关系,这就使每个正常请求的Referer具有一定的规律。通过Referer,可以判断一个请求有没有可能是CSRF。
Referer Check的缺陷在于服务器并非什么时候都能取到Referer。有的浏览器处于隐私考虑、从HTTPS跳转到HTTP等都不会发送Referer。
Anti CSRF Token
这是业界的一致做法,使用一个Token来防御CSRF。
CSRF的本质是重要操作的所有参数都是可以被攻击者猜测到的。
Anti CSRF Token 是足够随机的,为用户与服务器所共同持有,不能被第三者知晓。Token可以放在用户Session中,或者浏览器Cookie中。
Token需要同时放在表单和Session(或Cookie)中。在处理请求时,服务器只需验证表单中的Token与用户Session或Cookie中的Token是否一致,如果一致,则是合法的请求的,否则就是CSRF。
Token 使用原则
- 防御CSRF的Token是根据“不可预测性原则”设计的,所有Token的生成一定要足够随机,需要使用安全的随机数生成器来生成Token。
- 如果Token是放在Cookie中,可以考虑生成多个有效的Token,以解决多页面共存的场景。
- 使用Token时应该主要Token的保密性。
CSRF Token仅仅用于对抗CSRF攻击,当网站还同时存在XSS漏洞时,这个方案就会失效。CSRF的Token是建立XSS防御方案足够安全的基础上的。
点击劫持
HTML5 安全
欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。