WEB安全第十九课 浏览器的安全模型限制框架 |
尽管对同源策略的各种扩展设计很容易理解,但也往往功亏一篑。因为如果建议的修改不能应用到每个代码路径里,或者有某个特定的浏览器不支持,那就会回退到更严格的未经扩展过的处理逻辑上去。与仅仅做些安全扩展相比,要在现有浏览器安全模型之外创建全新的安全边界往往更危险。因为要支持新的策略,就必须调整每个与安全相关的代码路径,而且每种浏览器都要立刻支持新策略,否则难以预期会出现什么问题。
在这一章节,我们会速览一下目前比较有进展的一些尝试,这些尝试尽管颇有风险但长期而言可能收益更大——同时也会探讨它们的问题所在。 一.内容安全策略👵👠🪝😉💪 内容安全策略(Content Security Policy,CSP)是一套异常全面的安全框架,最早是由Mozilla的Brandon Steme在2008年提出。这套框架原本的目标是创建一个无所不包的机制,以消除常见Web漏洞如XSRF和XSS,并为网站管理者提供一系列与安全无关的内容策略设置工具。 在之后的岁月里,CSP迅速发展,在许多场景里它的使用范围有了巨大的变化(例如,作者迅速放弃了解决XSRF漏洞的想法,把这个事情转交给了还未获实现的Origin请求头)。 ✍🎠🌶🆚🐕 1.主要的CSP指令由Steme设计的CSP机制的核心,是让站点的所有者能针对单个页面设定它可以执行哪些动作,这些原本是同源策略的控制范围。例如,CSP可以限制某个页面不能加载除图片文件以外的任何外部子资源,但可以加载来自若干信任源的图片文件,例如: X-Content-Security-Policy:default-src'none';img-src http://*.example.com 👆🌕🥣♊🪶 显然在这个例子里,策略被编码在一个HTTP响应头里。根据W3C草案,也可以把它嵌入到文档里(使用<meta>标签)或由policy-uri设定的一个外部URL策略文件来设定。 对每项内容来源指令来说,源的数量不受限制,可以为完全限定形式的源或使用统配符形式来匹配多条的主机名、协议或端口。三个特殊关键字(none、self和data:)依次代表空集、策略所在页面对应的源或由完全内嵌的data:URL指向的策略文件。 🧑🚀🩲🪝😥🤛 到目前为止,CSP指令可以控制: ●脚本执行 使用script-src指令设置协议、主机名和端口的组合,以此设定允许调用哪些<script src=...>URL对应的JavaScript代码。正常来说,CSP不允许在页面里直接嵌入JavaScript脚本(无论是通过独立的<script>代码块还是通过事件处理器),或者当前脚本无意中把字符串传递给类似eval(...)、setTimeouU...)和setlnterval(...)这样的函数。因此script-src指令有助于限制XSS漏洞的影响:任何攻击者注入的代码,都只能加载那些在认可源上存放的脚本。 ●插件内容 由object-src指令控制插件对所在页面的访问权限。因为原本Java或者Flash这类插件,对其所在页面有不受限制的访问权限,这个指令的使用和script-srx非常类似,要获得安全的效果,就要相应地同时设置这两个指令。👨🚒👔🧪😄👀 ●样式表和字体 由style-src和font-src指令控制。与脚本的处理不同,CSP并未禁止在页面里使用内嵌式的<style>区块或style=“各种参数”的写法。因此,攻击者还是有可能极大地改变有漏洞页面的外观和功能(甚至带来更严重的问题),实际上这两条指令原本并非出于安全考虑的,唯一和安全相关的例外是可以限制混合内容的bug。就在本书出版之前,CSP规范刚做了修订,使它对CSS的处理变得更可靠。 ●静态的多媒体内容 如img-src或media-src这样的指令,控制页面是否可以内嵌来自特定源的多媒体内容。与CSS控制的原始设计类似,这并不算一项安全特性。例如,在某个XSS攻击的案例里,CSP无法阻止攻击者利用样式表在有漏洞的页面上画出任意形状的图案甚至能产生某些动画效果。 💪🚠🍍♊ ●子框架 frame-srx这个指令设定页面里任意<iframe>标签可以接受来自哪些目标站点的地址;但子框架内的页面不会继承父级页面的策略设置。要减少XSS的危害,此处也不能允许data:URL的格式。 ●默认策略 在W3C草案里这个设置名为default-src,而在Mozilla的文档里,是个更难懂的名字(allow),该指令的含义是,如果其他的指令都不适用于该内容,则应该回退到此默认策略。该指令是必须存在的,即使从理论上来说并不需要。 注意:CSP是针对每个独立的HTML标签设置对应的CSP指令,而不是按相似的功能来分组,这样的处理也许不算很理想。因为这样使得script-src、frame-src和object-src各个不同的设置之间的交互影响变得很难理解。而且,这种做法也不利于日后的保障:像一些已经出现的边缘类别的子资源(例如网站默认图标“favicons”)就被整个排除在CSP之外,而这种情况多半还会持续出现。👦🪖🛋😡👀 另外还有一个与前面提到的各种CSP子资源驱动模型都完全无关的特殊指令叫frame-ancestors。这个参数可用于设定当前页面能接受哪些父级页面,以消除点击劫持的风险,类似于更广为人知的X-Frame-Options响应头的做法。frame-ancestors的逻辑完全独立于default-srx和其他CSP指令之外;它的默认值为“*”。 2.对违反策略的处理 👦👙🪝😥🦷 根据设定的规则,CSP策略限定了其所在文档的行为方式。违反了这些规则通常会导致子资源无法加载,无法执行直接写在文档内的JavaScript脚本,或禁止某些页面的显示(这个特殊的例子就是什ame-ancestors)。 因为CSP控制了许多内容相关的行为,而且一旦违反规则,默认的处理也非常决绝,因此,CSP的作者们意识到需要减轻网站管理员的忧虑。为使CSP更加用户友好,同时可能还天真地想把它作为入侵检测的一种手段,CSP提供一个可选的功能,允许浏览器立刻向站点所有者报告策略违背事件。 可以通过策略里的report-uri关键字启用这种功能。为了进一步简化部署,还可以把全部或部分策略,转换成“柔和”模式,这样即使违反策略时,也仅是在HTTP里有个提示,而不会影响页面的加载。设置名为X-Content-Security-PolicyRepor-Only的响应头即可实现这一功能。 ✋🎠🍞®🐟 3.对CSP的批评 CSP的理念相当不错,而且设计得也非常有整体性,与浏览器里常见的东一榔头西一锤子胡乱添加的安全功能完全不同。但是,从它诞生伊始,这个建议就一直在反复设计当中,它的具体实现也令人关注。 👁🎢🍒♏🐞 对CSP最常见的抱怨和安全倒并无关系:为了拥有CSP框架提供的XSS防护效果,网站管理员必须把直接写在页面里的JavaScript代码(可能全站会有上百段此类代码)移到独立的脚本文件里;在新的CSP草案里,对样式表也有同样的要求。要改造现有页面会异常复杂,而另外要访问一个独立文件所带来的额外HTTP请求也代价高昂(这个问题也许可以通过最近CSP草案里提议的script-nonce扩展来解决)。 由于CSP的设计仍然是基于源这一级别进行保护,所以对它更深的忧虑是其规则集的粒度不够细,不能提供足够可靠的XSS防护。考虑到很多真实环境里的复杂网站都有数量众多、相对独立的Web应用,每个应用都可能包含数量众多彼此无关的静态脚本和JavaScriptAPI。如果攻击者企图利用受CSP保护站点里的XSS漏洞,确实无法直接执行恶意脚本,但通过在错误的上下文环境里加载同站点已有脚本或以非正常的顺序加载,也可能会使应用变得不统一或者进人危险的状态。 非Web形式的软件漏洞历史显示,这种破坏的情况往往会比想象中更严重。#363: 🤞🌧♻🦋 另一个更令人烦恼的问题是,攻击者可以加载一个实际上不是脚本但会被误认为是脚本的文件。这类的极端例子就是支持E4X的浏览器:攻击者可以在有效的XHTML文档里放置一条貌似无害的字符串,例如{alert("Hi mom!")},通过<script src=...>加载就可能导致代码的执行。意识到这些问题后,开发者们决定,通过CSP加载的任何脚本,其Content-Type值都需要是符合要求的,但即使这样,有时候还是防不胜防。 要理解问题可能会出在哪里,请看以下这个很常见的公开JSONPAPI处理,它由客户端在参数里设定回调函数的名称: 👩✈️👒🩺😍👆 GET /store_locator_api.cgi?zip=90210&callback=myResultParser HTTP/1.0 ... HTTP/1.0 200OK Content-Type:application/x-javascript ...👨⚕️👠📬😷👎 myResultParser({"store_name":"Spacely Space Sprockets","street":...}); 攻击者可以利用这个功能,使这个API调用CSP认可的源里任何客户端代码中的函数,还有可能连参数也会被攻击者控制。而如果callback的值并不限定于字母数字(也确实没必要这么限定吧?),指定回调为callback=alert(l);//就会导致直接的代码注入。 除了粒度控制的问题,由于缺乏侧重点,所以常令人困惑而且有危害性,这类对CSP较为温和的批评倒也有道理。一方面,通过包含类似frame-descendants和sandbox这样的指令,它貌似要创建一套独立而统一的浏览器安全框架——但除了含糊地提到Origin头之外,又出人意料地不再考虑解决XSRF漏洞,且没有提供什么额外的有价值的方案。而另一方面,这个提案经常被当作“内容策略”使用,并未过多地考虑强壮性问题,也未在安全属性上有更敏锐的想法。一旦考虑不周,还是会轻易创建出危险的脚本策略,再配合在样式表和图片策略上的匮乏,就是这种倾向的贻害。🧑🌾💍🧻🤤👊 #f465: 二.沙盒框架 沙盒框架(Sandboxed frame)是对常规<iframe>表现彳了为的扩展。它能让顶级页面对其嵌入的子页面以及这些子页面的子资源设置一些额外的限制。目标是让在某些敏感站点上的网站应用能更安全地嵌入某些可能不安全不受信任的广告页、组件页面或预格式的HTML文档。AdamBarth推动了这个设计的修正,以及它在WebKit里的初始实现(这也是到目前为止唯一支持这一机制的引擎)。 🤳🗺🥣®🐒 注意:令人好奇的是,沙盒框架并非一个全新的创意:在将近10年前微软就有类似的提议。从IE6开始就支持一个微软专有的security=restricted参数,它会强制目标框架里的页面按“受限区域”的权限打开,有效地阻止了执行其他位置脚本或跳转到其他页面等操作。然而,大家最多也就是用这个功能来规避一下某些客户端的JavaScript安全机制(最著名的如anticlickjacking检查)。我们很快就能知道接班的HTML5是否能做得更好些。 沙盒框架的设计相当简单:通过给<iframe>标签设置恰当的沙盒参数,就能把该页面里包含的某个框架限制为沙盒运行模式。默认情况下,受到限制的文件不能执行脚本和某些类型的页面跳转。当然可以通过空格分隔的若干关键字来设定sandbox参数的值,进一步设置具体的权限: 🤌🚗🥄💲🦌 Allow-scripts 如果没有这项关键字,在指定框架里的文件就无法执行JavaScript代码。这项功能的主要目的是防止嵌人的文档执行DoS攻击、打开浏览器级别的对话框或发起复杂的自动执行功能。Allow-forms 如果没有这项关键字,将无法使用嵌在文件里的任何HTML表单。这个机制用于防范在框架里的内容利用自己能显示在受信任页面内部之便,对敏感信息进行钓鱼(请注意,如果启用了allow-scripts,那是否禁用allow-forms也没有多大意义了。因为脚本可以轻易地构造出类似表单的控件,自动把收集到信息转发给其他站点而无需使用<form>标签。) Allow-top-navigation 这个关键字使被嵌人页面能重新操控顶级窗口的地址跳转。这种跳转通常是在同源策略里才有的例外情况,如果这种跳转被滥用,用户可能就无法和原站点进行交互或有可能被实施钓鱼攻击。 👨🦱🛍💰😛🤛 Allow-same-origin 没有这个标记的话,在沙盒框架里的内容会被指派一个独一无二的随机选择的合成源。这样页面就无法访问任何涉及源的内容了,哪怕是原本与它同源的脚本也无法执行。如果加上allow-same-origin,就会去掉合成源,得以访问同源数据了。 1.脚本、表单和跳转 🧑🚀🧢📡🙃✌ 沙盒框架里的前3项限制——脚本、表单和跳转,都很符合常识,可以放心使用。但它们的价值只有在使用sandbox属性的同时也禁用所有的插件才能发挥作用,因为类似Flash或者java这样的框架并不接受这种沙盒扩展,使得嵌入的插件可以绕过浏览器里这种新增的检查。但遗憾的是,沙盒框架里最常见的用户案例——嵌人式广告、视频和游戏,都极度依赖于Flash,因此会使得该安全机制没有它原先预想的那么管用。 2.合成源 在上述列表里的最后一项合成源(Synthetic origin)机制就更有问题和容易误导了。这个机制原本的用意,是既能显示一些不受信任的文档(如以Webmail方式收到的HTML格式邮件),但又不能让这些非信任的页面访问到敏感数据。 🤌⛴🌰♀🦚 不幸的是,合成源带来的问题还多过它能解决的问题。其中之一是,如果嵌人的文件URL是可预测的,攻击者就有可能直接在新的浏览器窗口里打开该页面,这样浏览器就完全没有机会用到sandbox这个属性的了. 为了解决这一问题,规范的作者逐渐提出,对理应受到沙盒框架约束的页面要使用一种特殊的MIME类型(text/html-sandboxed)。他们认为浏览器通常不会识别这种MIME类型,也就不会直接显示这个页面,所以在ciframe>的代码里就可以把它当作一种特例情况来处理。当然我们知道,这种防范也并不恰当,因为某些浏览器和插件会把插件响应默认按text/html类型直接显示出来,或把返回的数据作为其他的数据解析(如crossdomain.xml),这样也会引起麻烦。 👌⛄🍚❗ 由于在典型的浏览器里,同源或同域级别的安全机制也是有各种断裂,所以合成源的概念也非常有问题。例如一个可能带来危险交互的地方:密码管理器,就必须明确禁止对沙盒里的文档使用自动登录表单填充功能。另外,必须对特殊的登录增加安全提示,如登录操作是和地理位置API相关的时候。 在经过若干尝试和碰壁之后,按头痛医头脚痛医脚的办法,现在WebKit里的实现已经解决了许多问题。也就是说,未来的实现还是有可能再次落进相似的陷阱里,特别是HTML5规范认为这些功能都不在考虑范围内,对它们完全没有做任何要求。 注意:不用合成源也是会带来麻烦:如果用户点击了在沙盒框架中广告页面上的同站点链接,这个链接再打开一个新的窗口,浏览器需要阻止新窗口里的脚本能够遍历之前所有的opener对象,因为该新页面的父级页面本身其实并不能执行这个操作。👨🦱🧥⚔😛👃 #f467: 三.严格传输安全 👀🚈🍟🚷🦉 HTTPS设计中最重要的一个弱点就是,用户往往是先在地址栏里输人不带协议名称的URL(例如输入bankofamerica.com而不是完整的 ) ,浏览器就会先假设这是HTTP,然后发起一个明文的HTTP请求。即使站点立刻把访问重定向到HTTPS,但与受害者在同一网络上的主动攻击型攻击者也许就能拦截和篡改最初返回的响应,使得用户无法升级到安全的协议。这种情况下,用户很容易忽略掉浏览器界面上缺少了那个不起眼的加密锁符号标识。 这个问题,还有其他几个与混合内容和Cookie范围有关的周边影响,促使Jeff Hodges和其他几位研究员起草了HTTP Strict Transport Security的草案(严格传输安全,Scrict Transport Security,HSTS或STS)。他们的做法(目前WebKit和Firefox都支持)允许任何互联网上的站点告诉浏览器,对某个特定主机名或域名的所有请求,都必须使用HTTPS,任何HTTP流量都应该自动升级并只能以HTTPS协议传输。 HSTS的设计思路是,用户和特定域名的初次交互,应该还不会遭受到有效攻击——但随着时间的增加,例如用户利用开放的无线网络上网时,碰到攻击者的几率就大大增加了。因此HSTS不算一个完美的防护,但在实际使用中已经足够了。 🏫🌶❗🐺 作为可选项的HSTS以HTTPS响应头的形式出现,类似这样: Strict-Transport-Security:max-age=3000000; includeSubDomains ✌🎠🔪©🐅 注意:要使HSTS提供有效的保护,max-age(STS记录存储在浏览器里的有效时间)必须设置得比用户前后两次访问同一站点的间隔时间要长得多。但如果在此期间HTTPS站点出现了问题,会导致没有办法禁用或覆盖HTSTS设置,所以网站管理员多半会选择设置一个比较小的数字,这样一旦他们搞砸了事情的时候,用户还可以回退访问HTTP站点。还不清楚网站开发人员是否能针对这种关注点的差异,做出较为优化的选择。 这一设计的负面安全问题算是相当不起眼了:就是可能会略微提升DoS攻击的风险,因为攻击者可以在不支持HTTPS的站点的里也插人这个响应头。另外还有可能通过几个假造的主机名配合HSTS的设置得到独一无二的组合,用于标记一个特定的浏览器实例,获得除了Cookie之外的又一种用户追踪方式。但这些问题都不算特别突出了。 但是,和其他章节讨论的增加限制的安全框架一样,这个机制在原理上来说的确不错,但很难完全说得清楚它和其他旧有代码之间的交互会带来什么问题。特别是,除非使用了includeSubDomains标识,HSTS对HTTPCookie的保护远比预期的低:只要捏造一个不存在的二级域名,通过发往这个域名的请求(尽管不能读取,但即使是设置为安全的Cookie也可以通过类似的做法被覆盖和改掉),就可以很轻巧地截获没有标记为secure的Cookie。 🤌🌡🍪❗🐕 类似地,对插件返回的内容强制HSTS也没什么效果。#362: #f464: 四.隐私浏览模式 🧑💻👓🪟😋🤟 隐私浏览(Private Browsing),通俗来说也就是“色情浏览模式”这是个大部分最新浏览器都支持的一个非标准功能。它的原意是创建一个非持久的浏览沙盒,与主浏览器的会话隔离开来,当关闭最后一个隐私浏览窗口时,这个状态里的所有信息就会全部被清空。 在某种意义上来说,这种机制可以看作在现有的浏览器安全范式之上的一种内容隔离机制,当然也值得在这里简短地介绍一下。 🤟🌕🍒♏ 除了Chrome之外,其他大部分浏览器厂商都没有准确说明隐私浏览模式有什么安全保障。遗憾的是,按直觉来理解这个名词与浏览器实际上怎么处理还是有不小的差距。 无疑对这个功能最直观的理解是,在隐私浏览会话期间应该是完全匿名的,用户行为的任何数据都不会保留在系统里。但由于网络堆栈固有的局限,以及现代操作系统的内存管理机制,已经部分不满足这两条假设。但即使只说浏览器本身,要实现较为理想的匿名浏览也几乎不可能。 几乎每种和状态有关的浏览器机制,从地理位置定位和弹出窗口允许,到严格传输安全、表单自动完成乃至基于插件的持久数据存储,都必须全部进行修改,要明确区分两种浏览模式,对每个厂商来说都是难以企及的目标。 👎🛩🥣☪🐴 可能更令人抓狂的是,即使匿名浏览,仍然可以通过脚本检查浏览器的特征,例如安装的插件集合、字体、屏幕分辨率、窗口大小、时钟误差,甚至加密安全性不足够的PRNG(伪随机数发生器),都可以独一无二地锁定任意目标。 所以和隐私浏览模式原本的目标颇有距离,它只适合防止对使用同一台机器的其他非技术用户的常规数据泄露,但即使这个目标也不并容易达到。 🧒👚🧻😪👌
帖子热度 1.1万 ℃
小执念在论坛发帖时没有注意,被小偷偷去了 1 个 金币.
|
|
对于作为社会主义的打好男人,我你这样做对得起社会,对得起人民吗?我只想说4个字:请带上我!#379:
|