文中叙述了创作者在参与Discord众测的历程中,根据好几个bug的开发利用,取得成功发觉了Discord桌面应用的远程控制代码实行漏洞(RCE),获得了$5,300的奖赏。
Discord 是一款适用玩家一体化视频语音和聊天的即时通讯(IM)手机软件。 现阶段 Discord 早已遮盖 Windows、MacOS、Android、iOS、Windows Phone等各种流行服务平台。
我选择测试Discord的缘故
因为我对Electron架构的APP漏洞测试较为有工作经验,而恰好Discord运用恰好是根据Electron架构开发设计的,且我也是一名Discord客户,因此本着测试盘玩的心理状态,我便对Discord开展了剖析。
发觉的漏洞
我发现下列Discord运用存有的三个bug,开发利用最后产生了RCE漏洞:
- Missing contextIsolation(contextIsolation功能未开启)
- XSS in iframe embeds(iframe置入功能中的XSS)
- Navigation 导航栏限定功能绕开 (Navigation restriction bypass,CVE-2020-15174)
contextIsolation功能未开启(Missing contextIsolation)
在测试Electron架构时,通常我能先查验BrowserWindow API的选择项,当建立电脑浏览器对话框时BrowserWindow API会被启用。测试时,我便在想,当Electron渲染器(renderer)载入时,如何的随意JS代码实行才会造成RCE?
尽管Discord的Electron架构并并不是开源系统的,但Electron的JS代码是存放在运用当地,所以我是可以获取查询到的。根据当地JS代码的查询,我发现在APP主界面后观众席,应用了下列方式函数公式:
从以上代码精彩片段中,可以看得出,大家主要必须查验的是在其中的nodeIntegration和contextIsolation配备,这儿的nodeIntegration都被配备为了更好地false,且原来未修改版本号的和contextIsolation也被配备为了更好地false。
假如nodeIntegration为true,那麼web页面的JS代码可以根据启用require()方式应用Node.js功能。例如,在Windows系统中实行下列计算方式calc.exe程序流程的代码:
而在Discord这儿,nodeIntegration为false,因此我就不可以启用require()去应用Node.js功能。殊不知,依然具有一种浏览Node.js功能的方式。下面晓听我渐渐地表述。
Discord中的另一关键功能contextIsolation也配备为了更好地false,该功能用于防护不信任的內容,因此,假如你要清除RCE,那麼该功能也不应当配备为false。假如contextIsolation为false,那麼web页面中的JS可以危害Electron内部结构3D渲染时的JS代码和预加载脚本制作实行,(这儿Electron内部结构3D渲染时的JS代码指Web网页页面以外的JS脚本),例如,假定用Web网页页面JS中的方式函数公式,把Electron内嵌JS的方式Array.prototype.join遮盖掉,那麼Web网页页面以外的JS脚本在载入join方式时,便会启用之后被遮盖的方式函数公式。
这种做法是很危险的,由于这样一来,可以不需要考虑到nodeIntegration配备,立即用遮盖的方法,就可以让Electron容许Web网页页面以外的JS脚本应用Node.js特点,这类方法即使在nodeIntegration配备为false的情形下,都还还可发展为RCE漏洞。
我顺带提一下,相近的缺点早在2016年我还在Cure53企业时就早已看到了,那时候我汇报给了Electron安全性精英团队,之后在Electron架构中就引进了contextIsolation功能。下列为近期才公布的关键技术PDF:
- https://drive.google.com/file/d/1LSsD9gzOejmQ2QipReyMXwr_M0Mg1GMH/view
- https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en
contextIsolation功能的引进目地取决于防护Web网页页面和Web页面以外的JS代码,让他们在实行时不易造成互相影响。该功能十分必须,由于假如存有不被信赖的主要内容或实际操作,便会造成安全隐患。而在Discord这儿,该功能却被配备为false,被禁止使用了。因而,遵循以上遮盖JS脚本的方式,我对Discord的这里缺点进行了测试。
因为Electron内嵌的JS代码在3D渲染时可以在随意的Electron APP中实行,因此一般我测试Electron的RCE时,习惯性最先在3D渲染时要Electron内嵌的JS代码来测试。在我的内容中,我写到了可以用Electron在实行navigation timing时的代码来完成RCE,该缺点不但可以从代码中发觉,还可从其他地区发觉(之后我能发布具体的PoC案例)。可是,因为总体目标运用差异的Electron版本号应用或BrowserWindow选择项设定,Discord这儿Electron运作运作时,我具体测试的PoC一直不稳定,因此我将测试关键放到了预加载脚本制作上。
测试预加载脚本时,我发现Discord运用暴露了DiscordNative.nativeModules.requireModule('MODULE-NAME')方式函数公式,该函数功能取决于可以根据其把一些控制模块功能启用到Web网页页面中去完成。殊不知,经测试发觉,我并无法合理地启用相近child_process的控制模块完成RCE,但却可以用以前说过的遮盖方式,遮盖掉Discord Electron中内嵌的JS方式,影响暴露控制模块的实行,为此完成RCE。
下列为有关的PoC。当遮盖掉Discord Electron中内嵌的RegExp.prototype.test和Array.prototype.join方式,启用"discord_utils"控制模块中界定的getGPUDriverVersions方式函数公式时,可以开启实行calc.exe程序流程:
getGPUDriverVersions方法函数用于执行"execa"库启用:
通常,"execa"库又是用于执行nvidiaSmiPath自变量中规定的"nvidia-smi.exe"电脑显卡程序流程的,但因为遮盖掉了RegExp.prototype.test 和 Array.prototype.join方法,"execa"库文件nvidiaSmiPath用户标识符即被遮盖为了更好地"calc"。
从总体上,nvidiaSmiPath中的自变量遮盖必须更改下列2个JS文档:
- https://github.com/moxystudio/node-cross-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L36
- https://github.com/moxystudio/node-cross-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L55
到了这步,"nvidia-smi.exe"可以取得成功被更换为"calc",那麼下面只需寻找执行JS编码的方法就可以取得成功完成RCE了。
iframe置入作用中的XSS
在我试着发掘XSS的历程中,我发现Discord APP适用相近autolink或Markdown的作用,这有点儿意思。经检测,假如Discord客户信息交流中有视频贴子,如You-tube URL,那麼这儿相近Markdown的iframe置入作用就可以表明出视频播放软件(video player)来。
因为Discord牵涉到客户的各种各样社交媒体信息交流,因此其适用Open Graph Protocol(对外开放內容协议书),假如客户信息交流中包括OGP信息内容,那麼Discord运用即会展现出在其中产生的网页页面文章标题、叙述、缩图和一些相应的短视频內容。当客户信息交流中的短视频URL连接被置入到iframe之后,Discord运用会获取出该短视频URL连接。后面,我没法查询到Discord运用有关的iframe置入作用详细说明文本文档,就只能在其CSP frame-src 命令中找寻案件线索,发觉其使用了下列CSP对策:
能够看见,在其中列举了容许iframe置入的对策(如对You-Tube, Twitch, Spotify短视频的置入)。下面,我便对这种网站域名一个一个开展检测,期待之中能在iframe短视频置入时开启XSS。通过检测,我发现网站域名sketchfab.com可以在iframe置入时造成XSS,这是一个简易的DOM-based XSS。下列就是我依据OGP协议书制做的一个PoC,当我将该URL连接以聊天话题发给另一位Discord客户时,点一下当中的iframe,便会开启随意的JS编码执行:
https://l0.cm/discord_rce_og.html
如今,尽管看到了XSS,可是开启的JS编码却只有在iframe中实行。因为Electron不容易把“Web网页页面以外的JS编码”载入进到iframe中,因此即使我遮盖了其iframe内嵌的JS方式,或是不可以启用Node.js有关作用。因而,要建立真正意义上的RCE,还必须跳出来iframe限定,在客户访问內容方面去考虑到。这就要在iframe架构中构建一个新页面,或是以iframe中导航栏(navigating)到另一URL中的高层对话框。
通过对有关编码的剖析,我发现Navigation restriction(导航栏限定)的关键编码中采用了"new-window" 和 "will-navigate"2个事情:
只需提升这儿,就可以在iframe架构中构建一个新页面,或是以iframe中导航栏(navigating)到另一URL中的高层对话框。殊不知,这儿存有着一个要我彻底意想不到的缺点。
Navigation restriction bypass (导航栏限定作用绕开,CVE-2020-15174)
在我对导航栏限定有关编码开展检验全过程中,我本来觉得iframe对导航栏(navigation)应该是有局限的,但我惊讶地发觉,iframe不知道怎的对导航栏体制居然沒有限定。我原本惦记着,"will-navigate"事情和preventDefault()会在导航栏姿势绕开产生以前开展相应的捕获或阻拦,可是这却沒有。
为了更好地开展导航栏绕开检测,我建立了一个简便的Electron运用,随后发觉,顶端导航栏(top navigation)中的"will-navigate" 事情并不会从iframe中跳出来,从总体上,假如顶端导航栏的隶属域和iframe的所属域同样,"will-navigate" 事情会跳出来,不然就不容易跳出来。这并非一种符合情理的操控个人行为,反而是个Bug。拥有这一Bug,我便能绕开导航栏限定了。最终,我要做的便是,导航栏到可以开启XSS的iframe网页页面,随后之中包括进RCE Payload编码。
最后,开发利用以上三个Bug,我取得成功在Discord运用中保持的远程控制执行命令(RCE)。
POC短视频:https://tinyurl.com/y5nx6zjy
系统漏洞解决
我根据Discord众测新项目汇报了这三个系统漏洞,以后,Discord安全性精英团队禁止使用了Sketchfab的置入作用,随后在iframe中添加了沙盒作用避免导航栏限定绕开,与此同时开启了contextIsolation作用。我因而获得了$5,000的BUG奖赏。
https://github.com/electron/electron/security/advisories/GHSA-2q4g-w47c-4674
此外,在其中的XSS系统漏洞汇报给Sketchfab后,获得了Sketchfab奖赏的$300;"will-navigate"事情Bug汇报给Electron后,被分派了CVE-2020-15174的系统漏洞序号。
参照由来:mksben