From 97319b3074f223e85996cd395a924c6cfc1674ee Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 7 Jan 2025 18:15:38 +0000 Subject: [PATCH] Translated ['src/network-services-pentesting/pentesting-web/electron-des --- .gitignore | 1 + hacktricks-preprocessor.py | 53 +++++--- .../electron-desktop-apps/README.md | 123 +++++++++++++++--- 3 files changed, 144 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 365859fbc..77edd91a0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ scripts/* book book/* hacktricks-preprocessor.log +hacktricks-preprocessor-error.log diff --git a/hacktricks-preprocessor.py b/hacktricks-preprocessor.py index 969d5333e..af5949449 100644 --- a/hacktricks-preprocessor.py +++ b/hacktricks-preprocessor.py @@ -7,7 +7,14 @@ from os import path from urllib.request import urlopen, Request 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=(),): @@ -27,7 +34,7 @@ def findtitle(search ,obj, key, path=(),): 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() title = href if href.startswith("http://") or href.startswith("https://"): @@ -45,19 +52,29 @@ def ref(matchobj): try: if href.endswith("/"): href = href+"README.md" # Fix if ref points to a folder - chapter, _path = findtitle(href, book, "source_path") - logger.debug(f'Recursive title search result: {chapter["name"]}') - title = chapter['name'] + 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") + logger.debug(f'Recursive title search result: {chapter["name"]}') + title = chapter['name'] except Exception as e: try: 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))}') - chapter, _path = findtitle(path.normpath(path.join(dir,href)), book, "source_path") - logger.debug(f'Recursive title search result: {chapter["name"]}') - title = chapter['name'] + 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"]}') except Exception as e: - logger.debug(f'Error getting chapter title: {path.normpath(path.join(dir,href))}') - print(f'Error getting chapter title: {path.normpath(path.join(dir,href))}') + logger.debug(e) + logger.error(f'Error getting chapter title: {path.normpath(path.join(dir,href))}') sys.exit(1) @@ -69,6 +86,7 @@ def ref(matchobj): return result + def files(matchobj): logger.debug(f'Files match: {matchobj.groups(0)[0].strip()}') href = matchobj.groups(0)[0].strip() @@ -76,19 +94,19 @@ def files(matchobj): try: for root, dirs, files in os.walk(os.getcwd()+'/src/files'): + logger.debug(root) + logger.debug(files) if href in files: title = href logger.debug(f'File search result: {os.path.join(root, href)}') except Exception as e: logger.debug(e) - logger.debug(f'Error searching file: {href}') - print(f'Error searching file: {href}') + logger.error(f'Error searching file: {href}') sys.exit(1) if title=="": - logger.debug(f'Error searching file: {href}') - print(f'Error searching file: {href}') + logger.error(f'Error searching file: {href}') sys.exit(1) template = f"""{title}""" @@ -97,6 +115,7 @@ def files(matchobj): return result + def add_read_time(content): regex = r'(<\/style>\n# .*(?=\n))' 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) logger.debug(f"Context: {context}") - logger.debug(f"Env: {context['config']['preprocessor']['hacktricks']['env']}") for chapter in iterate_chapters(book['sections']): logger.debug(f"Chapter: {chapter['path']}") 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']) 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) chapter['content'] = new_content diff --git a/src/network-services-pentesting/pentesting-web/electron-desktop-apps/README.md b/src/network-services-pentesting/pentesting-web/electron-desktop-apps/README.md index 35b6c7fd2..8225bc8dc 100644 --- a/src/network-services-pentesting/pentesting-web/electron-desktop-apps/README.md +++ b/src/network-services-pentesting/pentesting-web/electron-desktop-apps/README.md @@ -101,9 +101,9 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" /> ```javascript "start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors", ``` -## Electron Lokale Code-Injektion +## Electron Local Code Injection -Wenn Sie eine Electron-App lokal ausführen können, ist es möglich, dass Sie sie dazu bringen können, beliebigen JavaScript-Code auszuführen. Überprüfen Sie, wie: +Wenn Sie eine Electron-App lokal ausführen können, ist es möglich, dass Sie sie dazu bringen können, beliebigen JavaScript-Code auszuführen. Überprüfen Sie, wie dies geht in: {{#ref}} ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md @@ -111,7 +111,7 @@ Wenn Sie eine Electron-App lokal ausführen können, ist es möglich, dass Sie s ## RCE: XSS + nodeIntegration -Wenn **nodeIntegration** auf **ein** gesetzt ist, kann der JavaScript-Code einer Webseite die Node.js-Funktionen einfach durch Aufrufen von `require()` verwenden. Zum Beispiel ist der Weg, die Calc-Anwendung unter Windows auszuführen: +Wenn **nodeIntegration** auf **on** gesetzt ist, kann der JavaScript-Code einer Webseite die Node.js-Funktionen einfach durch Aufrufen von `require()` verwenden. Zum Beispiel ist der Weg, die Calc-Anwendung unter Windows auszuführen: ```html ``` -## **RCE: XSS + Alte Chromium** +## **RCE: XSS + Alte Chromium-Version** -Wenn das **chromium**, das von der Anwendung verwendet wird, **alt** ist und es **bekannte** **Sicherheitsanfälligkeiten** gibt, könnte es möglich sein, es zu **nutzen und RCE über ein XSS zu erhalten**.\ -Siehe ein Beispiel in diesem **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) +Wenn die **Chromium**-Version, die von der Anwendung verwendet wird, **alt** ist und es **bekannte** **Sicherheitsanfälligkeiten** gibt, könnte es möglich sein, sie zu **nutzen und RCE über ein XSS zu erhalten**.\ +Ein Beispiel finden Sie in diesem **Bericht**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) -## **XSS Phishing über interne URL Regex-Umgehung** +## **XSS-Phishing über internen URL-RegEx-Umgehung** Angenommen, Sie haben ein XSS gefunden, aber Sie **können RCE nicht auslösen oder interne Dateien stehlen**, könnten Sie versuchen, es zu **nutzen, um Anmeldeinformationen über Phishing zu stehlen**. @@ -266,9 +268,97 @@ Falls der von der Funktion verwendete **Regex** **anfällig für Umgehungen** is window.open("") ``` +## Remote-Modul + +Das Electron Remote-Modul ermöglicht **Renderer-Prozessen den Zugriff auf APIs des Hauptprozesses**, was die Kommunikation innerhalb einer Electron-Anwendung erleichtert. Das Aktivieren dieses Moduls bringt jedoch erhebliche Sicherheitsrisiken mit sich. Es erweitert die Angriffsfläche der Anwendung und macht sie anfälliger für Schwachstellen wie Cross-Site-Scripting (XSS)-Angriffe. + +> [!TIP] +> Obwohl das **remote**-Modul einige APIs vom Haupt- zu den Renderer-Prozessen exponiert, ist es nicht einfach, RCE nur durch den Missbrauch der Komponenten zu erhalten. Die Komponenten könnten jedoch sensible Informationen offenlegen. + +> [!WARNING] +> Viele Apps, die das Remote-Modul weiterhin verwenden, tun dies auf eine Weise, die **NodeIntegration im Renderer-Prozess aktiviert** erfordert, was ein **großes Sicherheitsrisiko** darstellt. + +Seit Electron 14 könnte das `remote`-Modul von Electron aus mehreren Gründen, die mit Sicherheit und Leistung zu tun haben, **nicht verwendet werden**. + +Um es zu aktivieren, muss es zuerst **im Hauptprozess aktiviert werden**: +```javascript +const remoteMain = require('@electron/remote/main') +remoteMain.initialize() +[...] +function createMainWindow() { +mainWindow = new BrowserWindow({ +[...] +}) +remoteMain.enable(mainWindow.webContents) +``` +Dann kann der Renderer-Prozess Objekte aus dem Modul importieren, das er mag: +```javascript +import { dialog, getCurrentWindow } from '@electron/remote' +``` +Der **[Blogbeitrag](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** weist auf einige interessante **Funktionen** hin, die vom Objekt **`app`** aus dem Remote-Modul bereitgestellt werden: + +- **`app.relaunch([options])`** +- **Startet** die Anwendung neu, indem die aktuelle Instanz **beendet** und eine neue **gestart** wird. Nützlich für **App-Updates** oder signifikante **Zustandsänderungen**. +- **`app.setAppLogsPath([path])`** +- **Definiert** oder **erstellt** ein Verzeichnis zum Speichern von **App-Protokollen**. Die Protokolle können mit **`app.getPath()`** oder **`app.setPath(pathName, newPath)`** **abgerufen** oder **modifiziert** werden. +- **`app.setAsDefaultProtocolClient(protocol[, path, args])`** +- **Registriert** die aktuelle ausführbare Datei als **Standard-Handler** für ein bestimmtes **Protokoll**. Sie können bei Bedarf einen **benutzerdefinierten Pfad** und **Argumente** angeben. +- **`app.setUserTasks(tasks)`** +- **Fügt** Aufgaben zur **Aufgaben-Kategorie** in der **Jump List** (unter Windows) hinzu. Jede Aufgabe kann steuern, wie die App **gestart** wird oder welche **Argumente** übergeben werden. +- **`app.importCertificate(options, callback)`** +- **Importiert** ein **PKCS#12-Zertifikat** in den **Zertifikatspeicher** des Systems (nur Linux). Ein **Callback** kann verwendet werden, um das Ergebnis zu verarbeiten. +- **`app.moveToApplicationsFolder([options])`** +- **Verschiebt** die Anwendung in den **Anwendungsordner** (unter macOS). Hilft, eine **Standardinstallation** für Mac-Benutzer sicherzustellen. +- **`app.setJumpList(categories)`** +- **Setzt** oder **entfernt** eine **benutzerdefinierte Jump List** unter **Windows**. Sie können **Kategorien** angeben, um zu organisieren, wie Aufgaben dem Benutzer angezeigt werden. +- **`app.setLoginItemSettings(settings)`** +- **Konfiguriert**, welche **ausführbaren Dateien** beim **Login** zusammen mit ihren **Optionen** (nur macOS und Windows) gestartet werden. +```javascript +Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"}); +Native.app.exit() +``` +## systemPreferences-Modul + +Die **primäre API** zum Zugriff auf Systemeinstellungen und **zum Auslösen von Systemereignissen** in Electron. Methoden wie **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** und **setUserDefault** sind alle **Teil von** diesem Modul. + +**Beispielverwendung:** +```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** + +* **Hört** auf **native macOS-Benachrichtigungen** über NSDistributedNotificationCenter. +* Vor **macOS Catalina** konnten Sie **alle** verteilten Benachrichtigungen abfangen, indem Sie **nil** an CFNotificationCenterAddObserver übergeben. +* Nach **Catalina / Big Sur** können sandboxed Apps weiterhin auf **viele Ereignisse** (zum Beispiel **Bildschirm sperren/entsperren**, **Volume-Mounts**, **Netzwerkaktivität** usw.) **abonnieren**, indem sie Benachrichtigungen **nach Namen** registrieren. + +### **getUserDefault / setUserDefault** + +* **Schnittstelle** zu **NSUserDefaults**, die **Anwendungs-** oder **globale** Einstellungen auf macOS speichert. + +* **getUserDefault** kann **sensible Informationen** abrufen, wie z.B. **Standorte kürzlich verwendeter Dateien** oder **geografische Standorte des Benutzers**. + +* **setUserDefault** kann diese Einstellungen **ändern**, was möglicherweise die **Konfiguration** einer App beeinflusst. + +* In **älteren Electron-Versionen** (vor v8.3.0) war nur die **Standard-Suite** von NSUserDefaults **zugänglich**. + +## Shell.showItemInFolder + +Diese Funktion zeigt die angegebene Datei in einem Dateimanager an, was **die Datei automatisch ausführen** könnte. + +Für weitere Informationen siehe [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html) + ## **Tools** -- [**Electronegativity**](https://github.com/doyensec/electronegativity) ist ein Tool zur Identifizierung von Fehlkonfigurationen und Sicherheitsantipatterns in auf Electron basierenden Anwendungen. +- [**Electronegativity**](https://github.com/doyensec/electronegativity) ist ein Tool zur Identifizierung von Fehlkonfigurationen und Sicherheits-Anti-Patterns in Electron-basierten Anwendungen. - [**Electrolint**](https://github.com/ksdmitrieva/electrolint) ist ein Open-Source-VS-Code-Plugin für Electron-Anwendungen, das Electronegativity verwendet. - [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) zur Überprüfung auf anfällige Drittanbieterbibliotheken - [**Electro.ng**](https://electro.ng/): Sie müssen es kaufen @@ -309,5 +399,6 @@ npm start - [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) - Weitere Forschungen und Berichte über die Sicherheit von Electron in [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://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}}