Skip to content
KitploitKITPLOIT
HerramientasBlog
Log in
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
supernote-obsidian-plugin-PoC — PoC — path traversal mediante sincronización maliciosa de dispositivos en el plugin Supernote Obsidian (GHSA-3gx3-r874-5pp4, CVE-2026-86999, CVSS 5.6). | Kitploit
Herramientas/GitHubGitHub/squeeze440/supernote-obsidian-plugin-poc
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebVirtualización de SeguridadPruebas de PenetraciónPapers e Investigación
GitHubsqueeze440/supernote-obsidian-plugin-poc

supernote-obsidian-plugin-PoC

PoC — path traversal mediante sincronización maliciosa de dispositivos en el plugin Supernote Obsidian (GHSA-3gx3-r874-5pp4, CVE-2026-86999, CVSS 5.6).

Ver Repositorio
16hace 19 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Resumen

Estado del CVE: solicitado, pendiente de asignación. Este hallazgo se publica como GHSA-3gx3-r874-5pp4. Al asignarse el CVE, este repositorio se renombra CVE-YYYY-NNNNN-supernote-obsidian-plugin-PoC y este banner se reemplaza con el enlace del CVE.

InvestigadorDostxodjayev Abdullox (@squeeze440)
AvisoGHSA-3gx3-r874-5pp4
CVSS 3.15.6 (Medio)
DebilidadCWE-22, CWE-73

Resumen

El Path Traversal en la función de sincronización automática del dispositivo del plugin de Obsidian Supernote (Unofficial) (philips/supernote-obsidian-plugin) v2.9.1 permite que un dispositivo "Supernote" malicioso o no autorizado (o un atacante en la ruta/en la LAN que suplante la IP del dispositivo emparejado) haga que el cliente Obsidian de la víctima escriba un archivo nuevo arbitrario en cualquier lugar donde el proceso de escritorio pueda escribir —incluyendo fuera de la carpeta de sincronización configurada y fuera del propio vault— mediante un campo uri manipulado en la respuesta de listado de directorios del dispositivo.

Producto

philips/supernote-obsidian-plugin ("Supernote (Unofficial)"), un plugin de la comunidad de Obsidian.md que sincroniza las notas de un dispositivo físico de tinta electrónica Supernote dentro de un vault a través del servidor HTTP local "Browse and Access" del dispositivo (http://<device-ip>:8089, sin autenticación, por diseño de la función del dispositivo).

Versión probada

  • Plugin: v2.9.1, commit 48db5bf4dcfb100632c84699c830c1309da1abb9
  • Submódulo supernote-typescript: commit 195415b3a1f74147... (no implicado en sí mismo — el fallo está enteramente en el propio código de planificación de sincronización del plugin)
  • Aplicación anfitriona: Obsidian desktop 1.13.4 (binario real, probado dinámicamente)

CVSS v3.1 estimado

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

  • AV:A — el servidor HTTP del dispositivo es texto plano, sin autenticación, y se configura mediante una dirección IPv4 simple (IP_VALIDATION_PATTERN, src/settings.ts:6); alcanzarlo como "el dispositivo" requiere una posición de red adyacente a la LAN (AP rogue, ARP spoofing, o reclamar la IP), no acceso remoto arbitrario.
  • AC:H — la explotación depende de que el atacante ya ocupe esa posición de red cuando el plugin de la víctima se comunica con directConnectIP:8089; no es un disparador remoto de un solo intento.
  • UI:R — requiere que la víctima ejecute "Sync supernote notes now" (o que tenga ya habilitado el interruptor de sincronización automática) mientras apunta al endpoint controlado por el atacante.
  • S:C — el componente vulnerable es un plugin de Obsidian con alcance de vault; la escritura aterriza completamente fuera del vault, en el sistema de archivos del host subyacente, que es un ámbito de seguridad diferente.
  • C:N — esto es una primitiva de solo escritura; nada se lee de vuelta hacia el atacante.
  • I:H — bytes controlados por el atacante aterrizan en una ruta elegida por el atacante con un nombre de archivo elegido por el atacante. Advertencia acotada: writeBinaryAt() (src/syncEngine.ts:40-47) solo toma la rama de creación para rutas que aún no están registradas en el propio manifiesto de sincronización del plugin, y el propio Vault.createBinary() de Obsidian se niega a sobrescribir silenciosamente un archivo que ya existe físicamente en la ruta resuelta (confirmado empíricamente — véase PoC) — por lo que esto es "plantar un archivo nuevo en cualquier lugar", no "sobrescribir cualquier archivo existente".
  • A:N — no se demostró impacto en la disponibilidad.

Detalles

runDeviceSync() (src/syncEngine.ts:100-196) lista los archivos del dispositivo emparejado mediante scanDeviceSupernoteTree() (src/FileListModal.ts:53-68), que recorre recursivamente el propio listado de directorios HTTP del dispositivo y conserva cualquier entrada cuyo name coincida con /\.(note|spd)$/i (src/FileListModal.ts:46,63). El campo uri de cada entrada —una cadena separada e independientemente controlada en el mismo objeto JSON devuelto por el dispositivo— nunca se valida contra name ni contra nada más.

Ese uri sin procesar se introduce directamente en deviceUriToVaultPath() (src/deviceSync.ts:153-161):

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 elimina \ : * ? " < > | pero nunca elimina ni rechaza segmentos de ruta ... Un uri de dispositivo de /../../PWNED.txt sobrevive intacto y se une a la carpeta de sincronización configurada (por defecto "Supernote sync") para producir vaultPath = "Supernote sync/../../PWNED.txt".

syncEngine.ts:128 calcula este vaultPath a partir del uri sin procesar del listado, y luego ensureFolder()/writeBinaryAt() (syncEngine.ts:146-148, 21-47) lo pasan directamente a app.vault.getAbstractFileByPath() / createBinary() / modifyBinary() sin ninguna comprobación de traversal. La propia resolución de rutas de Obsidian normaliza entonces los segmentos .. contra el directorio real del vault en disco, haciendo que la escritura aterrice por encima de la carpeta de sincronización —y, con suficientes segmentos ../, por encima de la raíz del vault por completo, en el sistema de archivos del host, dentro del propio ámbito de permisos del usuario del SO.

Comprobación de hermanos: cualquier otro sumidero de escritura en el vault en este código base (src/main.ts — captura de espejo de pantalla, importación de PDF/markdown, "attach to note", DownloadListModal en src/FileListModal.ts:245-246) construye su ruta de destino mediante el propio app.fileManager.getAvailablePathForAttachment(file.name) de Obsidian, que solo consume el campo name del dispositivo y no es explotable de esta manera. deviceUriToVaultPath() en la función de sincronización automática más reciente es el único sumidero que, en su lugar, construye a mano una ruta a partir del campo uri del dispositivo, y es el que omitió el saneamiento de .. — un caso claro de "comprobado en todos los hermanos menos en este".

La propia interfaz de ajustes del plugin afirma: "El comando de sincronización nunca escribe en ningún lugar fuera de esta carpeta" (src/settings.ts, descripción de Sync folder) — este PoC falsifica directamente esa garantía.

Prueba de concepto

Confirmado dinámicamente de extremo a extremo contra un binario de escritorio real y sin modificar de Obsidian 1.13.4 (Xvfb + fluxbox + xdotool + scrot), ejecutando el main.js compilado real del plugin — sin simulación del código del plugin.

Descargar herramienta