Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
supernote-obsidian-plugin-PoC — PoC — path traversal tramite sincronizzazione malevola del dispositivo nel plugin Supernote Obsidian (GHSA-3gx3-r874-5pp4, CVE-2026-86999, CVSS 5.6). | Kitploit
Strumenti/GitHubGitHub/squeeze440/supernote-obsidian-plugin-poc
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebVirtualizzazione per la SicurezzaPenetration TestingPaper e Ricerca
GitHubsqueeze440/supernote-obsidian-plugin-poc

supernote-obsidian-plugin-PoC

PoC — path traversal tramite sincronizzazione malevola del dispositivo nel plugin Supernote Obsidian (GHSA-3gx3-r874-5pp4, CVE-2026-86999, CVSS 5.6).

Vedi Repository
7 giorni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Riepilogo

Stato CVE: richiesto, in attesa di assegnazione. Questa segnalazione è pubblicata come GHSA-3gx3-r874-5pp4. All'assegnazione del CVE questo repository viene rinominato CVE-YYYY-NNNNN-supernote-obsidian-plugin-PoC e questo banner viene sostituito con il link al CVE.

RicercatoreDostxodjayev Abdullox (@squeeze440)
AdvisoryGHSA-3gx3-r874-5pp4
CVSS 3.15.6 (Medio)
DebolezzaCWE-22, CWE-73

Riepilogo

Il Path Traversal nella funzionalità di sincronizzazione automatica del dispositivo del plugin Obsidian Supernote (Unofficial) (philips/supernote-obsidian-plugin) v2.9.1 consente a un dispositivo "Supernote" malevolo o compromesso (o a un attaccante on-path/on-LAN che si spaccia per l'IP del dispositivo associato) di far scrivere al client Obsidian della vittima un file nuovo arbitrario ovunque il processo desktop possa scrivere — anche al di fuori della cartella di sincronizzazione configurata e al di fuori del vault stesso — tramite un campo uri appositamente craftato nella risposta di elenco directory del dispositivo.

Prodotto

philips/supernote-obsidian-plugin ("Supernote (Unofficial)"), un plugin della community di Obsidian.md che sincronizza le note di un dispositivo fisico e-ink Supernote in un vault tramite il server HTTP locale "Browse and Access" del dispositivo (http://<device-ip>:8089, senza autenticazione, per design della funzionalità del dispositivo).

Versione testata

  • Plugin: v2.9.1, commit 48db5bf4dcfb100632c84699c830c1309da1abb9
  • Sottomodulo supernote-typescript: commit 195415b3a1f74147... (non direttamente coinvolto — il bug è interamente nel codice di pianificazione della sincronizzazione del plugin stesso)
  • App host: Obsidian desktop 1.13.4 (binario reale, testato dinamicamente)

CVSS v3.1 stimato

5.6 Medio — CVSS:3.1/AV:A/AC:H/PR:N/UI:R/S:C/C:N/I:H/A:N

  • AV:A — il server HTTP del dispositivo è in chiaro, non autenticato e configurato tramite un semplice indirizzo IPv4 (IP_VALIDATION_PATTERN, src/settings.ts:6); raggiungerlo come "il dispositivo" richiede una posizione di rete adiacente alla LAN (rogue AP, ARP spoofing o rivendicazione dell'IP), non un accesso remoto arbitrario.
  • AC:H — lo sfruttamento dipende dal fatto che l'attaccante occupi già quella posizione di rete quando il plugin della vittima comunica con directConnectIP:8089; non è un trigger remoto one-shot.
  • UI:R — richiede che la vittima esegua "Sync supernote notes now" (o abbia già abilitato l'interruttore di sincronizzazione automatica) mentre è puntata all'endpoint controllato dall'attaccante.
  • S:C — il componente vulnerabile è un plugin Obsidian con scope sul vault; la scrittura finisce completamente al di fuori del vault, sul filesystem host sottostante, che è uno scope di sicurezza diverso.
  • C:N — questa è una primitiva di sola scrittura; nulla viene letto dall'attaccante.
  • I:H — byte controllati dall'attaccante finiscono in un percorso scelto dall'attaccante con un nome file scelto dall'attaccante. Avvertenza limitante: writeBinaryAt() (src/syncEngine.ts:40-47) prende il ramo create solo per percorsi non già tracciati nel manifest di sincronizzazione del plugin stesso, e Vault.createBinary() di Obsidian rifiuta di sovrascrivere silenziosamente un file che esiste già fisicamente nel percorso risolto (confermato empiricamente — vedi PoC) — quindi si tratta di "piantare un nuovo file ovunque", non di "sovrascrivere qualsiasi file esistente".
  • A:N — nessun impatto sulla disponibilità dimostrato.

Dettagli

runDeviceSync() (src/syncEngine.ts:100-196) elenca i file del dispositivo associato tramite scanDeviceSupernoteTree() (src/FileListModal.ts:53-68), che ricorre l'elenco directory HTTP del dispositivo stesso e mantiene qualsiasi voce il cui name corrisponda a /\.(note|spd)$/i (src/FileListModal.ts:46,63). Il campo uri di ciascuna voce — una stringa separata e controllata indipendentemente nello stesso oggetto JSON restituito dal dispositivo — non viene mai validato rispetto a name o a qualsiasi altra cosa.

Quel uri grezzo viene poi passato direttamente a deviceUriToVaultPath() (src/deviceSync.ts:153-161):

root@kitploit:~
const INVALID_FILENAME_CHARS = /[\\:*?"<>|]/g;   // deviceSync.ts:144

export function deviceUriToVaultPath(syncFolder: string, deviceUri: string): string {
    const segments = deviceUri
        .split('/')
        .filter((s) => s.length > 0)
        .map((s) => s.replace(INVALID_FILENAME_CHARS, '_'));

    const cleanRoot = syncFolder.replace(/^\/+|\/+$/g, '');
    return cleanRoot ? `${cleanRoot}/${segments.join('/')}` : segments.join('/');
}

INVALID_FILENAME_CHARS rimuove \ : * ? " < > | ma non rimuove né rifiuta mai i segmenti di percorso ... Un uri del dispositivo pari a /../../PWNED.txt sopravvive intatto e viene unito alla cartella di sincronizzazione configurata (predefinita "Supernote sync") per produrre vaultPath = "Supernote sync/../../PWNED.txt".

syncEngine.ts:128 calcola questo vaultPath dall'uri grezzo dell'elenco, poi ensureFolder()/writeBinaryAt() (syncEngine.ts:146-148, 21-47) lo passano direttamente a app.vault.getAbstractFileByPath() / createBinary() / modifyBinary() senza alcun controllo di traversal. La risoluzione dei percorsi di Obsidian normalizza poi i segmenti .. rispetto alla directory reale del vault su disco, facendo atterrare la scrittura sopra la cartella di sincronizzazione — e, con abbastanza segmenti ../, sopra la radice del vault, sul filesystem host, nello scope di permessi dell'utente OS stesso.

Controllo sui sibling: ogni altro sink di scrittura sul vault in questo codebase (src/main.ts — cattura screen-mirror, importazione PDF/markdown, "attach to note", DownloadListModal in src/FileListModal.ts:245-246) costruisce il proprio percorso di destinazione tramite app.fileManager.getAvailablePathForAttachment(file.name) di Obsidian, che consuma sempre e solo il campo name del dispositivo e non è sfruttabile in questo modo. deviceUriToVaultPath() nella funzionalità di sincronizzazione automatica più recente è l'unico sink che invece costruisce a mano un percorso dal campo uri del dispositivo, ed è quello che ha saltato la sanificazione di .. — un caso limpido di "controllato su ogni sibling tranne questo".

L'interfaccia delle impostazioni del plugin stesso afferma: "The sync command never writes anywhere outside this folder" (src/settings.ts, descrizione della cartella di sincronizzazione) — questo PoC falsifica direttamente tale garanzia.

Proof of Concept

Confermato dinamicamente end-to-end contro un binario desktop Obsidian 1.13.4 reale e non modificato (Xvfb + fluxbox + xdotool + scrot), eseguendo il main.js effettivamente compilato del plugin — nessun mocking del codice del plugin.

  1. Compilato il plugin dai sorgenti (./scripts/build) e caricato in un vault di test pulito (Supernote (Unofficial) v2.9.1, abilitato tramite "Trust author and enable plugins").
  2. Impostata l'opzione del plugin Supernote IP address a 127.0.0.1, lasciato Sync folder al valore predefinito Supernote sync.
  3. Avviato un mock Node di un singolo file del server "Browse and Access" del dispositivo su 127.0.0.1:8089, simulando un dispositivo malevolo/compromesso. Il suo elenco directory restituisce:
    root@kitploit:~
    {"name":"Quick notes.note","size":61,"date":"2026-07-31 00:00:00",
     "uri":"/../../PWNED_BY_DEVICE_SYNC.txt","extension":"note","isDirectory":false}
    
    (name supera il filtro sull'estensione .note; uri porta il traversal.) Qualsiasi GET riceve risposta 200 con i byte del file — i client HTTP reali normalizzano i .. fuori dal percorso della richiesta in uscita prima che raggiunga il filo (RFC 3986), il che è irrilevante qui poiché il codice vulnerabile calcola il percorso di scrittura dalla stringa JSON originale, non dall'URL della richiesta normalizzato.
  4. Eseguita l'azione della command palette "Supernote (Unofficial): Sync supernote notes now".
  5. Risultato: un nuovo file, PWNED_BY_DEVICE_SYNC.txt, contenente i byte dell'attaccante, è stato creato una directory sopra la radice del vault (sibling di testvault/, completamente fuori dal vault). Il data.json del plugin stesso ha registrato il percorso calcolato alla lettera: "vaultPath": "Supernote sync/../../PWNED_BY_DEVICE_SYNC.txt".

Evidenze (catture autentiche, ~/engagements/supernote-obsidian-plugin/evidence/):

  • 01-vault-escape-file-write.png — terminale reale: ls -la testvault/ PWNED_BY_DEVICE_SYNC.txt che mostra il file come sibling della directory del vault, più il suo contenuto controllato dall'attaccante tramite cat.
  • 02-plugin-data-json-vaultpath.png — il file di stato di sincronizzazione persistito dal plugin stesso che registra "vaultPath": "Supernote sync/../../PWNED_BY_DEVICE_SYNC.txt".
  • 03-plugin-settings-security-claim.png — l'interfaccia delle impostazioni del plugin che afferma che il comando di sincronizzazione "never writes anywhere outside this folder."

Impatto

Un attaccante in grado di rispondere come il dispositivo Supernote configurato della vittima (adiacente alla LAN: rogue AP, ARP spoofing o rivendicazione dell'IP del dispositivo) può far creare al client Obsidian della vittima un nuovo file controllato dall'attaccante in qualsiasi percorso del filesystem in cui il processo desktop possa scrivere — dentro il vault (ad es. un file nuovo di zecca sotto .obsidian/plugins/<new-id>/, ponendo le basi per ulteriori abusi della fiducia nei plugin) o completamente fuori di esso (ad es. ~/.config/autostart/*.desktop, un nuovo drop-in di crontab, o qualsiasi altra posizione in cui un file nuovo — non una sovrascrittura — sia sufficiente per ottenere esecuzione o persistenza). Non può sovrascrivere silenziosamente un file che esiste già nel percorso risolto (il createBinary di Obsidian lancia "File already exists" in quel caso, confermato empiricamente), il che limita la primitiva al planting di file nuovi anziché alla sovrascrittura universale.

Debolezze

  • CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
  • CWE-73: External Control of File Name or Path (l'uri fornito dal dispositivo determina direttamente la destinazione su disco)

Remediation

In deviceUriToVaultPath() (src/deviceSync.ts:153-161), rifiutare o rimuovere i segmenti di percorso .. (e quelli vuoti/solo .) dopo aver diviso deviceUri, ad es.:

root@kitploit:~
const segments = deviceUri
    .split('/')
    .filter((s) => s.length > 0 && s !== '.' && s !== '..')
    .map((s) => s.replace(INVALID_FILENAME_CHARS, '_'));

Inoltre, scanDeviceSupernoteTree() (src/FileListModal.ts:63) dovrebbe validare che l'uri di una voce dell'elenco sia coerente con il suo name (ad es. uri termina con lo stesso nome file), anziché fidarsi dei due campi indipendentemente — la stessa classe di difesa su cui si fa già implicitamente affidamento ovunque nel codebase, che costruisce percorsi solo da name/basename tramite getAvailablePathForAttachment().

Crediti

Dostxodjayev Abdullox

Canale di segnalazione

Nessun SECURITY.md è presente in questo repository. La segnalazione privata di vulnerabilità di GitHub è confermata abilitata per philips/supernote-obsidian-plugin (gh api repos/philips/supernote-obsidian-plugin/private-vulnerability-reporting --jq .enabled → true; 0 advisory di sicurezza pubblicati in precedenza). Si applica il flusso GHSA standard: https://github.com/philips/supernote-obsidian-plugin/security/advisories/new.

Scarica lo strumento