Translated ['src/network-services-pentesting/pentesting-web/electron-des

This commit is contained in:
Translator 2025-01-07 18:15:41 +00:00
parent 09f5fec5d0
commit 08857072dc
3 changed files with 143 additions and 32 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ scripts/*
book
book/*
hacktricks-preprocessor.log
hacktricks-preprocessor-error.log

View File

@ -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"""<a class="content_ref" href="/files/{href}"><span class="content_ref_label">{title}</span></a>"""
@ -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

View File

@ -36,11 +36,11 @@ Le impostazioni del **renderer process** possono essere **configurate** nel **ma
L'applicazione electron **potrebbe accedere al dispositivo** tramite le API di Node, anche se può essere configurata per prevenirlo:
- **`nodeIntegration`** - è `off` per impostazione predefinita. Se attivato, consente di accedere alle funzionalità di node dal renderer process.
- **`nodeIntegration`** - è `off` per impostazione predefinita. Se attivato, consente di accedere alle funzionalità di Node dal renderer process.
- **`contextIsolation`** - è `on` per impostazione predefinita. Se disattivato, i processi main e renderer non sono isolati.
- **`preload`** - vuoto per impostazione predefinita.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - è disattivato per impostazione predefinita. Restriggerà le azioni che NodeJS può eseguire.
- Integrazione Node nei Workers
- Integrazione di Node nei Workers
- **`nodeIntegrationInSubframes`** - è `off` per impostazione predefinita.
- Se **`nodeIntegration`** è **abilitato**, questo consentirebbe l'uso delle **API di Node.js** nelle pagine web che sono **caricate in iframe** all'interno di un'applicazione Electron.
- Se **`nodeIntegration`** è **disabilitato**, allora i preload verranno caricati nell'iframe.
@ -132,7 +132,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
}
});
```
Pertanto, lo script può esportare node-features nelle pagine:
Pertanto, lo script può esportare node-features su pagine:
```javascript:preload.js
typeof require === "function"
window.runCalc = function () {
@ -148,7 +148,7 @@ runCalc()
</script>
</body>
```
> [!NOTE] > **Se `contextIsolation` è attivo, questo non funzionerà**
> [!NOTE] > **Se `contextIsolation` è attivato, questo non funzionerà**
## RCE: XSS + contextIsolation
@ -157,7 +157,7 @@ Il _**contextIsolation**_ introduce i **contesti separati tra gli script della p
Se i contesti non sono isolati, un attaccante può:
1. Eseguire **JavaScript arbitrario nel renderer** (XSS o navigazione verso siti esterni)
2. **Sovrascrivere il metodo incorporato** che viene utilizzato nel preload o nel codice interno di Electron con una funzione propria
2. **Sovrascrivere il metodo incorporato** che viene utilizzato nel preload o nel codice interno di Electron con una propria funzione
3. **Attivare** l'uso della **funzione sovrascritta**
4. RCE?
@ -175,7 +175,7 @@ electron-contextisolation-rce-via-electron-internal-code.md
electron-contextisolation-rce-via-ipc.md
{{#endref}}
### Bypass dell'evento click
### Bypass dell'evento di clic
Se ci sono restrizioni applicate quando clicchi su un link, potresti essere in grado di aggirarle **facendo un clic centrale** invece di un normale clic sinistro.
```javascript
@ -185,14 +185,14 @@ window.addEventListener('click', (e) => {
Per ulteriori informazioni su questi esempi, controlla [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) e [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Quando si distribuisce un'applicazione desktop Electron, è fondamentale garantire le impostazioni corrette per `nodeIntegration` e `contextIsolation`. È stato stabilito che **l'esecuzione remota di codice (RCE)** lato client che mira a script di preload o al codice nativo di Electron dal processo principale è efficacemente prevenuta con queste impostazioni in atto.
Quando si distribuisce un'applicazione desktop Electron, è fondamentale garantire le impostazioni corrette per `nodeIntegration` e `contextIsolation`. È stato stabilito che **l'esecuzione remota di codice lato client (RCE)** mirata a script di preload o al codice nativo di Electron dal processo principale è efficacemente prevenuta con queste impostazioni in atto.
Quando un utente interagisce con i link o apre nuove finestre, vengono attivati specifici listener di eventi, che sono cruciali per la sicurezza e la funzionalità dell'applicazione:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
Questi listener sono **sovrascritti dall'applicazione desktop** per implementare la propria **logica aziendale**. L'applicazione valuta se un link navigato dovrebbe essere aperto internamente o in un browser web esterno. Questa decisione viene solitamente presa tramite una funzione, `openInternally`. Se questa funzione restituisce `false`, indica che il link dovrebbe essere aperto esternamente, utilizzando la funzione `shell.openExternal`.
Questi listener sono **sovrascritti dall'applicazione desktop** per implementare la propria **logica aziendale**. L'applicazione valuta se un link navigato debba essere aperto internamente o in un browser web esterno. Questa decisione viene tipicamente presa attraverso una funzione, `openInternally`. Se questa funzione restituisce `false`, indica che il link deve essere aperto esternamente, utilizzando la funzione `shell.openExternal`.
**Ecco un pseudocodice semplificato:**
@ -200,7 +200,9 @@ Questi listener sono **sovrascritti dall'applicazione desktop** per implementare
![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Le migliori pratiche di sicurezza di Electron JS sconsigliano di accettare contenuti non attendibili con la funzione `openExternal`, poiché potrebbe portare a RCE attraverso vari protocolli. I sistemi operativi supportano diversi protocolli che potrebbero attivare RCE. Per esempi dettagliati e ulteriori spiegazioni su questo argomento, si può fare riferimento a [questa risorsa](https://positive.security/blog/url-open-rce#windows-10-19042), che include esempi di protocolli Windows in grado di sfruttare questa vulnerabilità.
Le migliori pratiche di sicurezza di Electron JS sconsigliano di accettare contenuti non attendibili con la funzione `openExternal`, poiché potrebbe portare a RCE attraverso vari protocolli. I sistemi operativi supportano diversi protocolli che potrebbero attivare RCE. Per esempi dettagliati e ulteriori spiegazioni su questo argomento, si può fare riferimento a [questa risorsa](https://positive.security/blog/url-open-rce#windows-10-19042), che include esempi di protocolli Windows capaci di sfruttare questa vulnerabilità.
In macos, la funzione `openExternal` può essere sfruttata per eseguire comandi arbitrari come in `shell.openExternal('file:///System/Applications/Calculator.app')`.
**Esempi di exploit di protocolli Windows includono:**
```html
@ -222,9 +224,9 @@ window.open(
)
</script>
```
## Lettura di file interni: XSS + contextIsolation
## Lettura di File Interni: XSS + contextIsolation
**Disabilitare `contextIsolation` consente l'uso di `<webview>` tag**, simile a `<iframe>`, per leggere ed esfiltrare file locali. Un esempio fornito dimostra come sfruttare questa vulnerabilità per leggere il contenuto di file interni:
**Disabilitare `contextIsolation` consente l'uso di `<webview>` tags**, simile a `<iframe>`, per leggere ed esfiltrare file locali. Un esempio fornito dimostra come sfruttare questa vulnerabilità per leggere il contenuto di file interni:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
@ -266,16 +268,104 @@ Nel caso in cui il **regex** utilizzato dalla funzione sia **vulnerabile a bypas
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
```
## **Strumenti**
## Modulo remoto
Il modulo Remote di Electron consente ai **processi di rendering di accedere alle API del processo principale**, facilitando la comunicazione all'interno di un'applicazione Electron. Tuttavia, abilitare questo modulo introduce rischi significativi per la sicurezza. Espande la superficie di attacco dell'applicazione, rendendola più suscettibile a vulnerabilità come gli attacchi di cross-site scripting (XSS).
> [!TIP]
> Anche se il modulo **remote** espone alcune API dal principale ai processi di rendering, non è semplice ottenere RCE solo abusando dei componenti. Tuttavia, i componenti potrebbero esporre informazioni sensibili.
> [!WARNING]
> Molte app che utilizzano ancora il modulo remoto lo fanno in un modo che **richiede l'abilitazione di NodeIntegration** nel processo di rendering, il che rappresenta un **enorme rischio per la sicurezza**.
Dalla versione 14 di Electron, il modulo `remote` di Electron potrebbe essere abilitato in diversi passaggi, poiché per motivi di sicurezza e prestazioni è **consigliato non usarlo**.
Per abilitarlo, è prima necessario **abilitarlo nel processo principale**:
```javascript
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)
```
Quindi, il processo di rendering può importare oggetti dal modulo come:
```javascript
import { dialog, getCurrentWindow } from '@electron/remote'
```
Il **[post del blog](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indica alcune interessanti **funzioni** esposte dall'oggetto **`app`** del modulo remoto:
- **`app.relaunch([options])`**
- **Riavvia** l'applicazione **uscendo** dall'istanza corrente e **lanciando** una nuova. Utile per **aggiornamenti dell'app** o significativi **cambiamenti di stato**.
- **`app.setAppLogsPath([path])`**
- **Definisce** o **crea** una directory per memorizzare i **log dell'app**. I log possono essere **recuperati** o **modificati** utilizzando **`app.getPath()`** o **`app.setPath(pathName, newPath)`**.
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- **Registra** l'eseguibile corrente come **gestore predefinito** per un **protocollo** specificato. Puoi fornire un **percorso personalizzato** e **argomenti** se necessario.
- **`app.setUserTasks(tasks)`**
- **Aggiunge** attività alla **categoria Attività** nella **Jump List** (su Windows). Ogni attività può controllare come l'app viene **lanciata** o quali **argomenti** vengono passati.
- **`app.importCertificate(options, callback)`**
- **Importa** un **certificato PKCS#12** nel **negozio di certificati** del sistema (solo Linux). Un **callback** può essere utilizzato per gestire il risultato.
- **`app.moveToApplicationsFolder([options])`**
- **Sposta** l'applicazione nella **cartella Applicazioni** (su macOS). Aiuta a garantire un'**installazione standard** per gli utenti Mac.
- **`app.setJumpList(categories)`**
- **Imposta** o **rimuove** una **Jump List personalizzata** su **Windows**. Puoi specificare **categorie** per organizzare come le attività appaiono all'utente.
- **`app.setLoginItemSettings(settings)`**
- **Configura** quali **eseguibili** si avviano al **login** insieme alle loro **opzioni** (solo macOS e Windows).
```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
```
## systemPreferences module
L'**API principale** per accedere alle preferenze di sistema e **emettendo eventi di sistema** in Electron. Metodi come **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** e **setUserDefault** sono tutti **parte di** questo modulo.
**Esempio di utilizzo:**
```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**
* **Ascolta** le **notifiche native macOS** utilizzando NSDistributedNotificationCenter.
* Prima di **macOS Catalina**, potevi sniffare **tutte** le notifiche distribuite passando **nil** a CFNotificationCenterAddObserver.
* Dopo **Catalina / Big Sur**, le app sandboxed possono ancora **iscriversi** a **molti eventi** (ad esempio, **blocco/sblocco dello schermo**, **montaggi di volume**, **attività di rete**, ecc.) registrando le notifiche **per nome**.
### **getUserDefault / setUserDefault**
* **Interfaccia** con **NSUserDefaults**, che memorizza le **preferenze** dell'**applicazione** o **globali** su macOS.
* **getUserDefault** può **recuperare** informazioni sensibili, come **posizioni di file recenti** o **posizione geografica dell'utente**.
* **setUserDefault** può **modificare** queste preferenze, potenzialmente influenzando la **configurazione** di un'app.
* Nelle **versioni più vecchie di Electron** (prima della v8.3.0), solo la **suite standard** di NSUserDefaults era **accessibile**.
## Shell.showItemInFolder
Questa funzione mostra il file dato in un gestore di file, che **potrebbe eseguire automaticamente il file**.
Per ulteriori informazioni controlla [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) è uno strumento per identificare misconfigurazioni e anti-pattern di sicurezza nelle applicazioni basate su Electron.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) è un plugin open source per VS Code per applicazioni Electron che utilizza Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) per controllare le librerie di terze parti vulnerabili
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) per controllare librerie di terze parti vulnerabili
- [**Electro.ng**](https://electro.ng/): Devi acquistarlo
## Laboratori
## Labs
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) puoi trovare un laboratorio per sfruttare le app Electron vulnerabili.
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) puoi trovare un laboratorio per sfruttare app Electron vulnerabili.
Al alcuni comandi che ti aiuteranno con il laboratorio:
```bash
@ -309,5 +399,6 @@ npm start
- [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)
- Maggiori ricerche e articoli sulla sicurezza di 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}}