浅析浏览器安全

2019-06-04 17,583

在一次与朋友的聊天中,朋友问我对浏览器安全是否有了解。我的第一反应就是没有了解过~做了这么多年安全,好像从来没有去思考过浏览器在安全方面的问题。

朋友再次提醒,你做过的web网站渗透,不都是通过浏览器去访问的么,它的URL、它的协议、它的同源策略、它的DNS请求、从用户发起请求的第一步到浏览器web页面的展示……恍然大悟~

安全的范围很广,为了完成工作要求我们总是在零零散散的学习,很多时候我们并没有一个系统性的思维,甚至我们每天都在接触的东西突然有一天被人问到时都不知道自己原来和它如此熟悉。直到有人提醒,我们才恍然大悟的说道:哦哦,这样啊,我知道的~~

这就是为什么我无论学什么都习惯性的总结成文章,侯亮大神说:知识的最高的境界是分享,而在我看来,我们在分享的同时也是对自我认知的一个提升。

有幸在安全脉搏得于此书《白帽子讲浏览器安全》,此书根据作者若干年实战与工作积累的丰富经验编写而成,深入地分析了浏览器从导航到页面展示的整个过程中可能会出现的安全问题,也对浏览器的部分实现细节有着详细和深入的介绍,对安全工作者有一定的参考意义。下面是本人所学所得总结如下。


随着WEB2.0的时代来临,互联网从C/S架构(客服端/服务端结构)转变为B/S架构(浏览器/服务器结构),后者相比于前者更加方便快捷,因此浏览器便成为了我们访问网站的窗口,浏览器安全也随之变得越来越重要。

作为用户与网络交互的最主要的一种平台,浏览器也日渐成为了网络攻击的目标,猖獗的地下0day交易,以及简单、流程化的木马生成与发布程序都让浏览器安全问题影响变得广泛。

为了应对攻击,浏览器也增添了许多安全特性。(1)各浏览器都纷纷开启了数据执行保护(DEP)和(2)地址空间分布随机化(ASLR)。同时,为了降低恶意代码运行时的权限,浏览器也在试图(3)降低浏览器网页进程的权限,例如(3.1)IE的保护模式和Chrome的沙箱。

为了防止用户受到脚本注入的困扰,(4)IE和Chrome也各自添加了XSS过滤器。为了防止用户受到钓鱼网站或者恶意网站的干扰,(5)浏览器也添加了形如SmartScreen Filter、恶意网站拦截的功能。同时,浏览器也在兼容新的安全特性,(6)例如DNT(不要追踪、Do Not Track)和(7)防止点击劫持的HTTP头、(8)CSP安全策略等。可以看的出来,浏览器在提升安全性上十分努力。

 

下面详述浏览器中常见的安全概念

1 URL

网址大家都不陌生,全称是“统一资源定位符”。URL浏览器是开始导航过程的第一步,URL安全也是浏览器安全的第一步。

在URL的解析库、编码、字符排版、UI显示、内容劫持等方面均出现过安全问题。

曾经的霸主IE6,在早期微软的想法比较超前,它推崇的正式当今互联网中热门的Web APP概念,即基于网页的应用程序。为了能达到和原生程序类似的效果,早期IE6支持网页脚本创建一个没有任何边框的新窗口。这个想法如果放在EXE程序中是没有任何问题的,因为对EXE来说,一个程序就是一个独立的个体,不依赖于其他框架。

但是在网页中,这显然引发了一些混乱。恶意网页可以自己绘制出一个假的IE界面,当然也包含网页的“名片”—地址栏。由于大量的弹窗广告和钓鱼网站绘制假的界面谎称自己是合法网站,不堪其扰的微软决定从XP SP2开始强制IE显示边框。对IE来说这是一个正确的决定,因为浏览器是一个展现信息的工具,因此用户看到的内容也可能是一个攻击点。

在边框问题之后,又有安全研究员报告了另一种问题—IE的地址栏中超长字符以及扩展字符处理的逻辑有问题,浏览器可能显示不出特定字符。这样,攻击者可以注册一个含特殊字符的域名,并利用浏览器显示文字的漏洞将其伪装成正常域名。或是使用大量空格,将一级域名顶出地址栏的显示范围外,让人误以为自己访问的是合法网站

http://www.xxx.com.evil.com
http://www.xxx.com              .evil.com             [许多空格]
http://www.xxx.com.          ….evil.com

地址栏中http://www.xxx.com.evil.com许多空格的错误和正确的显示方式

这些攻击案例零零散散有过报告,直到浏览器市场百花齐放时,更多与URL相关的漏洞才暴露出来,这里面有很多是通用型漏洞,例如地址栏、解析逻辑的处理中可能导致的缓冲区溢出、程序崩溃、执行恶意程序等,这些都威胁着浏览器的信息安全。

1.1 URL的“可视化”问题—字形欺骗钓鱼攻击

作为网站身份的标志,URL最常用的场景应用是被用户的眼睛看到。因此,攻击者引入了一种新的攻击方式—字形欺骗攻击。如果攻击者试图使用0、o、1、i之类的类似型字符进行攻击,可能会在网址的外观上产生一定的欺骗性。

在XP诞生之初,网络发展正盛,宋体和Times New Roman占据了大量桌面系统的UI,字母1和数字i的区分不是很强烈,乍一眼经常看错。因此,许多木马为了防止用户看出蹊跷,都以exl1orer.exe、svch0st.exe的名称运行。不久,在互联网上出现了许多字形攻击。

Apple—app1e        Apple—app1e          Apple—app1e
Time New Roman            微软雅黑                     宋体

为了解决这个问题,操作系统的字体和排版也进行一些微调,例如一些常用字体上数字1和字母i的区分越来越明显了,而且数字1出现在字母中时,两边的空隙也更大。

用长的像的数字去替换字母的方式相对过时,普通用户也有一定分辨的能力,攻击者肯定得找到更优的“解决方案”来实施攻击。结合URL支持国际化域名的“新功能”,攻击者提出了字形欺骗攻击的现代版本—国际化域名字形欺骗攻击。

1.2 国际化域名字形欺骗攻击

  国际化域名字形欺骗攻击是指利用一些语系字母外形和英文字母外形几乎一样的特性,从而欺骗受害者的视觉判读的攻击形式。例如常见的字母“O”就有许多编码不同,但是外观一样的“兄弟”。O的欺骗性比之前所说数字1的例子强的多,在许多字体中各种“O”都呈现出完全一样的外观。

语系/符号

字形

UNICODE+

西里尔字母

Oo

041E/043E

希腊字母

Oo

039F/03BF

亚美尼亚字母

Oo

0555/0585

腓尼基字母

Oo

1090F/1091F

这不是个例,许多西方字母,比如西里尔字母a和英文字母a显示起来就是几乎一样的。如果攻击者注册一个混杂有西里尔字母的域名的“alipay.com”并发送给受害者,对方仅凭肉眼识别的话很有可能会受骗。在常用额“微软雅黑”等字体中,西里尔字母a和英文字母a并无外观上的差异。

Chrome浏览器已经在用户输入这个URL的同时显示出了punycode,告诉用户这个域名里面有Unicode字符。同时,域名注册商也在加强对此类域名的过滤,并不是所有这类都能注册。但是最为理想的情况应当是浏览器主动提醒这个地址不是“alipay.com”如果只是显示转换后的国际域名,很可能只会提醒到那些有经验的、知道xn—是何物的用户,对不认识国际域名的用户来说,这个提示可能就和HTTPS的绿锁一样被忽视掉。为减弱这个威胁,现在注册商已不允许混杂英文的国际域名注册,但这仍不能阻挡全部由型近字符组成的域名。

1.3 自纠错与Unicode字符分解映射

上面提到域名只要有Unicode都应该视为IDN,但凡事总有例外,浏览器还真的对URL一些字符做了特殊处理。浏览器自身对用户输入的URL有一定的纠正逻辑,例如你输入‘http:/www.example.org’(少个斜线),浏览器会自动帮你纠正成‘http://www.example.org’。同理,方便国际化域名的是,加入用户输入了‘http://互联网中心。中国’,浏览器会自动把句号转换为点。

在浏览器中还有一些可能大家并不是非常在意的特殊逻辑。以Chrome为例,在Chrome输入http:/www.example.org之后,Chrome并不会把它们转为punycode,而是会在其标准化函数中将该Unicode字符按照映射分解成ASCII字符‘org’,然后重定向到http://www.example.org。跟踪网络可以发现,在整个替换过程中,浏览器并没有发起请求,所以我们可以确定,与punycode一样,Chrome通过自身的逻辑就把它替换了。调试Chrome得知,Chrome在对URL的Host部分进行标准化时,如果发现它是一个类IDN,将会对它做转换到ASCII处理,在这个过程中调用ICU(Unicode国际化组件)库的标准化函数来将特定Unicode分解为ASCII字符。这个过程称为“分解映射”(DM),在每个浏览器中均有对这类字符的自动分解。更多的分解字符可以查询Unicode表得到。

1.4 登陆信息钓鱼攻击

钓鱼方式则是利用URL中登陆信息的部分。由于用户名:密码这样的形式看起来非常像域名:端口号,因此攻击者可以使用http://www.example.com:80@evil.com/的形式来将evil.com伪装成http://www.example.com来钓鱼。不同浏览器有不同的处理方式,以下是在地址栏直接输入网址后,浏览器处理时的差异。

各浏览器处理登陆信息的差异

浏览器

http:// qq.com

@evilsite/

http:// qq.com:

@ evilsite

http://:qq.com

@ evilsite/

http:// :

@ evilsite /

http://qq.com:80

@ evilsite /

IE

不支持

Firefox

提示用户

提示用户

不支持

提示用户

提示用户

Chrome

不显示登陆信息

Safari(Mac)

提示用户

Safari(iOS)

AOSP

显示完整登陆信息

为了防止用户识别错域名,许多浏览器都对一级域名部分做了高亮。在没有高亮的浏览器中,用户需要辨认URL中的一级域名。不过在识别的过程中,同样也要注意字形欺骗攻击,例如全角的斜杠‘/’可以出现在密码部分,导致整个URL可能看起来像http://www.qq.com:80/something@TRUESITE/somepath.html,此时应该观察高亮部分并仔细识别。

另外,出于对一般用户的保护考虑,许多浏览器已支持在无须登陆的网站上自动隐藏登陆信息,或者无论如何都不显示登陆信息,但是移动端一些浏览器却保留了旧的方案。例如早期的Android4.4.4自带的浏览器并不会隐藏登陆信息,攻击者能很容易伪造出一个看起来像是正常网址的钓鱼网站。

 

2 HTTP协议

Http协议是一个基于请求-响应的形式交互数据的无状态协议。客户端(浏览器)发送一个HTTP请求到服务器,然后服务器返回一个响应信息给客户端。相应的数据包含有请求的状态信息,也可以包含有响应的内容。

http协议的使用极为广泛,但是却存在不小的安全缺陷。http协议在设计时并未考虑信息的加密和验证,因此http面临着数据的明文传输和缺乏对消息完整性的验证机制两个问题。许多类似网银支付、账号登陆等需要安全保护的地方,如果使用http则可能会导致严重的信息泄露风险。

2.1 注入响应头:CRLF攻击

针对http头,攻击者可以进行CRLF攻击。CRLF是‘回车换行’的意思,CRLF攻击实际上是一个代码注入型的攻击。我们也知道http头由CR+LF确定一个字段的范围,如果某次响应数据中,有一个字段的数据是用户输入的,而服务器没有做好过滤,用户就可以通过编码插入CR+LF及注入的新字段来发起攻击。例如,攻击者可以通过注入HTTP头来篡改响应消息,也可以构造超长的HTTP头来攻击运行着Apache2.2.0~2.2.21服务器,使用户的HttpOnly Cookie泄露。

HTTP头注入可以导致多种问题,例如通过注入一个Set-Cookie字段,可以向用户的浏览器注入一个Cookie,在Cookie中可以指定SESSION造成固定会话攻击,攻击者可以注入HTTP头来关闭浏览器的XSS防护。

2.2 攻击响应:HTTP 401 钓鱼

2012年至2013年互联网上出现了许多HTTP401钓鱼的例子。攻击者首先在服务器上创建一个需要认证登陆才可访问的图片或页面。然后将图片或页面放置在论坛、邮箱、博客等地方。当用户访问链接向钓鱼文件的页面时,浏览器即会弹出对话框。这种钓鱼利用了浏览器处理相应的一个特性—当用户正在访问需要认证的资源时,服务器会响应HTTP 401 Unauthorized,浏览器收到这个状态码后会根据服务器提供的认证提示信息,弹出窗口,让用户提供认证用的用户名和密码。客户端提示用户的信息是通过响应头中WWW-Authenticate字段传递回来的,因此攻击者可以返回一些诱惑性的话语让用户提供一些隐私信息。

要达到这个效果,攻击者仅需在服务器上配置一个需要401跳转的页面:

<?php
Header(‘WWW-Authenticate:Basic realm=”PLEASE LOG IN!!!”’);
?>

然后将这个URL当作图片的地址,贴到论坛等地方,即可等待用户上钩子。

如果只是正常使用,也不是很推荐使用HTTP 401认证,通过这种方式认证时,口令传输仅仅经过可逆Base64编码,可以视作明文传输,本身也并不安全。

现在如Chrome、Firefox等浏览器都已经对401认证弹框做了提示,例如网站A下有着网站B的HTTP 401资源,那么网站B的认证框将不会弹出。如果你仍然在使用过程中发现了此类认证提示框,一定要仔细辨别:1、是否是你的主动操作,如果不是,不要单机登陆;2、连接到的主机是否是你熟悉的,或者是否和你浏览的网页的主机地址一致,如果不是,也不要单击登陆。

 

3 源

在客户端中,绝大部分安全策略都通过限制源来实行,表明源是由方案名称、主机名、端口号组成的。源的判断之所以不单单采用主机名的原因是考虑到不同协议间的安全性。例如https的连接通常是加密的、需要一定安全保障的,而http则是明文的、安全性较低的。如果仅仅采用主机名判断,http://example.org和https:// example.org就会被认为是同源的,从而http网页就可以直接读取到https网页的内容,会严重降低https的安全性。

而还有一个需要注意的是,源的判断中使用的是完整的主机名。之所以要这么做也是出于安全考量。考虑这样一个情形:一些国外的免费空间提供商,它们提供空间和免费的二级域名,各个三级域名对应空间的所有人其实是不一样的,因此,如果按照一级域名来判断,会导致各二级域名之间可以互相访问从而干扰数据。

3.1 同源准则

在计算机中,同源准则是web应用安全模型的一个重要概念。这个准则可以组织一个页面上的恶意代码访问另一个页面的敏感内容。在这个准则下,仅当页面A和页面B有同样的源时浏览器才允许页面A内容访问页面B。这个准则为当今依靠HTTP Cookies来获取用户会话认证的现代浏览器及相关程序提供了显著保护。由不同的源提供的内容在客户端被阻止互相访问,借此,源可以自认为自己的信息在用户侧是受保护的。

http://www.example.org:8080/a.html同源判定结果

URL

结果

解释

http://www.example.org/b.html

同源

<协议,主机名,端口号>全部一致

http://ww2.example.org/a.html

不同源

<协议,端口号>全部一致,主机名不一致

http://www.example.org:8080/a.html

不同源

<协议,主机名>全部一致,端口号不一致

https://www.example.org/a.html

不同源

<主机名>全部一致,协议和端口号不一致

3.2 源的特殊处理

由于about:blank、javascript:和data:伪协议并未指定任何与源相关的信息,在浏览器加载他们时,它们继承了加载他的文档的源。因此,当页面A打开about:blank时,由于源的继承,因此页面A可以修改about:blank窗口的内容。这个特殊情况导致了一些漏洞的发生。

在处理同源策略的问题上,大部分浏览器都是遵守规范的,但是由于历史原因,仅在IE中有下面两个特殊的情形:

(1) 位于可信域的互信的域名间,不遵守同源策略的限制;

(2) IE在判断同源不考虑端口,因此http://www.example.org:80http://www.example.org:81在IE中不受同源策略限制。

浏览器在访问目标时就会确定源,不过脚本也可以通过设置document.domain来修改自己的源,这可以为一些需要在不同子域之间传递信息的javascript带来方便,但是修改也仅限于修改当前域,这只能说是一个稍微宽松一点的同源判定方法。

例如,http://www.example.org/a.html的脚本可以执行document.domain=” example.org”来修改自己的domain,执行了这个动作后,较短的域会作为同源检测的依据,因此,修改之后页面就可以成功访问http:// example.org/b.html了,为了维护SOP权威,example.org脚本并不能通过document.domain将自己的domain设置为example2.org。

设置document.domain时,如果不指定端口号,则会以null覆盖原先的端口号,所以如果要确保在修改源之后端口号判断正常,在设置document.domain时需要带上新端口号。

 

4 特殊区域的安全限制

4.1 安全域

域或者安全域的概念仅有IE使用,它限制了不同站点的安全策略。在Internet Explorer中用户可见的4个域,分别是:

·Internet域,这是默认的域;

·本地Internet域,简称为本地域,因为权限较大,所以有较多的限制,例如本地域中默认关闭了脚本的执行,同时Internet域也不能访问本地域的内容;

·受信任的站点,在信任的网站列表的网站会受到较小的安全限制,例如可以运行未标记为安全的和未签名的ActiveX控件;

·受信任的站点,这个里面的站点默认会拥有较小的权限。

本地Internet域、受信任的站点通常被称为特权域,而在Chrome、Firefox中俗称的特权域通常指有较高权限或开放了特殊API的页面,从Internet域跳到特权域的攻击,都可称为跨特权域脚本攻击。

4.2 本地域

我们将所有浏览器的本地网页文件都简称为本地域,在网络上的文件称为网络域。本地域和网络域在不同的浏览器中的表现有一些差别。

各浏览器对本地域的判定


本地域

网络域

Internet Explorer

·默认禁止加载JavaScript/VBScript、ActiveX,信息栏提示

·脚本和ActiveX本地交互提示

·被标记为MOTW的本地页面可以运行JavaScript但是不可以访问网络或其他站点

·默认禁止加载不安全的ActiveX

·默认用户单击本地域链接

Firefox

·JavaScript开启

·禁止读取Internet内容

·禁止读取非同级目录及子目录下的内容

·禁止单击、加载本地域链接

Chrome

·JavaScript开启

·禁止读取Internet内容

·禁止单击、加载file协议的链接

·下载的html页面会标记”MOTW”

Opera

·JavaScript开启

·只允许访问本地内容

·禁止单击、加载file协议的链接

 

Safari

禁止访问本地文件、包括Safari中运行的Java Applet

·禁止单击、加载file协议的链接

对本地网页文件的限制可以通过一些设置重载。Chrome中可以通过命令行—allow-file-access-from-files允许访问本地文件,Safari也可以在选项中关闭对本地文件的访问限制。

4.3 伪协议

在浏览器中,有一些用于访问资源或脚本的协议,称作伪协议,行为’about’只是一个URI方案名,它并不是协议,为了和正式的网络协议区分,将其简称为’伪协议’。 伪协议是一种非标准化的协议,在浏览器处理时通常不会远程获取数据,甚至不会创建独立的上下文环境来展示部分伪协议的结果。在不同的浏览器中,常见的伪协议解析方式各异。

4.3.1 data伪协议

Firefox、Chrome和Opera等浏览器支持data URI协议(IE 6不支持),格式非常简单:

data:资源类型;编码,内容

即以data:开头,后分别制定MIME类型,字符集,数据是否已Base64编码,以及数据部分。

如果没有指定MIME类型,那么浏览器就会用默认的text/plain代替;

如果没有指定charset,浏览器会用默认的‘;charset=US-ASCII’代替;

简单来说,要生成一个html资源,可以这样:

data:text/html;ascii,<html><title>hello</title><body>world</body></html>

你把上面的链接复制到浏览器地址栏,打开就能看到效果了。

图片1.png

另外,IE对data伪协议有一些特殊的处理,例如IE8限制data URI最大长度为32KB,而IE9则没有这个限制。在IE中,data伪协议只可用于:

·object(仅可用作图片)

例如<object type=”image/png” data=”data:xxx”></object>

  • img

例如<img src=”data:xxx”/>

  • input type=image

例如<input type=”image” src=”data:xxx”/>

  • link

例如<link type=”text/css” rel=”stylesheet” href=”data:xxx”/>

  • CSS中接受URL的属性,例如background、backgroudImage等

例如.picture { background: url(data:xxx) }

而且出于安全考虑,IE中data URI只可当作图片资源使用,不能用在导航、脚本、frame、iframe中。且“#”、“%”、控制字符、非US-ASCII字符、多字节字符必须被编码。

在非IE浏览器中,可以通过windows.open、a href等方式打开一个地址为data URI的新窗口。

在Firefox、Chrome等浏览器中,data URI也可以在A、IFRAME、OBJECT等地方使用,因此有必要对data URI的运行环境进行隔离。Firefox6之前的浏览器中,如果用户手动在地址栏输入data URI,那么data URI会继承当前页面的安全上下文,它不和当前页面共享信息。

4.3.2 about伪协议

about伪协议,它的用法和data伪协议较为相似,在导航至”about:SOME HTML CODE”的时候,about后的内容会原样写入浏览器中,但是随后许多浏览器中about的这个特性就被取消了。

在所有的about伪协议支持的内容中,最常见的就是about:blank,它会显示一个空白页。

图片2.png

至少在这些情况下,浏览器会显示空白页:

  • 手动打开about:blank;

  • 发出打开新标签页/窗口请求,但是URL为一个空字符串;

  • 打开一个新标签页,未发生任何导航;

  • 部分浏览器发生导航到导航结束之前;

  • 在新窗口中导航到一个标记为“没有内容/部分内容”的页面;

  • 页面导航结束之前有脚本执行或被停止加载。

在Firefox、Chrome等浏览器中,使用windows.open()方法打开一个新窗口时,无论第一个参数(strURL)是什么,新开的窗口中的URL都不会立即加载,直到windows.open()函数返回,新开的窗口地址都一直是about:blank,直到当前代码块执行完成时,窗口才会导航到指定的URL上。

而IE浏览器中,新窗口刚刚创建,windows.open()返回windows对象为null,页面开始加载时,源和传入的strURL的源一致。

浏览器解析about:blank时,一定会返回一个0字节的,媒体类型是”text/html”、字符编码是UTF-8的空资源。如果about:blank后面跟有请求字符串,例如about:blank?abc,那么它的处理方式将由浏览器决定,大多数浏览器会提示该地址无法访问。

浏览器会对about伪协议进行一次简单URI标准化操作,例如大小写的标准化、百分号编码转换,即about:bl%61nk与about:blank等价(但是这种用法并不推荐)。还有,虽然浏览器能自动将大写about  URI转换为小写,但是如果URI中含有复杂的语法转换,则浏览器将无法正确解析。例如about:bl%40nk,Chrome在一遍简单标准化之后会把它当作about:blank,这个地址是未定义的。

浏览器可以决定about  URI的行为,它们可以作为浏览器功能、信息展示或彩蛋等功能存在。例如Firefox、Chrome支持的about:cache,在浏览器访问后会显示当前网络缓存服务器中缓存下的数据。而Firefox支持的about:mozilla,访问后则会显示一个来自虚构小说”Mozilla之书”中的一节。如果跟随的是未定义的内容,浏览器可自行决定是否把它当作about:blank展示。理论上,浏览器应当确保各个功能性about显示的内容不被其他页面获取,因为它们当中很可能包含有隐私信息。

4.3.3 javascript/vbscript伪协议

javascript伪协议非常像data伪协议,都可以把一个编码后的脚本放到地址栏然后执行。javascript伪协议的解析分两步,首先是从地址栏取出并解码javascript伪协议的脚本部分,然后是在某个页面上下文中执行代码。例如下列代码,当用户单击该超链接时,浏览器会跳转到”javascript:foo()”这个URI上,然后解析出脚本部分foo(),并在当前页面的环境下执行foo()函数。

<a href=’javacript:foo()’></a>

另外,和data伪协议不同,javascript伪协议在一些浏览器中有不同的表现。通过windows.open()开启javascript:alert(1)时,各浏览器表现如下:

javascript伪协议时各浏览器的表现

IE 11

新标签页打开,地址栏是javascript:alert(1)

但是新标签页的脚本无法执行,页面转向:

res://ieframe.dll/dnserror.htm#javascript:alert(1)

Chrome 43

Firefox 39

新标签页打开,地址栏是javascript:blank

alert(1)执行成功,执行上下文:about:blank

Safari(所有版本)

Chrome Lite(Android)

无反应

而对超链接中的javascript伪协议,各浏览器的做法也有不同。

<a href=’ javascript:alert(1)’ target=’w’>Click Me</a>

上述代码在各个浏览器运行结果如下:

IE 11单击

新标签页打开,地址栏是javascript:alert(1)

但是新标签页的脚本无法执行,页面转向:

res://ieframe.dll/dnserror.htm#javascript:alert(1)

Chrome 43单击

在当前页中执行了alert(1)

Firefox 左键39

在当前页中执行了alert(1)

Firefox 右键39

新标签页打开,地址栏是about:blank

alert(1)执行成功,执行上下文:about:blank

Safari(所有版本) 点击/单击

在当前页中执行了alert(1)

Chrome Lite(Android)点击

正是各个浏览器的差异导致了开发者的混乱,因此产生了许多漏洞。

5 DNS请求

Chrome、IE等浏览器都会对用户的访问进行预测和预取,例如Chrome在用户地址栏输入的时候就会猜测用户想要访问哪个网站。如果Chrome猜测某个网站将被访问的可能性很高,就会提前预取该网站的数据以达到让用户‘秒开’网页的效果。无论预测是否命中,导航的最开始,浏览器都会通过DNS服务器发送请求并解析到主机对应的IP地址。

这个过程称作‘DNS查找’,它分为下列几步:

  • 首先,浏览器查找自己的DNS缓存。浏览器会自己缓存一些常用的主机的DNS请求结果,如果浏览器已经事先缓存了对方的地址,就可以省去一次网络请求。

  • 然后是查找系统缓存,系统中也会缓存有几十个常见主机名的请求结果,如果是windows操作系统,你可以在cmd中执行‘ipconfig/displaydns’查看系统的DNS缓存。

  • 如果缓存没有命中,浏览器就会发出网络请求,开始解析域名。这可能会经过路由器缓存、ISP NDS缓存,如果缓存均未命中,则最终该请求会进入递归搜索模式并最终获取解析结果。

除了浏览器主动的预取和缓存之外,网页编写者也可以手动使用LINK的”rel=’dns-prefetch’、rel=’ prefetch’”属性通知浏览器预期DNS或者页面。

5.1 DNS劫持和DNS污染

通常,DNS查询基于UDP且没有任何认证机制,因此DNS查询非常容易被篡改,攻击者可以扮演‘中间人’对DNS请求发起攻击,这将使得最终浏览器获取到一个被篡改的DNS结果。

DNS攻击有劫持和污染两类常用的手段。攻击者可以劫持DNS服务器,取得域名的解析记录控制权之后,修改域名的解析结果。这样,受害者请求解析时,得到的结果将是修改后的内容。这在一些地方ISP(网络服务提供商)中较为常见,ISP会劫持某个域名的DNS。这样,用户访问该网站时就会收到一个假的解析结果。浏览器会先跳转到广告网站上,广告网站弹出广告后,再调到目标网站。

而另一类DNS污染则是一种DNS缓存投毒攻击。攻击者对运行在UDP53的DNS查询进行检测,一旦发现与关键词匹配的请求则立即伪装成目标域名的解析服务器,返回虚假结果。

要减轻DNS劫持攻击的可能性,(1)可以优先选用公共的、可信的DNS解析服务器,例如谷歌的8.8.8.8、8.8.4.4。(2)而为了避免DNS污染,则可以借用其他工具加密查询数据,例如DNSCrypt。

5.2 导航尚未开始时的状态同步问题

浏览器的用户界面是不可少的,在开发人员制作浏览器界面时,一个较大的挑战是开发者是否能够精确地做到消息同步。接下来,我们以遨游浏览器的一个早期版本为例说明消息同步没有处理好可能带来的安全问题。

通过window.open(strURL)打开某个URL后,整个导航流程还处于刚要开始的状态,该浏览器将地址栏修改为strURL,但页面的URL实际上是”about:blank”,在上面的内容了解到,谁创建了about:blank的窗口,谁就有权限修改它的内容。

如果攻击者在别处再次命令这个about:blank的窗口执行一段脚本,或是直接访问该窗口的document对象。改变DOM内容,window.open即将发起的导航过程就会被打断。该浏览器在这种情况下又不会将地址栏再次同步成about:blank,就形成了页面伪造漏洞。

开发者应当确保在窗口确确实实发出全部加载完成(不论正常加载还是访问超时、资源不存在都应一视同仁)的通知之后再去访问窗口属性,并更新用户界面,包括地址栏上显示的内容,这样才能保证页面信息显示的正确性。

 

6 建立安全连接

根据用户指定的URL,浏览器将选择合适的方式连接,例如HTTP、HTTPS、FTP等。HTTP使用明文传递,它本身无法验证通信双方的身份,也不能证明传输内容的完整性。因此,在网络上流通的HTTP消息基本可以视作是有可能被窃听、篡改的。

中间人攻击是指攻击者与通信的两端分别建立联系,并作为一个‘代理’交换收到的数据,使通信的两端认为他们正私密地、直接地与对方对话,但事实上他们的会话都被攻击者完全控制。

有许多场景需要更安全的通信机制,因此,HTTPS应运而生,采用SSL的HTTPS协议是基于HTTP的‘增强版’,它提供了创建安全信道、提供加密处理、使用证书来认证服务器的能力。在传输HTTPS报文时,所有内容都是加密的,在通信两端均安全实现时,即使通道被窃听,基本上攻击者也只能知道两端有一个连接,而对通信内容则一无所知。

HTTP协议和HTTPS协议同属于应用层(OSI模型的最高层),HTTPS并不是应用层的新协议,它只是对工作在加密连接(TLS或SSL)上的常规HTTP协议的称呼。通常HTTP直接和TCP通信,而使用SSL使,则变成先和SSL通信,再由SSL和TCP通信。所以HTTPS本质仍是HTTP,只不过多带了一层SSL。

HTTPS的信任基于预先安装在浏览器中的第三方机构的证书(这是一些获得认可的企业或组织机构,如VerSign、Microsoft等),HTTPS默认信任这些机构所信任的网站。浏览器在和网站交互时,通过校验证书,即可确定对方是否是自己预期要访问的服务器。

6.1 HTTPS请求中的Cookie

在浏览器的Web页面同源判定中,端口、协议(HTTP/HTTPS)都是要区分的。但是如果HTTP和HTTPS的Cookie也如此区分,那用户从HTTP切换到HTTPS的时候,就又会丢失许多已经保存的状态。不过还好,这个问题不会发生。Cookie与网页的同源判定不同,它有如下特征:

  • Cookie不区分端口;

  • Cookie不区分协议,也就是说不仅HTTP、HTTPS可以适用同一个站点上存储的协议,其他协议比如FTP、GOPHER等都可以共享Cookie;

  • Cookie并不严格按照path部分提供隔离。

因为Cookie不区分协议,所以不区分端口的特性很好理解。因为这些协议本身就运行在端口上,但是同样的,如果攻击者控制了某站点任意一个协议下的页面,那么它就可以读取到这个站点保存的Cookie。

在Cookie中的Secure标记可以让某个Cookie仅能在HTTPS会话中传输,这可以让Cookie变得稍稍安全一些。但是[RFC6265]也同时指出,攻击者可以通过在非HTTP域中设置Cookie来覆盖掉带有Secure标记的Cookie。即便如此,还是建议在传输时加上Secure标记,因此攻击者只能通过覆盖的方式来覆写Cookie,而不能强迫带有Secure标记的Cookie通过HTTP传输。

 

7 响应数据的安全检查-XSS过滤器

XSS攻击能成功主要还是依靠网站程序的漏洞,而要让网站管理员消除所有漏洞几乎是不可能的,为了减少XSS攻击给用户造成的损失,浏览器厂商推出了XSS过滤器,以判断代码行为的方式阻断可疑的代码注入攻击,从而保护用户的数据安全。

Chrome和IE浏览器中都引入了原生的XSS,这是防护XSS攻击的一个较为有效的手段。

7.1 IE XSS Filter的实现原理

从IE8 Beta2开始,微软引入了XSS Filter。IE中的XSS Filter基于正则表达式匹配来过滤用户输入中存在的可能有害的内容。IE的XSS Filter在mshtml.dll中实现,因此规则信息也存放在mshtml.dll中。

使用findstr /C:”str{r}”%WINDOW%\SYSTEM32\mshtml.dll|find”{” 命令可找到本机IE支持的所有规则。微软在更新浏览器时,也会根据情况适时更新规则信息。IE在判断时会扫描URL,对匹配上正则表达式的URL报警,提示发现XSS攻击并将字符替换为“#”。

发起请求且页面有响应时,会触发XSS Filter的扫描过程。在IE读取返回数据前,先XSS Filter会先对HTTP请求数据进行分析。针对文档加载,XSS Filter的处理过程大致描述如下(下载文件、请求资源并不会触发XSS Filter)。

1. 首先,浏览器判断浏览器设置中是否启用了XSS过滤功能,如果开启了,继续下一步,否则中止流程;

2. 对URL进行解析,判断是否为HTTP/HTTPS协议,如果是HTTP/HTTPS协议,继续下一步,否则中止流程;

3. 检查HTTP响应头是否包含X-XSS-Protection字段,如果包含这个字段,则根据值为1或0来准备进行或取消XSS过滤,然后到步骤6。如果没有这个字段,则开始验证URL,到步骤4;

4. 判断要加载的网站所在的安全域设置是否开启了XSS过滤,如果开启了过滤,到步骤5,如果没有开启,则中止流程;

5. 通过Referrer判断这次请求是否是一个跨站请求,如果是,则到步骤6,否则中止流程;

6. 这一步浏览器正式判断是否存在XSS。这是一个比较复杂的过程,首先,浏览器对可能的XSS进行预检测,如URL中输入的标签是否输出到了文档中,只有通过预检测后,才会开始规则检测,也就是上面我们介绍的正则式匹配,如果匹配,认为有XSS,发出提示并修改输出。

但是,IE的解析只是基于文字意义上的解析,许多并不是脚本的输出由于符合了IE的过滤规则,也会被当作跨站脚本过滤。例如

<TEXTAREA><SCRIPT>alert(“userinput”)</ SCRIPT ></ TEXTAREA >

被<TEXTAREA>标签对括起来的部分应当是文本节点,浏览器在解析到文本节点时并不会把它当作HTML代码渲染,但是IE依然会将其当作跨站脚本过滤。这导致IE的误报率偏高。

7.2 Chrome XSSAuditor的工作原理

Chrome的XSS过滤器称为XSSAuditor。类似于IE的XSS Filter,Chrome的XSSAuditor也被整合到了渲染引擎WebKit中,Chrome这么做的原因是因为过滤器可以在脚本执行前拦截它们,而且整合进去之后过滤器可以被任何基于WebKit的浏览器使用。

当页面加载时,XSSAuditor会在页面渲染之前评估用户的输入。它首先检查用户输入是否包含有恶意内容,如果有就拦截。XSSAuditor也会检查用户输入是否会“反射”到正在渲染的页面中,每个HTML页面都有5种类型的元素:HTML实体、HTML属性、Javascript、CSS和URL。因为输出上下文通常有不同的结构和格式,所以XSSAuditor会评估用户输入的上下文是否合法,在遇到非法的内容时将其过滤。

与IE不同的是,Chrome的XSSAuditor并没有使用正则的形式去判断。Chrome的XSS过滤是在词法解析阶段进行的,在解析网页时,HTML代码会被分解成不同的Token(每个Token即一个元素),XSSAuditor会逐一审查Token,将Token中存在的危险属性、字段和URL比较,若URL中也有同样内容,则XSSAuditor会认为这是一次反射型XSS攻击,随后会对该字段进行过滤处理。

Chrome XSSAuditor工作原理,以Chrome44为原型,例如当解析器解析下列代码时:<iframe src=”x” onerror=”alert(6)”></iframe>,会依次做如下判断:

1. 检查开始标签iframe,如果包含属性src、onerror,则认为可能危险,继续检查;

2. 如果src不是以javascript:开头,则安全,放行;

3. onerror中包含有脚本,检查这段代码是否同样出现在URL中;

4. 如果出现在URL中,认为这个地方有问题,这段代码会被过滤成<iframe src=”x” onerror=”void(0)”></iframe>;如果没有出现在URL中,认为这个地方没有问题,继续;

5. 检查中止标签iframe,没有问题,全流程结束。


8 脚本的编码

普通脚本安全问题大多数是在脚本权限内的滥用。以xss为例,网站、插件、浏览器没有统一的过滤标准,常见黑名单关键字过滤、字符替换虽然加大了攻击者的攻击难度,但是一些情况下仍然可能会被绕过。

当网站有针对特殊字符做过滤时(例如双引号),可以使用javascript脚本来构造合适的绕过代码。

Javascript中支持转义字符,如\x、\、\u、\U等。这四种编码方式是javascript字符串原生支持的编码方式。

\x和\两个编码方式有些像C语言的字符串转义符,\x后可以跟一个十六进制的正整数,\后可以跟一个八进制的正整数,\x和\跟的数字即为所代表的转义字符的ASCII码。数字大小范围为0x00~0xff。

而\u或是\U则应当跟一个范围在0x0000~0xffff之间的四位十六进制数字,不足的位用0补充。数字的含义是对应字符的Unicode数值编码。

除去这四个字符,还有一些特殊的转义符号,例如\n代表换行,\t代表一个缩进符号、\\代表斜线(\)等,这和C语言也是一样的。

当这些转义字符出现在字符串中时,脚本会自动将它们对应字符存储在字符串中,不需要做任何额外的操作。

8.1 浏览器的应对策略:CSP

  浏览器只能起到缓解跨站脚本等问题,而不能杜绝它们。为了防患于未然,站长可以为自己的页面添加内容安全策略—CSP来限制加载资源的权限。W3C定义了内容的规范。

CSP支持策略列表如下:

CSP支持的策略及含义

指令

说明

default-src

默认策略,针对所有请求类型生效

script-src

脚本加载策略

img-src

图片加载策略

style-src

样式加载策略

connect-src

网络连接请求的加载策略,当拒绝时,浏览器会响应HTTP 400

media-src

多媒体加载策略,包括<>、<>等标签

frame-src

框架加载策略

sandbox

对所有请求的资源启用sandbox(有些类似于iframe的sandbox属性)

report-uri

请求资源被策略拒绝时上报日志信息的URI

每条指令均支持不同的策略值,这些值连在指令后面形成一条完整的策略,例如X-Content-Security-Policy:script-src’self’表明加载外部脚本时,只允许加载和自己同源的脚本,来自其他地方的脚本将全部拒绝。


9 页面显示时的安全问题

攻击者把低权限的内容,借由高权限的载体展示出来,利用一些欺骗性的内容对用户进行攻击,这称做责任混淆问题。

在浏览器中也是如此,低权限的内容是欺骗性的文字、图片,高权限的载体便是浏览器。此类骗局通常都需要攻击者使用诱惑、恐吓性质的内容先获取用户信息,然后引导用户去做一些他们平时并不会去做的行为(例如填写密码、银行转账、安装程序等)。

9.1 点击劫持

点击劫持(Clickjacking)是一种欺骗攻击手段,它通过在特制的页面中用欺骗性的内容覆盖在无害的页面上,并诱惑用户点击页面上的某个地方。当用户点击的时候,点击事件也会传给被覆盖的页面,这样可以让用户不知不觉地在覆盖的页面上做操作。

点击劫持可能有不同的目的,例如欺骗用户的“赞”。例如曾经有针对Facebook的攻击,攻击者用一个网页覆盖在Facebook之上,诱骗用户点击“赞”按钮所在的位置。另一种攻击则是利用Flash、HTML以及脚本的配合来劫持用户的光标,成为Cursorjacking。

虽然现在常见的Clickjacking攻击没有利用浏览器内核代码的缺陷,但是也应当视为安全问题。随着攻击案例越来越多,浏览器厂商也讨论出了一个方案—网站可以在HTTP头中声明自己不允许在框架中加载,现在,主流的浏览器几乎都已经支持这种声明,如果网站做出了正确声明,将有效地阻止点击劫持的发生。

部分的点击劫持要归结于元素的样式特性。在层叠样式表中,名为z-index的样式指明了元素的堆叠顺序。其中一条简单的规则是:z-index越高,元素堆叠顺序越高。如果两个元素的位置有重合,那么堆叠顺序高的元素会放置在堆叠顺序低的元素前面。

因此,按照上述规则灵活调整z-index,将攻击者欺骗用户点击的内容布置在堆叠的最上层,将被攻击网站放在堆叠顺序的最下层,即可构造Clickjacking攻击页面。

9.1.1 NoScript

实际攻击中,攻击者肯定会设法让用户看不到被攻击的页面,因此要凭观察准确地识别一个页面是否进行点击劫持攻击还是有些困难的。但是一些插件,例如NoScript含有点击劫持防护功能,这可以帮助我们避免受到点击劫持或者类似的劫持攻击。在NoScript插件中开启ClearClick之后,访问可疑的页面时,该插件会弹出警告。

9.1.2 X-Frame-Options

2009年IE8引入了X-Frame-Options这个字段,专门用于防御点击劫持。在IE启用之后后迅速被其他浏览器包括Chrome、Firefox、Safari、Opera所接受。2013年开始,这个头被RFC接受,成为正式的HTTP头的字段,并归入规范[RFC7034]。

网站所有者通过设置这个HTTP头来告诉浏览器应当使用的框架策略。这字段的可选值有DENY、SAMEORIGIN以及ALLOW-FROM。这三个分别代表拒绝网站在框架中(DENY),网站只能被同源的网站中的框架加载(SAMEORIGIN),网站可以被指定允许的网站的框架加载(ALLOW-FROM)。没有设置这个字段时,默认可被其他任意网站加载。

例如Google主站设置了X-Frame-Option:SAMEORIGIN,这代表它仅可被它同源的站点的IFRAME加载。

 

10 HTML5的安全问题

HTML5中重新定义了一些元素的规范,例如<cite>和<menu>在HTML5中赋予了标准含义。然后新功能也会伴随新威胁。

10.1 基于FullScreen和Notification API的新型钓鱼攻击

常规的钓鱼网站大多依靠程序或模板生成,攻击者只要进行一次傻瓜式的“填写信息-点击按钮”操作即可生成钓鱼代码。然后,攻击者将文件上传到自己的服务器上,受害者访问并提交表单后,填写的数据会被记录下来。这样,就完成了钓鱼过程。

要识别此类钓鱼网站十分简单,那便是仔细检查地址栏显示的网址以及页面属性中显示的地址是否正是你要访问的网址。或者,不妨在浏览器中打开钓鱼过滤,例如IE就提供了SmartScreen Filter来过滤钓鱼网站,也可以安装安全软件,凭借它们的防护功能来防御此类攻击。

但是HTML5提供的强大功能让攻击者又有其他的选择途径,例如Feross Aboukhadijeh提出的使用FullScreen API即可进行完整的界面伪装。在早期版本的Safari中,弹出的全屏窗口完全没有提示,这将让攻击者的攻击更容易得逞。

10.2 组合API后可能导致的安全问题

一些新API单个使用时看似危害不大,但是如果攻击者可以通过某种方式获取用户信息,并组合多个API,那么也是有一些危害的。例如,HTML5提供了音频相关的API,因此我们可以构造一个页面,使用计算机的麦克风录取声音,下载github上的Recorder.js的代码并布置到本地。访问后,我们可以发现浏览器提示该网页需要使用麦克风。如果用户点击允许按钮,浏览器将会录下麦克风传入的声音。

只是录音可能危害看起来并不是多大,如果攻击者取得用户声音之后,再通过WebSocket API将声音实时传给服务器,那么服务器将相当于对用户的麦克风做了实时监听。

现在的浏览器对这些需要权限的内容都做了较为明显的提示,浏览器首先请求了用户的许可,并在录音之后的Tab上显示出了明显的红点符号,表示当前页面正在获取麦克风信息。因此,当我们日常使用的时候,对一些不熟悉的网站弹出的提示不要轻易地点击允许,而应该养成优先禁止,仅在有需求的时候授予权限的习惯。

10.3 浮层广告

不少软件采用推广分成制度,软件厂商的出发点通常都是好的,软件厂商通常认为提供推广的人应当明确告知用户产品特色并吸引用户安装。软件的推广安装大多数是按新装机器收费的,如果推广商遵守发布商的规定正常推广,按行为收费的广告的转化率应当是相当低的。即访问网站的人中最终决定安装占比很低。

在下游接受推广服务后,有一些急于赚钱的推广者便选择一些“恐吓”用户的途径,例如采用网站的右下角浮层广告来吓唬使用者。

识别方式很简单,因为浮层广告的”扫描界面”只是一个图片或者一个Flash,移动一下浏览器窗口,“扫描界面”就会跟着浏览器窗口一起动,如果是真的杀毒软件的窗口,肯定不会有这么诡异的行为。


11 浏览器扩展与插件的安全问题

扩展与插件通过与网页交互来丰富浏览器的用户体验,Firefox用户中,至少1/3的用户安装了额外的扩展插件。虽然NoScript之类的扩展可以增强安全性,但不可否认的是还有许多插件并没有安全专家参与编写,许多插件几乎有和浏览器一样的权限,对攻击者来说,与其攻破浏览器,不如攻破规模相对较小的插件见效快。

黑客攻击插件不仅是因为用户量,这其中还有另一个原因:许多用户会及时更新浏览器,但是却不会主动更细浏览器插件。

11.1 ActiveX

ActiveX是IE3引入的一项特性,它可以让浏览器调用外部二进制程序,比让该程序也参与网页展示。在于Netscape的份额大战期间,为了展示自己软件功能丰富,微软和网景都加入了许多互不兼容的HTML特性,ActiveX插件就是这场大战中微软加入的一个“法宝”。

这项功能加入浏览器后,IE的扩展性得到了巨大的进步,然而windows用户大多数以管理员身份运行,因此IE中ActiveX也以同样权限运行。一旦ActiveX出漏洞,那攻击者也可以轻易地以管理员权限运行代码,相当于为安全性埋了一个****。

ActiveX问题产生已久,为了避免不安全的ActiveX加载到用户的浏览器中,微软也做出了一些限制,其中两项称为Safe For Scripting/Safe For Init的标记构成了这个安全架构的核心。

默认情况下,ActiveX插件要在IE中运行,则必须同时拥有Safe For Scripting/Safe For Init标记才可以运行。IE加载ActiveX控件时,会依次检查如下动作来确定控件是否可以安全加载和运用于网页代码中。

(1) 先检查ActiveX控件是否设置了Killbit,如果设置了Killbit,IE将不会加载这个控件;

(2) 确定这个控件是否派生了IObjectSafaty接口,如果有的话,IE会通过这个接口检查是否有设置Safe For Scripting/Safe For Init。

但是这个标记完全是靠ActiveX的作者说了算,不负责任的开发者可能只是为了ActiveX能够方便地加载到浏览器中,就随意认定自己的插件为安全。

另一种问题则是代码自身的缺陷,ActiveX的开发者不一定会写出非常严谨的代码,或是合理地控制自己代码的权限。一些逻辑问题不一定在测试的时候能够精确复现,因此和普通大的软件BUG一样,在特殊情况下可以触发某些非正常逻辑并可能导致灾难性的后果。

正因为ActiveX不那么安全且不合规范,所以微软决定放弃这项技术支持,但即使是号称放弃ActiveX的windows 10的Edge浏览器也还是能加载一些特定的ActiveX插件。

ActiveX相当于远程布置一个二进制程序到用户的计算机中,如果开发者在ActiveX中留下一些未经校验即可执行高权限操作的接口,这相当于给攻击者留下了进入用户系统的捷径。这些接口包括文件操作、注册表操作、系统信息读取、进程开启关闭、加载其他程序等,如果不加验证便任由大众调用,那便可以称作ActiveX中最低级的错误。

这类ActiveX插件的逻辑漏洞如何挖掘,这里有一个较为通用的流程可供参考:

(1)查看ActiveX支持的方法和属性;

(2)根据名称猜测(或是分析二进制代码,或是进行黑盒测试)方法和属性的作用;

(3)将各方法的作用记录,分析是否有几个步骤可能产生问题(例如A登陆后执行指定程序;B登陆;两步组合成B-A即可能会产生一个严重问题);

(4)写出测试代码进行验证;

COMRaider可查看插件的方法和属性。COMRaider是一个老牌的开源ActiveX Fuzzer,但是它的测试用例比较陈旧,但用于查看ActiveX信息还是比较合适的。打开COMRaider后,选中需要查看的控件,COMRaider便会枚举出该控件的方法和成员变量。如果你在分析的过程中看到了例如SaveToFile、RunApp这类奇怪的字眼时,不妨根据方法名称去手动尝试一下。

11.2 定制浏览器的扩展和插件的漏洞

目前在中国市场上存在大量的“定制”浏览器。这里“定制”的意思是指这些浏览器采用来了IE、Chrome等浏览器所开放的内核并基于此二次开发的浏览器。与IE、Chrome不同,定制浏览器的开发者的工作更多地集中于非内核部分,将内核的开发任务交给开源社区解放了浏览器制作者的人力,定制浏览器可以使用更多的精力去制作一些本地化的便捷服务。这其中包含了扩展体系。

目前国内的浏览器大多数采用Blink/Webkit内核,并开发了插件系统。这些插件系统多复用了Chrome的插件体系,但是厂商也会在自己的插件体系中添加一些特殊的功能支持,例如DLL文件调用、与浏览器的服务进程通信、与浏览器发出的特殊事件进行交互。各家产品标准的不一致,也会反映在安全性上。

11.2.1 特权API暴露

危害:

任意安装插件à任意代码执行

成因:

  • 特权域下存在XSS,导致安装插件的API暴露;

  • 插件应用市场的页面存在XSS,可导致各种插件安装的JS被调用;

  • 安装插件时没有校验来源,可能会引入攻击者自己构造的插件,导致任意代码执行。

校验来源方法:

  • 页面请求的发起者+下载地址(如果这个也是参数的一环)。

  • 最好还加上Token,Token可以是一些攻击者无法通过JS计算或者无法预测的内容(例如浏览器的安装时间)且只能使用一次。最好不要暴露接口给基本可信域的所有子域。


11.2.2 DOM修改引入攻击向量

危害:

插件修改页面元素,产生mXSS,导致文本节点的内容被修改成代码并执行。

成因:

1、读取页面内容并重新经过处理再输出到页面上,期间未过滤。

常见的漏洞点容易出现在如下类型的浏览器插件中:

  • 搜索插件

  • 翻译插件

  • 比价插件

  • 网站切换插件

以及一些会将用户输入的内容再以某些形式输出到页面中的插件。这些插件均可能脱离用户操作直接触发漏洞,因此需要引起足够重视。

安全建议:

在输出到页面中时进行编码或使用文本节点来输出。


11.2.3 windows文件名相关的多个问题

危害:

解压到其他目录/DLL劫持/文件覆盖à任意代码执行

1. 相对路径

Zip的文件名宽松,可以通过编辑Zip压缩包使得文件名部分带有../,在未经正确处理文件名输出的解压代码中可能会将文件解压到其他目录,如果攻击者将文件定位并解压到“启动”目录下,在下次启动系统时,便可以执行攻击者的程序,造成任意代码执行漏洞。

  • DLL劫持

许多插件采用ZIP压缩包的形式下发,在一些插件体系中,虽然校验了执行起来的插件,但是安装包内没有用到DLL文件等却不一定有足够充分的校验。

这特别适用于一些既有EXE又有DLL的插件,如果攻击者将DLL命名成lpk.dll等系统DLL名称来进行DLL劫持时,插件启动时便会带来非常严重的问题。建议开发者在解压DLL文件的时候也校验签名,直接忽略签名不正确的文件不进行解压操作。

2. 文件名解压时无效字符的问题

Windows文件名规范中表示文件名的末尾不得包含NULLCHAR(\0)、半角句点、空格,以及\1~\31这些字符,但是ZIP打包的时候却可以将这些字符插入文件名部分,如果攻击者在文件名后面加入这些非法字符—如“lpk.dll”,在通过插件安装系统释放文件时,写入到硬盘上的文件名也会变成“lpk.dll”,从而导致DLL劫持。

即使加上了解压时DLL签名校验,遇到特殊的文件名时,系统API也可能会出现问题,对“lpk.dll”这样的文件名,可提权后缀API PathFindExtension、_split_path返回的均是错误的后缀(返回的都是句点“.”)。插件解压系统如果只是简单判断后缀名是否为dll,则仍可能会失败。另外,如果在ZIP文件中制定lpk.dll…、lpk.dll\0123456、lpk.dll.\0xxx这样的非法文件名,解压到硬盘之后,文件名也会是lpk.dll,所以解压程序得从后往前扫描一遍,找到最后一个无效字符,并删除后面所有内容,而不能只判断最后一个字符。

所以,为了安全起见,建议在解压前排除所有无效的字符再校验。或者也可以通过解析文件格式,例如假设当前正在解压的文件是PE文件,则统一校验签名,如果签名不匹配则不予释放。

11.2.4 NPAPI DLL的问题 

危害:

任意代码执行

包含有NPAPI的DLL的插件,需要注意是否存在XSS可能导致攻击者在网页上即可传入参数的行为。

可利用方法:

  • 攻击者编写含恶意功能的插件并上传到应用市场(需要通过官方审核),这类操作起来较为困难;

  • 寻找带有缺陷的官方市场中的插件,在静默安装该插件后,触发漏洞

11.2.5 同源检查不完善 

危害:特权API暴露à任意代码执行

成因:扩展的extension API应该限制在特权域,例如chrome://等。但是如果攻击者可以通过某些特定的方式来访问域下的API,则依然可能产生安全问题。

安全建议:

包含特权API的域应当严格遵守安全规范,例如chrome://的链接不允许通过非同源网页访问。

11.2.6 Content Script劫持 

危害:

信息泄露à高权限函数引用暴露

在不支持Content Script的浏览器(如IE)中,如果通过插件向页面注入代码,则应当十分小心。页面可以通过劫持注入的函数,并获取引用,导致敏感信息泄露。

安全建议:

在需要注入网页时,尽量给网页中注入的内容添加一个脚本无法计算的、各用户却不同的值,例如浏览器计算出的用户机器的MAC地址的哈希值。但是这个注入的内容也需要经过良好的加密,以免造成修复了Content Script劫持带来的问题又再次引入信息泄露的新问题。推荐将值加盐并使用单向散列函数对获取的用户值进行哈希运算。这样可以即保证根据各用户产生变化性,让javascript无法计算,又不会造成信息泄露。

11.2.7 配合切核策略+本地内部页XSS执行代码

危害:

特权域API泄露à任意代码执行

这里依然是百度浏览器的一个例子,百度浏览器在实现切核策略时,对通过FTP/UNC协议展示的HTML文件使用IE核心渲染。

而旧版本的百度浏览器的本地自带的文件(一些内部页)又存在XSS,XSS Filter在IE核心下一旦被绕过便可能导致任意代码执行。

安全建议:

浏览器在任何时刻都应当维持安全性,例如采用IE模式渲染时,应当开启IE提供的XSS Filter,而内部页面则建议使用固定的核心渲染,如果内部页面有需求可被其他页面打开,则打开后不应当跟随打开者的核心,而应当采用固定的渲染内核并配上合适的CSP策略。

11.2.8 下载服务器限制宽松

危害:

任意代码执行

浏览器在使用自家的下载服务器,下载并安装插件时,为确保安全,限制下载服务器时不应过于宽泛。例如旧版本的百度浏览器下载时限制下载服务器为*.baidu.com/*.crx,可以让导致攻击者找到一个百度域下的302跳转(形如:xxx.baidu.com/jumpto?http://eval.site/eval.crv)即可绕过该检测。

安全建议:

在设计下载部分代码的安全校验时,必须指定少而固定的列表,下载服务器不同于其他内容,不应当有如此宽泛的限制。

11.2.9 TLDs判定问题

危害:

信息泄露

在一些与域判断有关的插件中,可能存在顶级域判断的问题。由于顶级域不一定只有一个点号(如.com、.cn等),还可能有常见的两点(.com.cn、.net.cn等),因此许多插件可能会采用一个顶级域白名单依次判断。

在判断时,这个顶级域的白名单需要绝对精准,否则一些比较“偏门”的顶级域则不一定能识别,尤其是这些顶级域包含两个点号的时候,如果错误识别,则可能会被浏览器误将保存的信息填充到不该填充的欲中。

顶级域名表中有多个地方的顶级域,例如.ah.cn(安徽区域)、.bj.cn(北京区域),这些顶级域可能被误识别为.cn的TLD后导致出问题。

安全建议:

在判断时一定要选择最新的、完整的TLD列表去进行判断。在比对时,应当从长(点好多的)到短依次识别判断。

11.2.10 经典漏洞 

危害:

浏览器崩溃、或任意代码执行

例如旧版的Firefox官方的切核插件匹配*.10086.cn/*这条规则切换IE内核时,如果攻击者指定在图片文件中src时,如果src大于65535字节会导致程序处理异常,使得整个浏览器崩溃。

其他的一些经典漏洞例如缓冲区溢出等,同样会导致各种严重问题。

安全建议:

使用插件时,尽量使用由官方出品的插件。而且使用时请尽量保持插件能够及时更新到最新版本。


本文作者:Lemon

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/106906.html

Tags:
评论  (0)
快来写下你的想法吧!

Lemon

文章数:68 积分: 647

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号