HackerOne報告目前尚未公開,但在徵得了Symbol的允許後,本文將公開於此分享此次事件。在此,CertiK對Symbol提供的賞金獎勵,以及對公開分享漏洞發現的許可表示感謝。
Symbol wallet是一個基於Electron的桌面應用程式,此次發現的漏洞與Electron配置有關。Electron是不是聽起來很耳熟?但它可不是你在物理化學課上學到的那個電子。在展開漏洞分析之前,不妨先來看看本文中的Electron是什麼,在安全層面有什麼值得注意的事項。
Electron是什麼
Electron是由GitHub開發和維護的開源軟體框架,它允許開發人員使用HTML,CSS和Javascript等網路技術來構建跨平臺的桌面應用程式。
Electron透過將Chromium引擎和Node.js組合到一起來實現這一目標。一些知名的Electron應用程式包括Atom編輯器,VisualStudio Code和Slack等。
使用Electron的優點:
· Web開發人員可以使用主要的Javascript框架庫(包括Angular,React和Vue)構建能在不同作業系統上執行的跨平臺桌面應用程式。此過程無需再花費時間學習新的程式語言。
· 除錯基於Electron的應用程式比除錯傳統的桌面應用程式容易。Chromium中的DevTools擴充套件允許開發人員使用和Web應用程式相同的方式除錯其基於Electron的應用程式。
Electron的安全性以及Node.js的危險性
基於Electron的應用程式本質上是一個Web應用程式,因此它包含常見的Web漏洞,例如跨站點指令碼(XSS)、Sql注入、身份驗證和授權漏洞。
Electron提供許多輔助桌面應用程式開發的API,此外,它還可以使用Node.js模組。
Node.js允許基於Electron的應用支援比在Web瀏覽器中執行的Web應用更多的功能。但是,啟用Node.js會帶來一定的安全風險。如果攻擊者可以找到在應用程式中注入JavaScript,就可以在目標的計算機上執行系統命令。
如果想要檢查Electron應用程式是否在啟用了Node.js,使用者可以在開發控制檯中傳送模組匯入功能“require”。在macOS中,控制檯可以透過同時按“option + command + i”開啟。
如果Node.js未被啟動,控制檯將返回錯誤訊息 “require is not defined”:
如果Node.js被啟用,控制檯將返回"require"的相關資訊:
在開發控制檯中傳送以下命令,就能在macOS中彈出計算器:
require('child_process').exec('/System/Applications/Calculator.app/Contents/MacOS/Calculator')
為了減輕因為注入JavaScript而引起的遠端程式碼執行的風險,從版本5.0.0開始,Electron預設禁用了程式對Node.js模組的訪問。開發人員可以透過在配置檔案中將“nodeIntegration”設定為true來啟用對Node.js模組的使用,從安全形度來說並不推薦。
值得注意的是在2018年,Electron被發現有一個嚴重漏洞可被攻擊者利用來訪問Node.js模組,即使在配置中已經被禁止。參考文獻1也對此進行了詳細說明,因此在開發時請務必使用最新版本的Electron。
Symbol Wallet 遠端執行程式碼漏洞演示
在瞭解了基於Electron的應用程式相關特徵之後,現在可以深入探討在Symbol桌面錢包中發現的漏洞。
Symbol桌面錢包是開源的,可以在其Github(參考文獻2)中找到該應用的原始碼。build.js(參考文獻3)是其應用程式的Electron構建配置檔案。下面這段Build.js中的程式碼檢查程式是否在“darwin”(macOS)上執行。如果不是,app.on將使用“createWindow”函式建立瀏覽器視窗。
....code...
if (process.platform === 'darwin') {
app.on('ready',createMac)
} else {
app.on('ready',createWindow)
....code...
在“createwindow”函式中,函式內部的“ windowOptions”變數包含瀏覽器視窗配置選項。注意,紅色部分顯示的行將“nodeIntegration”變數設定為true,這表示此應用程式啟用了Node.js。
...code...
function createWindow(){
const windowOptions = {
minWidth: width,
minHeight: height,
width: width,
height: height,
title: app.getName(),
titleBarStyle: 'hiddenInset',
webPreferences: {
nodeIntegration: true,
},
resizable: true,
}
....code...
mainWindow= newBrowserWindow(windowOptions)
}
根據build.js配置檔案,可以瞭解到如果此應用在Windows作業系統上執行,Node.js將被啟用。為了利用啟用的Node.js,攻擊者需要在應用程式中注入任意的JavaScript。攻擊者一般可以透過利用XSS(跨站點指令碼)漏洞或者在當前Electron視窗中載入任何包含攻擊者注入的JavaScript的網站來實現攻擊。
Symbol桌面錢包(v9.7版)提供了瀏覽“新聞”的功能,只要使用者點選新聞中的連結,應用程式便會從錢包視窗載入外部網站(圖中展示的是Github)。
那麼漏洞又是如何被利用的呢?
為了演示該漏洞利用的流程,技術人員在個人網站上託管了以下程式碼段。在Github上可以很容易的放置指向其網站的URL。當“nodeIntegration”設定為true並啟用Node.js,在“child_process”模組的幫助下可以將任意的JavaScript執行升級為遠端程式碼執行。
使用者訪問包含payload的頁面,並點選頁面裡的“Close”按鈕後,使用者的計算機上將彈出計算器。在目標系統中彈出計算器是證明成功利用程式碼執行漏洞的一種方法。
Proof-of-Concept:
<!DOCTYPEhtml>
<h2>click me</h2>
<button type="button" onClick="rce_calc()">Submit</button>
<script>
functionrce_calc(){
const{ exec } = require('child_process');
exec('calc');
}
</script>
Symbol在修復中將“nodeIntegration”設定為false,禁止了JavaScript對Node.js模組的訪問。此更改已經反映在了他們當前的build.js(參考文獻4)檔案中。他們還更新了“新聞”功能,停止了將遠端網站載入到Electron視窗中的行為。
探索基於Electron的加密貨幣錢包
做為安全研究員,當在一個程式中發現漏洞,我們總會嘗試去探索此類漏洞是否在別的應用中存在。透過網際網路搜尋,CertiK安全團隊發現了另一個基於Electron的加密貨幣錢包: MyCrypto。在測試時,技術人員發現MyCrypto將“nodeintegration”設定為true,並啟用了Node.js。雖然沒有找到攻擊此配置的辦法。但是我們不應該給攻擊者將“self-xss”轉化為命令程式碼執行的機會。
CertiK旨在為加密社羣的安全做出貢獻,並幫助企業保護使用者資產。技術人員在對方的Github 倉庫中提交了Issue。
MyCrypto十分重視,並回復該漏洞將在下一版本中修復。
重點提示
Electron本身是非常優秀的軟體框架,但開發人員要注意不要因為配置錯誤而使程式暴露在危險之中。在產品中使用新技術時要小心,要保持謹慎並瞭解潛在的安全風險。這裡CertiK安全團隊總結了幾個要點來提高基於Electron的應用程式的安全性:
· 在生產版本中移除對development console的訪問。
· 除非應用程式絕對必要,否則將“nodeintegration”設定為false。
· 使用“event.preventDefault()來禁止應用程式載入外部網頁。
· 使用React,Vue或Angular(2+)等前端框架開發應用程式,以減少應用程式包含XSS(跨站點指令碼)漏洞的機會。
· 持續使用最新版本的Electron框架,並保持更新。
· 開發Electron應用程式時,請務必閱讀參考官方安全指南(參考文獻7)。其中包含了可以提高Electron的應用的安全性的建議。
無論是由內部安全團隊還是第三方公司執行安全審計和滲透測試,對於確保系統的安全性都是至關重要的。專業的安全人員會試圖從“惡意駭客”的角度來破壞系統,幫助在真正的駭客利用漏洞之前識別和補救漏洞。
對於專業安全服務提供商而言,要提高安全測試水平的唯一途徑就是不斷學習。CertiK的安全工程師自始至終都在透過廣泛涉獵不同目標來提高自身的滲透測試技能,從而為客戶提供最佳的滲透測試服務。
參考文獻:
https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/cve-2018-1000136-electron-nodeintegration-bypass/
https://github.com/nemfoundation/symbol-desktop-wallet
https://github.com/nemfoundation/symbol-desktop-wallet/blob/14ddfd44fe9a54b54f8261dfaa68b2f88be211ce/public/build.js
https://github.com/nemfoundation/symbol-desktop-wallet/blob/master/public/build.js#L237
https://github.com/terra-project/station-electron/blob/5a919b87323c9d1d9c76f7c4a7deff5d731d235e/public/electron.js
https://www.electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity
https://www.electronjs.org/docs/tutorial/securit