您的位置:首页 > Web前端 > HTML5

安全机制

2016-07-20 00:10 447 查看
安全机制包括两个不同的部分,第一是网页的安全,包括但是不限于网页数据安全传输、跨域访问、用户数据安全等,第二部分是游览器的安全,具体是指网页或者JavaScript代码有一些安全问题或者存在安全漏洞,游览器也能够在运行它们的时候保证自身的安全,不受攻击从而泄漏数据或者使系统破坏

网页安全模型

安全模型基础

当用户访问网页的时候,游览器需要确保该网页中数据的安全性,如Cookie、用户名和密码等信息不会被其他的恶意网页所获取。



它表示的是网页所在的域名、传输协议和端口等信息,域是表明网页身份的重要标识,如网页“http://blog.csdn.net/steward2011”,它的域是”http://blog.csdn.net“,其中”http:”是协议,”blog.csdn.net”是域名,而端口默认为80,用户可以打开chrome游览器的开发者工具和控制台,输入”window.location”查看域的各种信息。根据安全模型的定义,不同域中网页间的资源访问是收到严格限制的,也就是网页的DOM对象、个人数据、XMLHttpRequest等需要收到控制,默认情况下,不同网页间的这些数据是被游览器隔离的,不能互相访问,这是HTML的“Same origin Policy”策略。

XSS

XSS全称Cross Site Scripting,其含义是执行跨域的JavaScript脚本代码,执行脚本本身没什么问题,但由于执行其他域的脚本代码可能存在严重的危害,还有可能会盗取当前域中的各种数据,因此HTML5规范之前,跨域的资源共享是不被允许的,这样做会造成功能上的缺陷,为此标准组织和WebKit使用了大量的技术来避免各种攻击的发生,例如在HTTP消息头中定义了一个名为“X-XSS_Protection”的字段,此时游览器会打开防止XSS攻击的过滤器,目前主要的游览器都支持该技术。

CSP

Content Security Policy是一种防止XSS攻击的技术,它使用HTTP消息头来指定网站能够标注哪些域中的哪些类型的资源被允许加载在该域的网页中,包括JavaScript、CSS、HTML Frames、字体、图片和嵌入对象(如插件、Java Applet等),在HTTP消息头中,可以使用相应的字段来控制这些域和资源的访问,其主要是服务器返回的HTTP消息头,目前不同游览器中使用不同的字段名来表示,主要包含三种名称:Content-Security-Policy(由标准组织定义)、X-WebKit-CSP(实验性的字段名)和X-Content-Security-Policy(Firefox使用),该字段的定义格式如下(字段名:指令名 指令值;指令名 指令值;….. )。下表是包含一个字段名及一系列的“指令名+指令值”对的列表,其包括11种类型的指令来控制网页中的各种资源和安全行为:

指令名含义
default-src控制所有的资源,如果已经包含该指定资源的指令,那么default-src优先级较低,如果没有包含该知道的指令,那么使用default-src指令定义的内容
script-src用于控制JavaScript代码
stype-src用于控制CSS样式表
img-src用于控制图片资源
connect-src用于控制XMLHttpRequest、WebSocket等同连接相关
font-src用于控制字体资源
object-src用于控制“embed”、“object”、“applet”等元素加载的资源
media-src用于控制多媒体资源,包括音频和视频
frame-src用于控制可以加载的框
sandbox用于控制网页中是否允许弹出对话框,插件和脚本的执行等,值可能是”allow-forms”、”allow-same-origin”、”allow-script”、”allow-to-navigation”
report-uri将错误消息发送到指定的URI
CORS

根据“Same Origin Policy”原则,游览器做了很多的限制以组织跨域的访问,所以跨域的资源共享又变成了一个问题,标准组织为了适应现实的需要,zhi’ding 额CORS(Cross Origin Resource Sharing)规范,也就是跨域资源共享,该规范借助域HTTP消息头并通过定义一些字段来实现,主要是定义不同域之间交互数据的方式,当某个网页希望访问其他域资源的时候,需要按照CORS定义的标准从一个域访问另外一个域的数据。CORS使用HTTP头来描述规范定义的内容,HTTP消息头是指包含有限个字段(如Accept、Accept-language等)并请求类型只是HEAD、GET和POST。通常简单的HTTP消息头只需要较小的代价,而包含了CORS的消息头却不是简单的HTTP消息头,该消息请求在CORS里面被称为“Preflight”消息请求,CORS使用到的字段如下表:

字段名类型含义
Origin请求端请求端申明该请求来源于哪个域
Access-Control-Request-Method请求端请求端的HTTP请求类型,如PUT、GET、HEAD等
Access-Control-Request-Headers请求端一个以“,”为分隔符的列表,表项是自定义请求的字段
Access-Control-Allow-Origin响应端表明响应端允许的域,可以指定特定的域,也可以使用“*”表示允许所有的域请求
Access-Control-Allow-Credentials响应端默认情况Cookie之类的信息是不能共享的,但如果设置该字段为真,那么Cookit是可以传输给请求端的
Access-Control-Expose-Headers响应端是否暴露回复消息给XHR,以便XHR能够读取响应消息的内容
Access-Control-Max-Age响应端Prelight请求的有效时间
Access-Control-Allow-Methods响应端响应端 允许的HTTP请求类型,如前面的PUT、GET、HEAD等
Access-Control-Allow-Headers响应端响应端支持的自定义字段
其类型可以分成请求段和相应端,如果每个HTTP消息头都要包含这些字段那是一种浪费,因为没有必要每个HTTP消息头都重复包含这些类型,为了就会使用到“Preflight”请求来发送包含CORS字段的消息,而其他则是简单的HTTP消息头,表中Access-Control-Max-Age表示Prefight请求的有效期,在有效期内不需要重复发送CORS定义字段的消息,CORS和CSP的区别在于CSP定义的是网页自身能够访问的某些域和资源,而CORS定义的是一个网页如何才能访问被同源策略禁止的跨域资源,规定了两者交互的协议和方式。

Cross Document Messaging

Cross Document Messaging定义的是通过window.postMessage接口让JavaScript在不同域的文档中传递消息成为可能,以下代码演示了如何使用该技术来传递消息:

http://csdn.com中JavaScript代码
contentWin.postMessage('Hello','http://blog.csdn.net');
 http://blog.csdn.net/steward网页中的JavaScript代码 window.addEventListener('message',function receiver(e)) {
if (e.origin == 'http://myweb.com') {
if (e.data == 'Hello') {
e.source.postMessage('Hello2', e.origin);
} else {
alert(e.data);
}
}
}, false);


该机制使用“window”对象的postMessage方法来传递给其他域网页消息,该方法包含两个参数,第一个是消息内容,第二个是需要对方的域消息,而在接收方,开发者在JavaScript代码中注册一个消息响应函数,如果检测出消息来源于上述“http://csdn.com”,那么就回复一个“Hello2”的消息。

安全传输协议

对于用户而言,网页的安全还包含一个重要点,就是用户和服务器之间交互数据的安全性问题,对于一般的网页而言,这些数据的传输都是使用明文方式,也就是说它们对谁都是可见的,这能够满足大多数的使用情况,但是对于隐私的数据,如密码、银行帐号等,如果使用明文来传输就存在风险,为此Web引入了安全的数据传输协议HTTPS,HTTPS是在HTTP协议之上使用SSL(Secure Socket Layer)技术来对传输的数据进行加密,从而保证了数据的安全性,SSL协议是构建在TCP协议之上、应用层协议HTTP之下的,SSL工作的主要流程是先进行服务器认证,然后是用户认证,SSL协议主要是服务提供商对用户信息保密的承诺,这有利于提供商而不利于消费者,同时SSL还存在一些问题,例如只能提供交易中客户域服务器间的双方认证,在涉及多方的电子交易中,SSL协议并不能协调各方的安全传输和信任关系。TLS(Transport Layer Security)是在SSL3.0基础上发展起来的,它使用了新的加密算法,因此同HTTPS之间不兼容,TLS用于两个通信应用程序之间,提供保密性和数据完整性,该协议是由两层子协议组成的,包括TLS记录协议(TLS Record)和TLS握手协议(TLS Handshake),较低的层为TLS记录协议,位于TCP协议之上,TLS握手协议具有三个属性,其一是可以使用非对称的密码术来认证对等方的身份,其二是共享加密密钥的协商是安全的,对偷窃者来说协商加密是难以获得的,此外经过认证的连接不能获取加密,即使是进入连接中间的攻击者也不能,其三是协商是可靠的,如果没有经过通信方成员的检测,任何攻击者都不能修改通信协商。TLS独立于高层协议,如HTTP协议,高层协议如HTTP协议可以透明的分布在TLS协议上面,然而,TLS标准并没有规定应用程序如何在TLS上增加安全性,它把如何启动TLS握手协议及如何解释交换的认证证书的决定权留给协议的设计者和实施者来判断。

WebKit的实现

首先看WebKit为了防止XSS攻击所做的工作,下图是WebKit中启动XSS过滤功能所使用的相关基础设施,为了防止XSS攻击,需要在解释HTML的过程中进行XSS过滤,也就是对词法分析器分析之后的词语(Token)进行过滤,以发现潜在的问题:



基本工作是这样,在HTMLDocumentParser类揭示出一个词语之后,如果需要进行XSS过滤功能,则每一个词语使用HTMLDocumentParser类的XSSAuditor对象来进行过滤,也就是图中的XSSAudior::filterToken函数,对于每一个词语,该函数进行过滤并生成相应的结果XSSInfo对象,该对象包含是否需要阻止整个页面渲染等信息,XSSAuditor不做决定,而是由HTMLDocumentParser将这些信息交给XSSAuditorDelegate类来处理,在根据这些信息来生成报告,XSSAuditorDelegate将结果报告发送给“report-uri”,XSS有很多种攻击的类型,这里主要包括对于元素开始和结束及其属性的检查,同时对于一些特定类型的词语进行过滤,包括input、form、button、iframe、script等,当发现潜在危险的时候再生成相应的结果信息此处为XSSInfo对象。其次是CSP方面的支持,下图是WebKit支持CSP所定义的相关基础设施,同时包括Origin的定义,其中对于CSP支持的主要部分是ContentSecurityPolicy和SecurityContext这两个类:



ContentSecurityPolicy:主要包括对于规范中定义的各个字段的解释和解释后内容的保存,如图中的didReceiveHeader函数就是处理服务器端的HTTP消息头,该类将指令和指令的内容保存在”m_policies”中,形成一个列表

SecurityContext:支持安全机制的上下文类,包含Origin对象和ContentSecurityPolicy对象,其他对CSP等的调用都是通过该类来获取的

图中最下部分为两个类WebSecurityOrigin和WebSecurityPolicy,这是WebKit的Chromium移植定义的两个接口,可以被Chromium调用,它们都有内部的实现,具体分别是SecurityOrigin和SecurityPolicy,SecurityOrigin就是规范中对于Origin的定义,而SecurityPolicy就是对CSP策略的定义,通过WebSecurityPolicy接口,Chromium可以自定义一些策略并设置到WebKit中。Document类间接继承了SecurityContext,由此Document也继承了CSP的设置,因为Document会在各处都使用,这样方便调用CSP的功能,DOMSecurityPolicy为了将CSP的信息暴露到JavaScript中,这样JavaScript代码可以获取CSP定义的内容,如“script-src”指令所定义的允许访问的域,ResourceFetcher是获取资源的类,根据CSP的定义,对于各种类型的资源,在获取之间都需要检查该资源是否在CSP定义的允许范围内,如果不在,则拒绝请求,并报告错误,如果在,则发起请求,该请求需要依赖SecurityPolicy提供的一些信息。最后是CORS的支持,下图是WebKit支持CORS所涉及的一些类,其中最主要的是CrossOriginAccesControl部分,它不是一个类,里面只是包含了一组全局函数,用来帮助生成符合CORS规范的“Preflight”请求或者其他简单请求,同时包括处理来自回复端的消息,在WebKit使用WebURLLoader请求的时候,使用这些方法能够生成相应的请求:



沙箱模型

原理

一般而言,对于网络上的网页中的JavaScript代码和插件是不受信的,特别是一些故意设计侵入游览器运行的主机代码更是危险,通过一些手段或者游览器中的漏洞,这些代码可能获取了主机的管理权限,这对主机系统来说十分危险,所以除了保证网页本身之外,还需要保证游览器和游览器所在的系统不存在危险。对于网络上的网页,游览器认为它们是不安全的,因为网页总是存在各种可能性,也许是无意或有意的攻击,如果有一种机制,将网页的运行限制在一个特定的环境中,也就是一个沙箱中,使它只能访问有限的功能,那么即使网页工作的渲染引擎被攻击,它也不能够获取渲染引擎工作的主机系统中的任何权限,这就是沙箱模型的思想。Chromium是以多进程为基础的,网页的渲染在一个独立的Renderer进程中,这位实现沙箱模型提供了基础,因为可以相对容易的使用一些技术将整个网页的渲染过程放在一个受限的进程中来完成,如下图所示,受限的环境只能被某些或者很少的系统调用而且不能直接访问用户数据,沙箱模型工作的基本单位就是进程。



Chromium的沙箱模型是利用系统提供的安全技术,让网页在执行过程中不会修改操作系统或者是访问系统中的隐私数据,而需要访问系统资源或者说是系统调用的时候,通过一个代理机制来完成。

实现机制

由于沙箱模型依赖操作系统提供的技术,而不同操作系统提供的安全技术是不一样的,这意味着不同操作系统上的实现是不一致的,需要分别针对不同平台来讨论,但是不管是Linux还是Windows,或者是其他平台,Chromium都是在进程的力度下来实现沙箱模型,也就是说需要运行在沙箱下的操作都是一个单独的进程:



图中右侧是目标进程,也就是需要在沙箱中运行的代码,左侧是代理进程,它需要负责创建目标进程并为目标进程设置各种安全策略,同时建立IPC连接,接受目标进程的各种请求,因为目标进程是不能访问过多资源的。

Linux

在Linux上,沙箱模型分成两个层,第一层是阻止某个或者某些进程通常能够访问的资源,chromium中称为“语义层,这里使用的系统技术主要是“setuid“,第二层是防止进程访问能够攻击内核的接口或者供给面,这里使用的系统技术主要是”Seccomp”,在沙箱机制启动之后,如果运行Chromium程序,会产生下面的进程层次结构,它是一棵树,树的根节点是“browser“进程,该进程启动后,会孵化多个子进程,包括”GPU“、”chrome_sandbox“等进程,而对于沙箱模型来说,这里关注”chrome_sandbox“进程,它的目的主要是使用”setuid“技术来实现模型的第一层,生成了”zygote“子进程,其中”chrome_sandbox“进程使用的是上面介绍的目标”chrome_sanbox”生成的二进制可执行文件,而其它的是目标”chrome“生成的结果,二者是不一样的。



生成第一个”zygote“之后,该进程会生成两个子进程,第一个是”nacl-helper“进程,是为了支持NaCl插件进程服务的,第二个又是一个”zygote“,这个不同于它的父亲,主要是为了生成各种”Renderer“进程服务,这样每个”Renderer“进程经过上面的过程后都会使用沙箱机制进行处理,网页在”Renderer“中的运行就收到了限制,Renderer进程域代理进程通过进程间通信机制来交互,所有的请求都是发送给代理进程,代理进程将结果返回给Renderer进程,这里的代理进程就是Browser进程,Browser进程拥有访问这些资源和系统调用的权限。其中第一层主要使用两种技术:

使用setuid来为新进程设置新用户ID和组ID,根据Linux的规定,两个不同用户ID之间的数据是隔离开的,这将Renderer进程同Browser进程分开,后者拥有访问很多关键数据的能力,如各个网页的Cookie,在现在的Chromium实现中,不再使用setuid来实现,而是使用CLONE_NEWPID标记,该标记是在Linux系统调用clone时设置,从而为新进程创建一个新的名空间,也就是上面描述的文件系统等

显示网络访问,Chromium使用标记”CLONE_NEWNET“设置在调用”clone“系统调用的参数中,使用这这些技术之后克隆出来的进程就同父进程分离开来,包括新文件系统等和限制网络的访问等

第二层使用的主要技术是Seccomp和Seccomp-BPF,seccomp是Linux内核提供的一种简单的沙箱机制,它能够允许进程进入一种不可逆的安全状态,进入该状态的进程只能够调用4个系统调用,包括exit、sigreturn、read和write,而且最后两个系统调用只能操作已经打开的文件描述符,如果该进程尝试调用其他的系统调用,那么内核会通过SIGKILL信号来杀死该进程,进入该按去哪状态的方法就是使用系统调用prctl社会自标记位PR_SET_SECCOMP就可以了,前提是系统的内核在编译的时候就加入了对Seccomp的支持,因为不是所有使用Linux内核的操作系统都能打开该机制,Seccomp-BPF是Seccomp及时的一个扩展,它允许使用BPF所定义的方法来将系统调用转变成BPF格式的小程序,BPF(Berkeley Packet Filter)原是Berkeley开发的一种用来过滤网络包的技术,现在被应用在Seccomp,Seccomp-BPF将系统调用转变成BPF格式的小程序,这些小程序能够被内核所解释,这样每个系统调用的次数和参数都能够被重新评估或者被限制。对于开发者来说,如果想要关闭第二层的沙箱技术只需在命令行韩总加入参数”–disable-seccomp-filter-sandbox“就可以了,对于Android系统来讲,虽然Android是基于Linux内核开发出来的,但还是有些区别,目前沙箱机制的第二层在Android上并没有得到支持,只是第一层得到了支持,但是在Android上,系统支持的安全机制都已经在Chrome的Android版本上得到了启动,主要体现在两个方面,第一是SUID,Android系统上稍微不同,它是UID isolation(UID隔离技术),Android可以为每一个进程设置一个新的UID,这些每个进程之间就不能随意修改和访问数据,这是由Linux内核机制来保证的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息