购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

Chapter 1
第1章
前端安全漏洞

前端安全漏洞是指位于客户端的程序存在的漏洞或弱点,包括但不限于跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、界面操作劫持等。该类型漏洞如果被攻击者利用,那么可能被攻击者获取用户的系统权限、敏感信息等。

在本章中,你将会看到近几年知道创宇404实验室在前端安全方向遇到的真实漏洞,了解前端安全攻击和防护的相关思路。

1.1 前端防御从入门到弃坑——CSP的变迁

作者:知道创宇404实验室 LoRexxar'

1.1.1 前端防御的开始

页面存在XSS漏洞的原因通常是用户输入的数据在输出时没有经过有效的过滤,示例代码如下:

在这种没有任何过滤的页面上,攻击者可以通过各种方式构造XSS漏洞利用,例如:

通常情况下,我们会使用htmlspecialchars函数来过滤输入。这个函数会处理以下5种符号:

一般情况下,对于上述页面,这样的过滤机制可能已经足够有效。然而,我们必须认识到,漏洞场景往往比想象中复杂,示例如下:

对于这样的场景来说,上述过滤方法已不再适用,尤其是在输入点位于script标签内时。因此,我们通常需要采用更多样化的过滤手段来应对这类潜在的XSS攻击点。

首先,我们需要考虑符号的过滤。为了应对各种情况,我们可能需要过滤以下符号:

但事实上,过度过滤符号会严重影响用户的正常输入,因此这种过滤方法并不常见。大多数人会选择使用htmlspecialchars结合黑名单的过滤方法,例如:

有没有一种更底层的浏览器层面的防御方式呢?

CSP就这样诞生了。

1.1.2 CSP

CSP(Content Security Policy,内容安全策略)是一种增强型的安全措施,旨在检测和缓解各种攻击,特别是跨站脚本攻击(XSS)和数据注入攻击。CSP的显著优势在于,它是在浏览器层面实施防护机制,与同源策略处于同一安全级别。除非浏览器本身存在漏洞,否则从原理上讲,攻击者无法绕过这一保护机制。CSP严格限制了允许执行的JS代码块、JS文件、CSS等资源的解析,并且只允许向预先设定的域名发送请求,从而确保了网络内容的安全性。

一个简单的CSP规则如下所示。

CSP规则的指令分很多种,每种指令分管浏览器中请求的一部分,如图1-1所示。

图1-1 CSP规则的指令

每种指令都有独特的配置,如表1-1所示。简而言之,针对各种数据来源和资源加载方式,CSP都设有相应的策略。

表1-1 每种指令的配置

我们可以这样理解:如果一个网站实施了足够严格的CSP规则,那么XSS或CSRF就能从根源上得到防范。然而,实际情况真的如此吗?

1.1.3 CSP的绕过

CSP规则可以设定得极为严格,以致于有时会与众多网站的核心功能冲突。为了确保广泛的兼容性,CSP提供了多种灵活的模式以适应各类场景。然而,这种便利在为开发者提供灵活性的同时,也可能带来一系列安全隐患。

CSP在防御前端攻击方面主要采取两大措施:一是限制JavaScript代码的执行,二是限制对不可信域的请求。下面将探索若干种绕过CSP规则的策略。

1.第一种CSP规则代码

第一种CSP规则代码如下所示。

这是一个几乎没有任何防御能力的CSP规则,它允许加载来自任何域的JS代码。

2.第二种CSP规则代码

第二种CSP规则代码如下所示。

这是最普通、最常见的CSP规则,只允许加载当前域的JS代码。

网站通常会提供用户上传图片的功能,如果我们上传一个内容为JS代码的图片,图片就在网站的当前域下。

直接加载图片即可。

3.第三种CSP规则代码

第三种CSP规则代码如下所示。

当发现设置self并不安全的时候,你可能会选择把静态文件的可信域限制到目录。这种方法看似解决了问题,但是,如果可信域内存在一个可控的重定向文件,那么CSP的目录限制就可以被绕过。

假设static目录下存在一个302文件。

如之前所述,攻击者可以上传一个名为test的图片文件,然后利用302脚本实现重定向,将用户引导至upload目录下加载的JS代码,从而成功执行恶意代码。

4.第四种CSP规则代码

第四种CSP规则代码如下所示。

CSP不仅能阻止不可信的JS代码的执行,还能防止对不可信域的资源请求。

在上述CSP规则的约束下,如果我们尝试加载来自外部域的图片,该请求将被阻止。

在CSP的演变过程中,难免就会出现一些疏漏。

在CSP 1.0版本中,对于链接的限制并不完善,而且不同浏览器(包括Chrome和Firefox)对CSP规则的支持也有所差异。每个浏览器都维护着自己的一份CSP规则列表,这份列表通常包含CSP 1.0的规范、部分CSP 2.0的特性,以及少量的CSP 3.0功能。

5.第五种CSP规则代码

无论CSP有多严格,我们都无法预测开发者会写出何种代码。以下是Google团队发布的一份关于CSP的报告中的示例代码:

这段代码实现了将传入的字符串作为JS代码动态执行。实际上,许多现代前端框架都采用了类似机制。它们能够从特定的标签中提取字符串,并将其解析为JS代码。例如,AngularJS框架引入了ng-csp标签,以实现与CSP的完全兼容。

然而,即便在启用了CSP的环境中,一些现代框架仍能够正常运作。这表明在这些情况下,CSP可能并未发挥预期的安全防护作用。这突显了在实施CSP时,需要对框架的兼容性和安全性进行细致的考量和调整,以确保CSP规则能够有效地增强网站的安全性。

6.第六种CSP规则代码

第六种CSP规则代码如下所示。

可能你的网站并没有遇到这类问题,但你可能会采用JSONP技术来实现跨域数据获取,这种方式在现代Web开发中相当流行。然而,JSONP本质上与CSP存在冲突。因为JSONP旨在解决跨域请求的问题,它必须能够在可信域中执行,这与CSP限制不可信域代码执行的原则相悖。

通过这种方法,攻击者可以构造并执行任意的JS代码。即使CSP限制callback函数只能接收包含字母、数字字符(\w+)的数据,但某些情况下,部分JS代码仍有可能被执行。结合特定的攻击和场景,这可能导致安全威胁。

为了防范这种风险,最稳妥的做法是将返回数据类型设置为JSON格式。这样,即使攻击者尝试注入恶意代码,也只会将其作为数据处理,而不是作为可执行的代码,从而降低潜在的安全风险。

7.第七种CSP规则代码

第七种CSP规则代码如下所示。

与前面提到的CSP规则相比,以下所述的才是更为常见的CSP规则。

unsafe-inline是处理内联脚本的策略。当CSP规则中的script-src属性允许内联脚本时,页面中直接添加的脚本便能够被执行。

既然有能力执行任意的JS代码,接下来的问题便集中在如何巧妙地绕过对可信域的限制上。

(1)通过JS代码生成link prefetch

第一种办法是通过JS代码生成link prefetch:

这种办法只在Chrome浏览器中可用,但非常有效。

(2)跳转

在浏览器的机制中,跳转本身就是跨域行为:

通过发起跨域请求,我们能够将所需的各类信息传递出去。

(3)跨域请求

在浏览器中,存在多种类型的请求本质上是跨域的,包括表单的提交。而它们的共同特征就是包含href属性。

1.1.4 CSP困境以及升级

CSP被提出作为跨站脚本攻击手段之后的几年内,不断遇到各种挑战和问题。2016年12月,Google团队发布了一篇关于CSP的调研报告,题为“CSP is Dead,Long live CSP”。利用强大的搜索引擎技术,该团队分析了超过160万台主机上的CSP部署方式。

该团队研究发现,在加载脚本时最常被纳入白名单的15个域中,有14个安全性不足。因此,75.81%采用脚本白名单策略的主机,实际上允许了攻击者绕过CSP的限制。总结来说,它们发现在尝试限制脚本执行的策略中,有94.68%是无效的,并且高达99.34%的主机实施的CSP对防御XSS没有实质性帮助。

1.CSP类型

在这篇报告中,Google团队正式提出两种先前已被提出的CSP类型。

(1)Nonce Script

Nonce Script代码如下:

对于动态生成的nonce字符串,仅当script标签包含相应且值相等的nonce属性时,该script块才能被执行。

这个字符串生成可以在后端实现,并且每次请求都会重新生成。这样,无论哪个域被认为是可信的,只要确保加载的资源都是经过验证且可信的,就可以保证安全。

后端实现代码如下:

(2)Strict Dynamic

Strict Dynamic代码如下:

Strict Dynamic意味着由可信的JS代码生成的JS代码也是可信的。

这个CSP规则主要是为了适应各种现代前端框架而设计的。通过实施这个规则,可以显著减少为了适配框架而导致CSP规则过于宽松的情况发生。

Google团队希望通过这两种方法来解决因前端技术发展而产生的CSP相关问题。

2.绕过思路

然而,双方博弈总是不断升级。Google团队提出的两种方法存在如下问题。

(1)Nonce Script绕过

2016年12月,在Google团队提出Nonce Script CSP可以作为新的CSP趋势之后,Sebastian Lekies在圣诞节期间指出了Nonce Script CSP的一个严重缺陷。Nonce Script CSP对于纯静态的DOM XSS(文档对象模型跨站脚本攻击)漏洞几乎无法防御。随着Web 2.0时代的到来,前后端交互的场景越来越多。为了应对这种情况,现代浏览器配备了缓存机制。当页面中没有修改或者不需要再次请求后台时,浏览器会从缓存中读取页面内容。location.hash就是一个典型的例子。如果JS代码中存在由操作location.hash产生的XSS,那么这样的攻击请求不会经过后台,因此进行Nonce处理后的随机值不会刷新。这种CSP绕过方式曾经在CTF(Capture The Flag)网络安全竞赛题目中出现过。

除了最常见的location.hash,作者还提出了一种新的攻击方式,即通过CSS选择器来读取页面内容。

当匹配到相应的属性时,页面便会发起对应的请求。此时,页面上的变化仅限于CSS层面。这是一种纯静态的XSS,可以使CSP失效。

(2)Strict Dynamic绕过

2017年7月的BlackHat大会上,Google团队提出了全新的攻击方式——Script Gadgets。

Strict Dynamic的提出是为了适应现代框架,但Script Gadgets利用了现代框架的特性。Script Gadgets针对流行JavaScript库的绕过能力如图1-2所示。

图1-2 Script Gadgets针对流行JavaScript库的绕过能力

下面是Script Gadgets的示例代码:

Script Gadgets本质上是动态生成的JS代码,因此对于新型CSP,几乎可以实现破坏性的绕过,如表1-2、图1-3所示。

表1-2 对新型CSP的绕过

(续)

图1-3 对新型CSP的绕过

1.1.5 防御建议

随着我们对CSP的深入了解,不难发现,基于白名单的防御模式在很大程度上依赖于网站的代码和部署方式,特别是在现代前端架构逐渐承担更多压力的情况下,这也就要求前端的白名单限制越来越宽松。从这个角度来看,结合黑名单和CSP的防御模式才是最可靠的解决方案。

然而,在网络安全领域,并没有一劳永逸的防御措施……

1.2 从老漏洞到新漏洞——iMessage 0day挖掘实录(CVE-2016-1843)

作者:知道创宇404实验室 SuperHei

1.2.1 背景

国外安全研究人员发布了一个iMessage XSS漏洞(CVE-2016-1764)的修复细节,他们公布的细节里没有提供详细触发点的分析。然而,根据这些信息,我发现了一个新的0day 漏洞。

1.2.2 CVE-2016-1764漏洞分析

CVE-2016-1764漏洞最简单的触发Payload为javascript://a/research?%0d%0aprompt(1)。可以看出,这个漏洞实际上是未处理的%0d%0导致的,这是一种常见的XSS漏洞利用方式。

值得一提的是,选择使用prompt(1)而不是更常见的alert(1)的原因。经过实际测试发现,alert无法弹出窗口,此外很多网站直接过滤了alert函数,因此,在测试XSS时,建议将prompt替换为alert。

当遇到需要分析这样的客户端XSS漏洞时,首先要查看location.href信息。该漏洞是在applewebdata://协议下发生的,原漏洞分析里已经提到。然后要看具体的触发点,一般在浏览器环境下可以通过查看HTML源代码来分析,但是在客户端通常无法看到。因此,我们可以使用以下小技巧:

这里是查看HTML里的head代码:

继续查看body代码:

那么,关键的触发点如下:

JS代码被设置进a标签的href属性,导致单击a标签后执行漏洞。iMessage新版本的修复方案是直接不解析javascript://。

1.2.3 从老漏洞(CVE-2016-1764)到0day漏洞

XSS漏洞的本质是注入的代码最终被解析执行。既然我们看到了document.head. innerHTML,是否还有其他注入代码的机会呢?首先,我尝试了CVE-2016-1764漏洞点攻击,使用" "及< >进行闭合,但都被过滤了。接下来,我检查其他可能存在代码输入的点,发现了一个潜在的输入点。于是,我尝试发一个tttt.html附件来查看解析情况,部分代码如下:

附件的文件名在代码中出现,可能为攻击者提供了操控的空间。经过一系列测试发现,尽管过滤机制相对严格,我最终还是识别出一个潜在的风险点,即位于文件扩展名的部分:

将提交附件的后缀嵌入style属性:

这可能导致CSS注入。测试中,我也发现了一些过滤措施的存在,例如“/”被直接转换为“:”。这一点颇为有趣,正如“成也萧何,败也萧何”,如果你的目标是注入CSS,那么在属性赋值时必须使用“:”,但文件名中又不能包含“:”。而我尝试在注入的CSS中调用远程CSS或图片资源时,又需要使用“/”,但“/”被替换成了“:”。

尽管存在这些挑战,我还是决定先尝试注入CSS进行测试,于是提交了一个附件名:

按推断“/”变为“:”,如果注入成功应该是:

当我尝试发送包含这个附件的消息时,我的iMessage崩溃了,我想我发现了一个新的漏洞,于是升级OS X到最新的版本并重新测试,结果一个全新的0day漏洞诞生了!

1.2.4 修复建议

我想强调的是,在分析别人发现的漏洞时,一定要找到漏洞的关键点,总结提炼出“模型”,然后尝试新的攻击测试。该漏洞在OS X El Capitan v10.11.5的安全性更新2016-003中给出修复方法,建议用户及时更新到最新的操作系统。

1.2.5 参考链接

[1]https://github.com/BishopFox/cve-2016-1764

[2]https://www.bishopfox.com/blog/2016/04/if-you-cant-break-crypto-break-the-client-recovery-of-plaintext-imessage-data/

[3]https://www.seebug.org/vuldb/ssvid-92471

[4]https://support.apple.com/en-us/HT206567

1.3 从CVE-2018-8495看PC端URL Scheme的安全问题

作者:知道创宇404实验室 0x7F

受CVE-2018-8495漏洞的启发,出于学习的目的,我对PC端URL Scheme的安全问题进行了深入研究。关于URL Scheme的安全隐患,并不是一个新问题,早在2008年,就有关于URL Scheme的研究和利用;而在2018年,又连续出现了一些安全问题,包括1月的Electron命令注入(CVE-2018-1000006)和10月的Edge RCE(CVE-2018-8495)。这些事件表明,URL Scheme的安全问题值得深入探讨。

1.3.1 概述

1.常见的URL Scheme应用场景

在日常使用计算机的过程中,我们经常会遇到点击某个链接会启动本地应用程序的情况,各大操作系统开发商和浏览器开发商为了提升用户体验、丰富浏览器的功能,允许开发人员将URI与本地的应用程序进行关联,从而在用户使用浏览器时,可以通过点击某一链接来启动应用程序。我们将这个功能简称为URL Scheme。例如,点击mailto://test@test.com会启动邮件客户端,点击thunder://xxxxx则会启动迅雷客户端。这就是URL Scheme的应用场景。除此之外,我们在浏览器的地址栏中也会看到各种不同的前缀,如http://、https://、ftp://和file://,这也是URL Scheme的应用场景。

例如,在Windows 7下使用IE8启动默认邮件客户端Outlook,如图1-4所示。

2.URL Scheme工作流程

在掌握了URL Scheme的功能后,我们便能大致洞察其工作流程。应用程序在操作系统中进行URL Scheme的注册。当浏览器或其他支持URL的应用访问特定的URL Scheme时,系统会匹配相应的URL Scheme项,进而启动相关应用程序。显然,这是一个需要三方协同作业的功能,如图1-5所示。

图1-4 在Windows 7下使用IE8启动默认邮件客户端Outlook

图1-5 URL Scheme工作流程

因此,对于URL Scheme这一功能,操作系统、浏览器(或其他支持URL的应用)、应用程序这三个环节中的任何一个出现安全隐患,或者它们协同工作中出现问题,都可能给整体安全造成影响,最终可能会给用户带来安全问题。

1.3.2 创建URL Scheme

那么,如何在操作系统中注册URL Scheme呢?不同的操作系统有着不同的实现方式,这里我们以Windows 7为例进行说明。

在Windows 7系统中,URL Scheme被记录在注册表的HKEY_CLASSES_ROOT下,例如mailto的相关字段,如图1-6所示。

若需创建新的URL Scheme,直接在HKEY_CLASSES_ROOT下进行添加即可,并确保在相应字段填入对应的值。所创建的子项名代表URL Scheme的功能名称。该子项下包含两个关键项:DefaultIcon和shell。其中,DefaultIcon项存储该功能所使用的默认图标路径;shell项下则需要进一步创设子项,例如命名为open,接着在open子项下再创建command子项(用于描述应用程序的路径以及相关参数)。

图1-6 URL Scheme被记录在注册表的HKEY_CLASSES_ROOT下

例如,创建calc以启动C:\Windows\System32\calc.exe:

在Windows系统中,实际上存在两种添加URL Scheme的方法。一种是直接在注册表中添加(即Pluggable Protocol),另一种是使用异步可插拔协议(即Asynchronous Pluggable Protocol),后者注册的URL Scheme协议会被记录在HKEY_CLASSES_ROOT\PROTOCOLS下。详细的信息在参考链接[1]中提供,此处不再展开说明。

1.3.3 安全隐患

简而言之,URL Scheme功能允许通过URL启动本地应用程序,这无疑极大地提升了用户体验。然而,这也带来了一些安全隐患。例如,用户可能会通过浏览器无意中启动恶意程序,或者用户启动的应用程序可能具有可被利用的特殊功能(如删除文件、启动网络连接)。

除此之外,对于处理URL的相关应用,用户通常只是使用者或阅读者,而非编辑者。这意味着,URL可能会被攻击者恶意构造,从而实现远程启动本地应用程序的目的,如图1-7所示。

图1-7 攻击者可恶意构造URL

在操作系统中,哪些URL Scheme可以被调用呢?我们提供了3个脚本,以导出三大PC系统(Windows、MAC、Linux)下的URL Scheme。这些脚本均来源于参考链接[5]。

通过运行这些脚本,我们可以发现系统中有许多可调用的URL Scheme,其中既有操作系统默认支持的,如HTTP、FTP、Mailto,也有第三方应用程序支持的,比如QQ、Thunder等。如果这些应用程序存在安全隐患,例如支持删除文件、启动另一个程序等敏感操作,那么在URL Scheme的帮助下,这些安全问题可能会被远程触发。

除了应用程序可能存在的安全问题,浏览器(或其他程序)在解析URL并启动应用程序的过程中也可能出现安全问题。在这三方相互支持的过程中,仍然有可能出现安全问题。无论哪个环节出现安全问题,最终都可能在URL Scheme下被放大。

接下来,我们将对可能出现安全问题的环节进行分析,并通过示例进行说明。

1.3.4 操作系统中的问题

早在2007年,Heise Security就公开了URL Scheme的远程命令执行漏洞,它出现在Windows XP下已安装IE7版本的系统中,影响范围包括所有支持URL Scheme的应用程序。

构造的PoC如下:

在Windows XP中的运行结果如图1-8所示。

图1-8 在Windows XP中的运行结果

此漏洞出现的根本原因在于,微软通过为Windows XP安装IE7,更改了操作系统对URL的处理方式。应用程序将URL Scheme路径直接传递给操作系统以启动对应的程序,而含有“%”字符的特殊链接最终导致任意应用程序的启动。

在漏洞被公开后,微软并未发布修复补丁,声称这并非Windows XP的问题。随后,各大应用程序开发人员纷纷对该漏洞进行了修复。虽然上层应用确实可以对输入参数进行检查,但这里的问题显然与操作系统的处理有关,从而导致了URL Scheme的远程命令执行漏洞。

1.3.5 浏览器参数注入

2018年,有两个明显的URL Scheme安全问题是由Windows下的IE和Edge参数注入引发的。其中一个是Electron自定义协议导致命令注入(CVE-2018-1000006),另一个是Edge远程代码执行漏洞(CVE-2018-8495)。

Windows下的IE和Edge对URL Scheme的处理方式存在差异。当浏览器接收到一个URL Scheme时,它会访问注册表以查询相应的应用程序路径,之后进行URL解码,并调用ShellExecute函数簇以启动应用程序,如图1-9所示。正是URL解码这一步导致双引号的闭合,从而引发了参数注入问题。

1.Electron自定义协议导致命令注入

2018年1月,Electron发布了自定义协议导致命令注入的安全公告(CVE-2018-1000006)。对于参数注入而引发的问题,构造的PoC如下:

图1-9 URL Scheme调用流程链

使用IE浏览器访问该链接,最终生成的启动参数如下:

通过参数注入,调用Electron支持的--gpu-launcher参数,设置该参数的值为cmd命令,并最终执行该cmd命令,启动计算器,如图1-10所示。

图1-10 CVE-2018-1000006 PoC演示

2.Edge远程代码执行漏洞

2018年10月,Edge公开了远程代码执行安全漏洞(CVE-2018-8495)。该漏洞同样是利用参数注入,最终达到了远程代码执行的效果。整个漏洞利用过程非常巧妙,下面进行详细分析。

首先需要指出的是,在Edge浏览器中居然可以打开一些不合法的URL Scheme(没有包含URL Protocol字段),比如wshfile项,如图1-11所示。

当然,在Windows 7和Windows 8中不能打开不合法的URL Scheme。

wshfile项指向了wscript.exe,这是一个非常熟悉的Windows内置脚本解释器。那么,我们可以利用wshfile尝试去运行脚本。上文提到Edge浏览器中存在参数注入问题,那么是否有脚本可以接收参数并用于执行呢?

图1-11 Edge浏览器通过URL Scheme调用wshfile

漏洞作者最终找到了以下解决方案:

该脚本文件支持接收参数,并且会将命令直接拼接到字符串中,然后通过PowerShell执行。

最终构造的PoC如下:

执行后触发的效果如图1-12所示。

图1-12 利用wshfile项构造PoC来打开calc.exe

目前,Windows 10已经发布了修复补丁,Edge已经不能调用这类不合法的URL Scheme。

此外,在分析漏洞过程中,知道创宇404团队也有了一些额外的发现,例如,在注册表HKEY_CLASSES_ROOT下发现了类似wshfile的URL Scheme,这些URL Scheme都指向wscript.exe,同样有可能触发远程代码执行。这些URL Scheme包括:

在C:\Windows\System32\目录下,我们还发现了SyncAppvPublishingServer.vbs文件。该文件同样可被用于触发远程代码执行,并且相较于漏洞作者所提供的方法,这种方式更为可靠。

除了SyncAppvPublishingServer.vbs文件外,位于C:\Windows\System32\Printing_Admin_Scripts\zh-CN目录中的pubprn.vbs文件也具备触发远程代码执行的能力。

需要补充的是,在Windows 7操作系统中,Chrome和Edge浏览器都存在打开非法URL Scheme的问题,但由于Chrome并未出现参数注入问题,因此可以暂时认为它是安全的。

1.3.6 应用程序的问题

2017年12月,macOS中的Help Viewer应用程序因XSS而出现的文件执行漏洞(CVE-2017-2361)被公开披露。此漏洞影响了macOS Sierra 10.12.1及其以下版本。攻击者可以利用该漏洞,通过恶意构造页面实施远程攻击。这是由应用程序引发的URL Scheme安全问题的一个典型例子(详情可参考链接[7])。

构造的PoC如下:

显而易见的是,在这个漏洞利用过程中,操作系统和浏览器本身并未出现任何问题,真正的安全隐患出现在通过URL Scheme启动的应用程序上。深入分析这个利用链,我们可以发现几个“巧妙”之处。

❑利用URL Scheme中的Help协议,可以启动Safari.help应用程序。

❑通过双重URL编码技术,成功绕过了Help Viewer对路径的安全检查,从而打开一个能够执行JavaScript的页面。

❑使用Help Viewer的内置协议x-help-script来启动应用程序(概念验证代码中并未包含这一部分)。

实际上,URL Scheme功能的便捷性是操作系统、浏览器(或其他支持URL的应用)以及应用程序这三者相互协作的结果。要确保URL Scheme的功能安全可靠,我们必须对这三方的安全性有充分的把控。

需要注意的是,不同的操作系统对URL Scheme的实现方式各有差异,不同的浏览器有特有的处理机制,应用程序的处理方式也各不相同。这种多样化的组合有可能导致一些意想不到的安全问题。

1.3.7 防御建议

1)谨慎点击链接:避免点击来源不明或不可信的链接,特别是包含URL Scheme的链接。

2)注意短信和电子邮件:小心处理短信和电子邮件中的链接,尤其是来自陌生发送者的链接。

3)使用最新的应用程序和操作系统版本:确保你的设备上安装的应用程序和操作系统都是最新版本。

4)审查应用程序权限:在安装应用程序之前,仔细审查应用程序请求的权限。

5)使用安全软件:安装可信任的安全软件,如防病毒软件和防火墙,以提供实时的安全保护和检测潜在的恶意链接或攻击。

6)定期备份数据:定期备份你的设备上的重要数据,以防数据丢失或受URL Scheme攻击的影响。

7)保持警惕:保持对不寻常的行为或弹窗的警惕,特别是点击链接后出现的窗口。

1.3.8 参考链接

[1]https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767916(v%3dvs.85)

[2]https://images.seebug.org/archive/duh4win.vbs

[3]https://images.seebug.org/archive/duh4mac.m

[4]https://images.seebug.org/archive/duh4linux.sh

[5]https://www.blackhat.com/presentations/bh-europe-08/McFeters-Rios-Carter/Whitepaper/bh-eu-08-mcfeters-rios-carter-WP.pdf

[6]http://www.h-online.com/security/news/item/URI-problem-also-affects-Acrobat-Reader-and-Netscape-733744.html

[7]https://bugs.chromium.org/p/project-zero/issues/detail?id=1040&can=1&q=reporter%3A lo kihardt%40google.com%20&sort=-reported&colspec=ID%20Status%20Restrict%20 Reported%20Vendor%20Product%20Finder%20Summary&start=100

[8]https://leucosite.com/Microsoft-Edge-RCE/

[9]https://paper.seebug.org/515/

[10]https://electronjs.org/blog/protocol-handler-fix

[11]https://www.blackhat.com/presentations/bh-dc-08/McFeters-Rios-Carter/Presentation/bh-dc-08-mcfeters-rios-carter.pdf

[12]https://www.oreilly.com/library/view/hacking-the-next/9780596806309/ch04.html

[13]https://github.com/ChiChou/LookForSchemes

[14]https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8495

[15]https://docs.microsoft.com/en-us/windows/uwp/launch-resume/reserved-uri-scheme-names

[16]https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85)

1.4 iOS中的BadURLScheme

作者:知道创宇404实验室 SuperHei

1.4.1 概述

这个漏洞的根源主要在于iOS操作系统对URL Scheme的处理,以及它在UIWebView等控件中的自动诊断、识别和处理机制,这些因素共同导致了跨应用的XSS漏洞。

1.4.2 漏洞详情

iOS操作系统中的URL Scheme具有几个特点。

❑iOS操作系统中的URL Scheme全局有效且只需安装App即可生效。

❑iOS操作系统中的URL Scheme会被UITextView或者UIWebView的Detection Links属性识别为可点击的链接。

我们先看第2点的具体处理机制——“UIWebView的Detection Links属性识别为可点击的链接”,也就是任何输入的URL Scheme链接都会被解析为HTML里的<a>标签的href属性:

对于熟悉XSS漏洞的人来说,可能会考虑两种攻击思路。

❑通过双引号闭合,然后使用事件来执行JS语句:经过测试,双引号出现在URL Scheme里不会被正确识别,因此这个思路不可行。

❑利用javascript://:通过伪协议执行JS语句。

在主流的浏览器内核中,有两种常见的方法来执行JS代码。第一种方法如下:

第二种方法很少有人正规使用:

请注意区分“:”与“://”这两种标识。正是这两种标识的非常规使用,导致众多程序中出现漏洞,例如先前披露的iMessage的XSS漏洞(CVE-2016-1764)。因此,所谓的“BadURLScheme”实际上指的是JavaScript这个URL Scheme。我们再次聚焦于iOS系统中URL Scheme的第一个特性:一旦用户安装了一个注册了JavaScript这个URL Scheme的应用程序,若其他应用程序中嵌入了UIWebView并配置了Detection Links属性进行链接识别,那么在这些应用程序中输入如下文本内容:

该文本内容会被Detection Links属性解析为<a>调用,导致这些应用程序的XSS漏洞出现:

1.4.3 实际案例

要成功触发这一漏洞,需要同时满足两个条件。第一个条件是用户必须下载并安装JavaScript URL Scheme的应用程序(仅安装就足够),通常是攻击者通过短信、微信等社交手段诱使用户下载并安装的恶意应用程序。此外,也有可能在现有的应用市场中存在一些已经注册了JavaScript URL Scheme的应用程序,例如Maxthon Cloud Web Browser-Best Internet Explorer Experience by Maxthon Technology Limited。也就是说,那些安装了Maxthon浏览器的用户可能面临风险。

第二个条件是,被攻击的应用程序使用了UIWebView并且开启了Detection Links属性。实际上,我们发现许多应用程序都满足这一条件,比如微信(已修复)、QQ邮箱(已修复)、Outlook、印象笔记、知乎等。有关此漏洞的利用演示,请参考链接[2]。

1.4.4 漏洞披露

在发现这个漏洞时,我产生了一些疑问:当A系统上安装了B公司的软件导致C公司的软件遭受攻击时,这个漏洞究竟属于谁的责任?应该向哪个公司报告?经过深入分析,我认为这实际上是iOS的一个漏洞。对于Maxthon开发人员来说,他们也算是在合理使用URL Scheme,而对于受影响较大的C公司,我选择了同时向它们报告。

❑2016年4月12日,我向product-security@apple.com报告了此问题,并于4月15日收到了邮件确认,但后续并未收到任何关于漏洞修复计划的消息。

❑2016年4月11日,我向TSRC报告了此问题,得到了TSRC的积极响应。它们陆续修复了报告中提到的受BadURLScheme影响的App。

❑2016年4月12日,我向MSRC报告了此问题,它们反馈称该漏洞被认定为iOS漏洞,并已与苹果公司进行了沟通,但Outlook一直未进行处理。

❑2016年8月27日,我在KCon 2016大会上做了题为“BadURLScheme in iOS”的演讲。

❑2016年9月14日,苹果发布了iOS 10,经测试不再受BadURLScheme漏洞的影响。

1.4.5 防御建议

1)保持更新移动设备操作系统。

2)不要点击或访问来历不明的链接。

1.4.6 参考链接

[1]https://itunes.apple.com/cn/app/maxthon-cloud-web-browser/id541052011?l=en&mt=8

[2]http://v.qq.com/x/page/x0328nwv6ju.html

1.5 从Drupal 1-click到RCE分析

作者:知道创宇404实验室 LoRexxar'

2019年4月11日,Zero Day Initiative(ZDI)博客发布了一篇题为“A SERIES OF UNFORTUNATE IMAGES: DRUPAL 1-CLICK TO RCE EXPLOIT CHAIN DETAILED”的文章,详细介绍了一个Drupal中的一键远程代码执行(RCE)漏洞链。

整个漏洞链的每个环节单独看来并无特别之处,攻击者使用了3个漏洞,把所有的漏洞连接起来构建了一个相对完整的利用链。现在,我们就来一起看看整个漏洞链。

1.5.1 无后缀文件写入

Drupal机制中存在这样一条规则:用户上传的图片文件名将会被保留,如果出现文件名相同的情况,那么文件名后面就会被加上“_0”“_1”……

为了兼容各种编码,在处理上传文件名时,Drupal会对文件名进行相应的处理,如果出现值小于0x20的字符,那么会将其转化为“_”,如图1-13所示。

但如果文件名中出现了\x80到\xff之间的字符,PHP就会抛出PREG_BAD_UTF8_ERROR错误。一旦这种错误发生,preg_replace函数就会返回NULL,$basename变量就会被赋值为NULL,如图1-14所示。

图1-13 Drupal对文件名做相应的处理

图1-14 返回值

当basename为空时,后面的文件内容会被写入“_0”格式的文件内,如图1-15所示。

图1-15 文件内容被写入“_0”格式的文件内

在这个基础上,文件内容原本会被上传到的路径/sites/default/files/pictures/<YYYY-MM>/改为/sites/default/files/pictures/<YYYY-MM>/_0。

当服务器开启了评论头像上传功能,或者攻击者掌握了作者账号时,他们可以先上传一张经过恶意构造的GIF图片,随后上传一张含有恶意字符的同名图片。这样做会使恶意图片内容被写入相应目录下的“_0”文件中,如图1-16所示。

图1-16 恶意图片内容写入相应目录下的“_0”文件中

但如果我们直接访问这个文件,该文件可能不会被解析,这是因为:

1)首先,浏览器会根据服务器端给出的content-type解析页面,而服务器端一般不会将空后缀的文件设置为content-type或者application/octet-stream。

2)其次,浏览器会根据文件内容做简单的判断,如果文件的开头为<html>,则部分浏览器会将其解析为HTML。

3)最后,部分浏览器会解析该文件,还可能会设置默认的content-type,但大部分浏览器会选择不解析该文件。

这时候我们就需要小技巧,<a>标签可以设置打开文件的type(only not for chrome)。

当你访问该页面时,页面会被解析为HTML并执行相应的代码。

当攻击者访问该页面时,他们可以实现任意的跨站脚本攻击。

1.5.2 Phar反序列化RCE

在2018年的BlackHat大会上,Sam Thomas分享了一个议题,名为“File Operation Induced Unserialization via the‘phar://’Stream Wrapper”。他提到,PHP中存在一个名为Stream API的机制,通过注册扩展,可以注册相应的伪协议。而Phar扩展就注册了phar://这个Stream Wrapper。

根据知道创宇404实验室安全研究员seaii之前的研究“利用Phar拓展PHP反序列化漏洞攻击面”,所有的文件函数都支持Stream Wrapper。这意味着,如果找到可控的文件操作函数,它的参数可控为phar文件,那么我们就可以通过反序列化执行命令。

Drupal有一个功能——对传入的地址做is_dir判断,这里就存在上述问题,如图1-17和图1-18所示。

图1-17 对传入的地址做is_dir判断

直接使用下面的Payload生成文件:

图1-18 file system功能

修改文件名后缀为PNG之后,将图片传到服务器端,并在file system中设置phar://./sites/default/files/2019-04/drupal.png即可触发漏洞,如图1-19所示。

图1-19 在file system中进行设置

1.5.3 漏洞触发要求

这个漏洞在Drupal 8.6.6版本更新时被修复,所以漏洞触发要求如下。

❑Drupal版本为8.6.6及以下。

❑服务器端开启评论配图或者攻击者拥有Author以上权限的账号。

❑受害者需要访问攻击者的链接。

当上述三点同时满足时,这个攻击链就可以成立。

1.5.4 漏洞补丁

1)无后缀文件写入(SA-CORE-2019-004)。补丁可通过相关链接查看,修补代码如图1-20所示。

如果出现preg_last_error错误,代码直接抛出异常,不继续写入。

2)Phar反序列化(SA-CORE-2019-002)。补丁可参考链接[5]。

1.5.5 总结

回顾整个漏洞,我们可以发现它实际上是由许多看似微不足道的小漏洞组成的。其中,Drupal的反序列化POP链和Phar漏洞早已被公之于众。在2019年初,Drupal已经发布了更新版本来修复这个漏洞。而preg_replace报错会抛出错误,这不是什么特别的特性,然而把这三个漏洞配合一个很特别的<a>标签来设置content-type,就成了一个相对完善的漏洞链。

图1-20 无后缀文件写入漏洞修补代码

1.5.6 防御建议

为了防止受到该漏洞的影响,建议将Drupal升级至8.6.6以上版本。

1.5.7 参考链接

[1]https://www.zerodayinitiative.com/blog/2019/4/11/a-series-of-unfortunate-images-drupal-1-click-to-rce-exploit-chain-detailed

[2]https://paper.seebug.org/680/

[3]https://www.drupal.org/SA-CORE-2019-004

[4]https://github.com/drupal/drupal/commit/82307e02cf974d48335e723c93dfe343894e1a61# diff-5c54acb01b2253384cfbebdc696a60e7

[5]https://www.drupal.org/SA-CORE-2019-002

1.6 代码审计从0到1——Centreon One-click To RCE

作者:知道创宇404实验室 huha

代码审计的思路往往是多种多样的,可以通过历史漏洞获取思路,也可以通过黑盒审计快速确定可疑点。本节侧重于通过白盒审计思路,对Centreon V20.04的代码审计过程进行一次复盘,文中提及的漏洞均已提交官方并修复。

1.6.1 概述

Centreon是法国Centreon公司的一套开源系统监控工具。该工具主要提供对网络、系统和应用程序等资源的监控功能。Centreon的强大之处在于其灵活性和可扩展性,能够适应不同类型的IT环境。通过Centreon,用户可以实时监控性能指标、事件,并能迅速应对潜在问题,从而确保系统稳定运行,提高业务效率。

1.6.2 Centreon代码基本结构

Centreon源代码目录组成如图1-21所示。

centreon/www/网站根目录如图1-22所示。

图1-21 Centreon源代码目录组成

图1-22 centreon/www/网站根目录

centreon/www/include/核心目录结构如图1-23所示。

核心目录概述如下。

1)centreon/www/index.php是网站的入口文件。用户进入网站会先进行登录认证,登录成功后进入后台。

2)centreon/www/main.php与centreon/www/main.get.php分别对应PC端与移动端的路由功能。根据不同的参数,用户可以加载到后台不同的功能页面。在实际调试过程中,我发现使用main.php加载对应的功能页面时,最终会调用main.get.php,所以路由部分直接看main.get.php即可。

3)centreon/www/include/目录包含核心功能代码、公共类代码。有些功能代码可以直接通过路径访问,有些则需要通过main.get.php进行路由访问。

4)centreon/www/api/目录下的index.php是另一个路由功能,可以实例化centreon/www/api/class/*.class.php、centreon/www/modules/、centreon/www/widgets/*/webServices/rest/*.class. php、centreon/src/中的类并调用指定方法。

在审计代码的时候,有两个重要的关注点。

1)重点审查centreon/www/include/和centreon/www/api/class/两个目录,因为这两个目录下的功能点可以通过centreon/www/main.php或centreon/www/api/index.php路由访问。

2)重点寻找绕过登录认证或者越权的方式,否则后台漏洞难以被攻击者利用。

图1-23 centreon/www/include/核心目录结构

1.6.3 代码分析

下面简要分析centreon/www/目录下的部分脚本。

1.centreon/www/index.php

index.php会进行登录认证,检查是否定义$_SESSION["centreon"]变量,该变量的值在管理员登录后设置。用户的登录方式有两种——使用账号、密码和token,相关逻辑在/centreon/www/include/core/login/processLogin.php中。不止index.php,centreon/www/include/下的文件都包括检查Session的代码。

2.centreon/www/main.get.php

这是主要的路由功能,在程序开头对数据进行过滤。使用fiter_var()过滤处理$GET数组,对特殊字符进行编码,有效地防御了一些XSS攻击,比如可控变量在引号中让其无法进行标签闭合,无法逃逸单引号,如图1-24和图1-25所示。

图1-24 使用fiter_var()过滤处理$GET数组

图1-25 对特殊字符进行处理

对于GET和_POST中的指定参数,程序会进行过滤处理,对数据类型进行限制,对特殊字符进行编码,如图1-26所示。

图1-26 对指定参数进行处理

最终,_GET或_POST数组赋值到$inputs数组中,如图1-27所示。

图1-27 _GET或_POST数组赋值到$inputs数组中

全局过滤数据后,程序引入公共类文件和功能代码,如图1-28所示。

图1-28 程序引入公共类文件和功能代码

在第99行,centreon变量从hcader.php的SESSION中取出,认证用户是否登录,如图1-29所示。

图1-29 变量从SESSION中取出

通过登录认证后,程序会查询数据库,获取页面与URL的映射关系,并通过p参数找到对应的URL,执行路由操作。页面与URL的映射关系如图1-30所示。

图1-30 页面与URL的映射关系

接着在第248行include_once $url中引入centreon/www/include/下对应的脚本,如图1-31所示。

图1-31 引入对应的脚本

这里将页面与URL的映射关系存储到本地,方便后续查询,如图1-32所示。

图1-32 页面与URL的映射关系存储到本地

3.centreon/www/api/index.php

这是另外一个路由功能,如图1-33所示。

图1-33 路由功能

同样需要验证登录,第104行$_SERVER['HTTP_CENTREON_AUTH_TOKEN']可以在请求头中伪造,但是并不能绕过登录验证。接着可以跟进查看CentreonWebService::router方法。

在/api/class/webService.class.php中,object和action参数是可控的,如图1-34所示。

第311行判断isService是否为true,如果是,webService['class']赋值为dependency-Injector['centreon.webservice']->get($object),否则赋值为webservicePath(object)如图1-35所示。

图1-34 object和action参数可控

图1-35 判断isService

第313行centreon.webservice属性值如图1-36所示,对应的是centreon/src目录下的类。

$webServicePaths变量包含的类路径如图1-37所示。

在第346行。检查类中是否存在对应方法(见图1-38),在第374行调用该方法,但是在第350到369行进行了第二次登录认证,所以之前$_SERVER['HTTP_CENTREON_AUTH_TOKEN']伪造并没能绕过登录验证。

图1-36 centreon.webservice属性值

图1-37 $webServicePaths变量包含的类路径

图1-38 第346行检查类中是否存在对应方法

1.6.4 过滤处理

除了以main.get.php开头的全局过滤操作,程序中的其他过滤操作相对分散。为了防范SQL注入攻击,使用PDO进行参数化查询。对于那些在PDO中直接拼接的参数,程序会单独调用函数进行过滤处理。例如,在执行数据库更新操作时,updateOption()函数会执行query操作,其中$ret["nagios_path_img"]是可控的。但是,这里会调用escape()函数对其进行转义处理,如图1-39所示。

图1-39 调用escape()函数进行转义处理

1.6.5 路径限制

在不通过路由的情况下,直接访问对应路径的功能代码一般是不被允许的。例如,直接访问generateFiles.php页面是不被允许的,如图1-40所示。

图1-40 直接访问generateFiles.php页面

可以看到,第39行检查oreon参数是否存在,如果不存在则直接退出。刚才在分析main.get.php中提到,header.php会初始化oreon参数,这就是通过main.get.php去访问某些功能点的原因。当然有一些漏网之鱼,比如rename.php页面(见图1-41),这里只是检查SESSION是否存在,在登录状态下,可以通过路径直接访问该页面。

图1-41 rename.php页面

1.6.6 从One-click到RCE

接下来对One-click利用链进行分析。

1.XSS

在上一节的最后,我们关注了通过路径访问和通过路由访问的区别。这是因为在main.get.php中通过路由访问会经过全局过滤处理,而直接通过路径访问则没有这样的处理。这就产生了潜在的漏洞。通过这个思路,我们可以找到一个XSS漏洞:在rename.php中,程序将攻击者可控的内容直接打印输出,并且没有进行编码处理。此外,程序还缺乏HttpOnly和CSP等攻击缓存机制。当管理员点击精心构造的恶意链接时,将触发XSS漏洞并执行任意JS代码,从而导致Cookie泄露。

漏洞入口rename.php如图1-42所示。

图1-42 漏洞入口rename.php

正如前面提到的,第46行验证SESSION是否存在,所以受害者只要处于登录状态即可,第59行echo直接打印widgetObj->rename($_REQUEST)返回的值,在rename函数中对params['newName']进行一些验证,最后返回$params['newName'],因为这里直接通过路径访问,没有经过任何过滤处理,如图1-43所示。

图1-43 返回params['newName']

所以,将elementId设置为title_1(任意数字),newName设置为<script>标签即可,如图1-44所示。

图1-44 设置newName为<script>标签

2.授权RCE

程序在使用Perl脚本处理mib文件时,没有对反引号中的内容进行正确的过滤处理,攻击者可以利用通过XSS攻击窃取的凭证登录,并上传恶意文件,从而实现远程代码执行。

我们顺着CVE-2020-12688的思路,全局搜索"shell_exec("关键字符串,formMibs.php调用了shell_exec函数,如图1-45所示。

查看源码,第38行执行了shell_exec(command)(我们发现command从$form中取值),第14行添加var_dump($form),以打印$form变量,方便调试,如图1-46所示。

图1-45 formMibs.php调用了shell_exec函数

图1-46 部分源码

之前记录的页面与URL的映射关系现在就可以派上用场了,设置page为61703,通过main.php或main.get.php路由到formMibs.php(也就是文件上传功能),如图1-47所示。

图1-47 文件上传功能

调试发现,formMibs.php中第31行的$values["tmp_name"]是不可控的缓存文件名,$manufacturerId可以通过上传数据包中的mnftr字段进行修改,但是会被filter_var()处理,只能为整数,如图1-48所示。

图1-48 $manufacturerId只能为整数

虽然缓存文件名是不可控的,但是上传的mib文件内容可控。shell_exec()执行的命令实际为以下形式(xxx.mib代表缓存文件名):

centFillTrapDB是一个Perl脚本,代码在/bin/centFillTrapDB中,用use引入,如图1-49所示。

图1-49 引入centFillTrapDB模块

use命令寻找的路径默认在@INC下,但我们不知道具体位置,可以进行全局搜索,如图1-50所示。

图1-50 全局搜索

最后在usr/share/perl5/vendor_perl/centreon下找到script目录,其中有我们想要的文件,如图1-51所示。

图1-51 找到文件

我们把centFillTrapDB模块拉出来做静态分析,发现存在命令执行且内容可控的位置。实际调试发现最终分支是进入第541行,第540行和第543行是我添加的调试代码,如图1-52所示。

图1-52 调试代码

在Perl的反引号内可以执行系统命令,第534行$mib_name可控,所以$trap_lookup可控。对于mib文件来说,$mib_name为DEFINITIONS::=BEGIN前面方框部分,空格会被过滤,但可以用${IFS}代替,如图1-53所示。

图1-53 mib文件中的$mib_name

为了方便构造mib文件,我们打印出反引号中的命令,并在服务器Shell中进行测试,如图1-54所示。

图1-54 在服务器Shell中进行测试

构造/tmp/1.mib文件,如图1-55所示。

图1-55 构造/tmp/1.mib文件

执行以下命令:

可以清晰地看到command,并且执行了curl命令,如图1-56所示。

图1-56 执行curl命令

修改mib文件中的命令,在浏览器上传进行测试,成功执行whoami并回显,如图1-57所示。

图1-57 成功执行whoami并回显

1.6.7 防御建议

要防御此类漏洞,建议将Centreon更新到最新版本。及时更新软件和框架可以修复已知漏洞,提高系统的安全性。

1.6.8 参考链接

https://github.com/TheCyberGeek/Centreon-20.04

1.7 MyBB 18.20:从存储型XSS漏洞到RCE漏洞分析

作者:知道创宇404实验室 LoRexxar'

2019年6月,RIPS团队在博客中分享了一篇文章“MyBB<=1.8.20: From Stored XSS to RCE”。文章中主要提到了一个MyBB 18.20中存在的存储型XSS漏洞以及一个后台文件上传绕过漏洞。

1.7.1 漏洞触发要求

(1)存储型XSS漏洞

❑拥有可以发布信息的账号权限。

❑服务器端开启视频解析功能。

❑MyBB版本为18.20及以下。

(2)后台任意文件创建漏洞

❑拥有后台管理员权限(换言之就是需要有管理员权限的账号来触发漏洞)。

❑MyBB版本为18.20及以下。

1.7.2 漏洞分析

在原文描述中,多个漏洞被构建成一个利用链。但从漏洞分析角度来看,我们可以单独讨论这两个漏洞:存储型XSS漏洞、后台任意文件创建漏洞。

(1)存储型XSS漏洞

在MyBB以及大部分论坛类CMS中,无论文章、评论还是其他内容,通常需要在内容中插入图片、链接、视频等。为了实现这一功能,系统采用了一种被称为“伪标签”的解析方式。

也就是说,用户通过在内容中加入[url]、[img]等“伪标签”,后台就会在保存文章或者解析文章的时候,把这类“伪标签”转化为相应的<a>、<img>标签,然后输出到文章内容中。这种方式会以事先规定好的方式解析和处理内容和标签,也就是所谓的“白名单防御”。这种语法被称为BBCode。

这样,攻击者就很难构造存储型XSS漏洞了,因为除了这些标签以外,其他的标签都不会被解析(所有的尖括号和双引号都会被转义),转义代码如下。

在这看似严密的防御方式下,我们不如重新梳理下MyBB的处理过程。

/inc/class_parse.php中第435行的parse_mycode函数主要负责处理BBCode,代码如下。

当服务器端收到传输的Payload数据,它将首先处理并解析与[img]标签相关的语法。接着,如果$this->options['allow_videocode']被激活(默认情况下是启用的),服务器端会开始解析[video]标签的相关语法。之后,它会对[list]标签进行处理。在代码的第488行,服务器端将针对[url]等其他标签进行相应的处理操作,代码如下。

我们可以简化这个流程,假设在发给服务器端的Payload数据中输入:

后台会首先处理[video],然后Payload数据就变成:

接着,后台会处理[url]标签,最后Payload数据变成:

乍一看,似乎没有什么问题。每个标签数据都会被拼接到HTML标签对应的属性内,并且还会经过htmlspecialchars_uni处理,无法逃逸双引号的包裹。

但假如我们输入Payload数据为[video=youtube]http://test/test#[url]onload=alert();//[/url]&1=1[/video]首先查看函数/inc/class_parse.php第1385行mycode_parse_video,如图1-58所示。

链接经过parse_url处理被分解为:

然后在第1420行中,各个参数会被做相应处理,由于必须保留“=”以及“/”,所以这里我们选择把Payload数据放在fragment中,如图1-59所示。

图1-58 函数mycode_parse_video

图1-59 在第1420行中各个参数会被做相应处理

在第1501行case youtube中,Payload数据被拼接到id上。

最后id会经过一次htmlspecialchars_uni处理,然后生成模板,如下所示:

当然,这并不影响我们向服务器发送的Payload数据。

到此,Payload数据变成了:

紧接着再经过对[url]的处理,上面的Payload数据变为:

我们再对上面的Payload数据进行简化,链接由[video=youtube]http://test/test#[url]onload=alert();//[/url]&1=1[/video]变成<iframe src="//www.youtube.com/embed/<a href="http://onload=alert();//"..."></iframe>

由于我们在<iframe>标签中插入的href被转化为<a href="http://();//">格式,双引号未进行转义处理,因此<iframe>的href在<a>标签的href属性中被提前闭合。这导致原本应在<a>标签中的href数据直接暴露在标签之外,使得onload属性成为有效的属性。

最后,浏览器会执行简单的解析和分割操作,生成相应的标签。当URL链接加载完毕,相应标签的动作属性便可以被触发,如图1-60所示。

图1-60 标签的动作属性被触发

(2)后台任意文件创建漏洞

在MyBB管理员后台中,管理员可以自定义论坛的模板和主题,除了普通的导入主题以外,可以直接创建新的CSS文件。当然,服务器端限制了管理员的这种行为,要求管理员只能创建后缀为.css的文件。

看上去没办法绕过这一限制,但值得注意的是,在代码中会先将文件名写入数据库,如图1-61所示。

图1-61 代码中先将文件名写入数据库

紧接着我们看一下数据库结构,如图1-62所示。

图1-62 数据库结构

可以很明显地看到,name的类型为varchar,且长度只有30位。

如果我们在上传的XML文件中构造name文件名为tttttttttttttttttttttttttt.php.css,name文件内容在存入数据库时会被截断,并只保留前30位,也就是tttttttttttttttttttttttttt.php,代码如下:

紧接着我们需要寻找一个获取name并创建文件的位置。

在/admin/modules/style/themes.php的第1252行,$query变量被从数据库中提取出来,如图1-63所示。

图1-63 $query变量被从数据库中提取出来

$theme_stylesheet的name作为字典的键,被写入相关数据。

当$mybb->input['do']=="save_orders"时,当前主题会被修改,如图1-64所示。

图1-64 当$mybb->input['do']=="save_orders"时,当前主题会被修改

在保存了当前主题之后,后台会检查每个文件是否存在,如果不存在,则会获取name并写入相应的内容。可以看到,我们成功把phpinfo写入了PHP文件,如图1-65所示。

图1-65 成功把phpinfo写入了PHP文件

1.7.3 漏洞复现

(1)存储型XSS漏洞

首先找到任意一个发送信息的地方,如发表文章、发送私信等,如图1-66所示。

图1-66 找到任意一个发送信息的地方

发送以下信息:

受害者只要阅读到攻击者发送的信息,就会触发该XSS漏洞,如图1-67所示。

图1-67 阅读即可触发漏洞

(2)后台任意文件创建漏洞

找到后台加载Theme处,如图1-68所示。

图1-68 后台加载Theme处

构造上传文件test.xml:

注意要勾选Ignore Version Compatibility。

然后查看Theme列表,找到新添加的Theme,如图1-69所示。

图1-69 找到新添加的Theme

然后单击Save Stylesheet Orders按钮,接着根据tid和设置的name得到URL(/Upload/cache/themes/theme{tid}/{name}),访问该URL即可触发漏洞,如图1-70所示。

1.7.4 补丁分析

官方更新补丁链接如下:https://github.com/mybb/mybb/commit/44fc01f723b122be1bc8d aaca324e29b690901d6

(1)存储型XSS漏洞

在这里,<iframe>标签中的链接被encode_url函数重新处理。一旦链接被转义,[url]便不会再被解析,从而避免了潜在的问题,如图1-71所示。

图1-70 保存并访问相应tid地址的文件

图1-71 <iframe>标签中的链接被encode_url函数重新处理

(2)后台任意文件创建漏洞

补丁代码在判断文件名后缀之前加入了对文件名进行字符数截断的操作,这样攻击者就无法通过数据库中字符截断功能来构造特殊的name了,如图1-72所示。

图1-72 在判断文件名后缀之前加入了对文件名进行字符数截断的操作

1.7.5 防御建议

建议更新MyBB到最新版本。

1.7.6 参考链接

[1]https://blog.ripstech.com/2019/mybb-stored-xss-to-rce/

[2]https://zh.wikipedia.org/wiki/BBCode

1.8 Chrome扩展安全问题

作者:知道创宇404实验室 billion

本节主要介绍Chrome插件中潜在的两类安全问题:一类是插件的content_scipt错误代码编写,另一类是CSP错误的规则设置。

1.8.1 Chrome插件体系

一个完整的Chrome插件可被划分成popup_script、background_script、content_script、devtools_script等多个JavaScript脚本文件、manifest.json配置文件。

1)popup_script:主要用于控制插件的弹出页面。

2)background_script:后台脚本,可以用来监听Chrome标签页新建/关闭等事件,并且该脚本是常驻后台的。

3)content_script:可以当作Web页面和background_script等脚本沟通的桥梁。

4)devtools_script:可以用来操作控制台的调试。

5)manifest.json:配置文件,用于设置插件的各种属性和权限。

关于Chrome插件更详细的介绍,读者可以参考Chrome扩展文档,这里我们主要学习content_script以及CSP规则导致的安全问题。

一些开发者在具体实现content_script的主要功能时,有以下几种常见做法。

1)contentscript和backgroundscript互相通过message事件(postMessage/onMessage)进行通信。

2)将数据存到一个大家都可以访问的位置缓存。

除此之外,content_script还可以直接向Web页面中注入JS/HTML代码,接收Web页面发送的message事件。

下面举一个例子,来学习这种模式有什么危害。

1.8.2 CVE-2019-12592

Evernote Web Clipper的content_script为BrowserFrameLoader.js,在JS代码中调用了window.addEventListener监听onMessage事件,所以可以在Web页面通过调用postMessage进行通信。

BrowserFrameLoader.js中的问题代码如下:

_installScript函数中有一处向Web页面添加Script标签的操作。可以发现,_installScript函数在installAllFrameSerializers函数中被调用:

this._getBundleUrl会对URL和页面进行一次拼接:

回溯installAllFrameSerializers函数,可以找到这么一处调用:

在某个变量上设置一个映射关系,当访问到i. MessageNames. INSTALL_SERIALIZER变量的时候,返回e=>this.installAllFrameSerializers(e)函数。

回溯INSTALL_SERIALIZER变量,找到如下定义:

接下来要找到触发方式,content_script中有一些比较容易和Web页面进行交互的事件(比如message事件)。在Web页面中直接调用postmessage是可以触发contentscript中的onMessage事件的。

BrowserFrameLoader.js文件中使用了start函数监听message事件,代码如下:

回调函数为_handleMessage,跟进到该函数的代码:

这里,i是一个动态调用的函数,来自this._requestHandlers[t]。我们动态调试一下,可以看到_requestHandlers的值,如图1-73所示。

图1-73 _requestHandlers的值

当t=EN_installFrameSerializer的时候,返回installAllFrameSerializers函数,这样就回到前面的问题代码了。

Payload如下:

Dom树如图1-74所示。

图1-74 Dom树

payload.html文件内容如下:

FrameSerializer.js文件内容如下:

访问payload.html,可以成功触发XSS漏洞,如图1-75所示。

图1-75 成功触发XSS漏洞

由于manifest.json中开启了all_frame,理论上将XSS代码插入所有的iframe会造成更大危害。

1.8.3 CSP问题

Chrome插件同样受到CSP规则的限制,可以在manifest.json中配置,如下所示。

默认情况下,Chrome Extension中CSP规则的设置是:

在CVE-2019-12592漏洞中,攻击者可以通过向Web页面添加<script>标签的方式进行XSS利用,但是Chrome插件自身会受到CSP策略的限制,如果开发者设置了更宽泛的CSP规则的话,比如直接允许内联标签,如下所示:

这种情况确实非常罕见,并且Chrome Extension V3版本已经取消了unsafe-inline这种配置,这意味着通过直接添加标签的方式来实现XSS攻击的可能性越来越小了。

这里以McAfee WebAdvisor为例介绍内联脚本被限制时,如何利用HTML注入。

McAfee WebAdvisor的site_report.js文件中存在HTML注入代码,简化之后的代码如下:

所以只要控制URL参数,就可以向report页面插入HTML标签。测试Demo如下:

HTML的注入点已经存在,接下来是利用,如图1-76所示。

图1-76 HTML的注入点

(1)CSP规则

看起来离成功触发XSS漏洞已经很近了,但是在加载<script>时出现了图1-77所示错误。

manifest.json中未开启unsafe-inline,不能加载<script>标签以及内联事件,如下所示。

图1-77 加载<script>时出错

一种常见的做法是在允许的源内,找到一处JSONP,这样就可以执行JS代码了。

测试Demo如下:

Payload如下所示。

McAfee WebAdvisor虽然没有JSONP,但有一个添加白名单的功能,如图1-78所示。

可以利用XSS漏洞在用户不知情的情况下,设置一个恶意的URL地址,这样就会让该插件最主要的功能失效。

图1-78 McAfee WebAdvisor中添加白名单的功能

测试Demo如下:

用户单击button时触发点击劫持事件,如图1-79所示。

图1-79 单击button时触发点击劫持事件

但是依旧会触发CSP规则,如图1-80所示。

图1-80 触发CSP规则

实际上,我们可以对这个页面进行一些优化,例如,可以完全隐藏eval.com,以提高页面的整洁度。此外,我们也可以考虑将按钮设计得更有吸引力,以提高用户点击的可能性。

(2)jQuery特性

在本地测试环境用jQuery添加<script>标签,就能找到劫持不成功的原因了,如下所示。

jQuery在添加<script>标签时会经过一层转换,这从网络请求也能看出来。加载1.js的请求是通过ajax发出的,如图1-81所示。

大致过程是jQuery会把<script>标签中src属性相应的地址提取出来,单独访问该地址以获取响应,再创建一个Script,经过这样一次转换之后,原来的src属性就没有了,因此,在将新创建的<script>标签添加到Dom时,由于缺少src属性,可能会出现内联错误。

图1-81 加载1.js的请求是通过ajax发出的

在这里添加一处断点,可以看到最后的<script>标签,如图1-82所示。

图1-82 添加一处断点

最后被添加到Dom中的<script>标签如图1-83所示。

图1-83 被添加到Dom中的<script>标签

跟进jQuery的源码,如图1-84所示。

可以发现,当type==module时,就不再通过ajax的方式来加载Script了,如图1-85所示。

图1-84 jQuery的源码

图1-85 不再通过ajax的方式来加载Script

所以可以在payload中的<script>标签中添加一个type属性,如下所示。

最后结果如图1-86所示。

图1-86 最后结果

1.8.4 防御建议

将相关软件和插件升级到最新版本,以确保已知漏洞被修复。

1.8.5 参考链接

[1]https://guard.io/blog/evernote-universal-xss-vulnerability

[2]https://developer.chrome.com/docs/extensions/ zbsvpmVEnXsWRAwLSLGCOrKRfpx/6zjV3oGYZZ0eYxtVnkW55il8dg5MlRSMfA1w

点击中间区域
呼出菜单
上一章
目录
下一章
×