Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
supernote-obsidian-plugin-PoC — PoC — Supernote Obsidian プラグインにおける悪意あるデバイス同期を介したパストラバーサル(GHSA-3gx3-r874-5pp4、CVE-2026-86999、CVSS 5.6)。 | Kitploit
ツール/GitHubGitHub/squeeze440/supernote-obsidian-plugin-poc
脆弱性分析エクスプロイトウェブアプリケーション悪用セキュリティ仮想化ペネトレーションテスト論文と研究
GitHubsqueeze440/supernote-obsidian-plugin-poc

supernote-obsidian-plugin-PoC

PoC — Supernote Obsidian プラグインにおける悪意あるデバイス同期を介したパストラバーサル(GHSA-3gx3-r874-5pp4、CVE-2026-86999、CVSS 5.6)。

リポジトリを見る
7日前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

概要

CVEステータス: リクエスト済み、割り当て待ち。この脆弱性は GHSA-3gx3-r874-5pp4 として公開されています。CVEが割り当てられ次第、このリポジトリは CVE-YYYY-NNNNN-supernote-obsidian-plugin-PoC に改名され、このバナーはCVEリンクに置き換えられます。

研究者Dostxodjayev Abdullox (@squeeze440)
アドバイザリGHSA-3gx3-r874-5pp4
CVSS 3.15.6 (Medium)
脆弱性CWE-22, CWE-73

概要

Supernote (Unofficial) Obsidianプラグイン (philips/supernote-obsidian-plugin) v2.9.1 のデバイス自動同期機能におけるパストラバーサルにより、悪意のある、あるいは不正な「Supernote」デバイス(またはペアリングされたデバイスのIPを偽装するオン・パス/オンLAN攻撃者)が、デバイスのディレクトリ一覧レスポンス内の細工された uri フィールドを介して、被害者のObsidianクライアントに、デスクトッププロセスが書き込み可能な任意の場所 — 設定された同期フォルダの外や、Vault自体の外を含む — に任意の新規ファイルを書き込ませることができます。

製品

philips/supernote-obsidian-plugin(「Supernote (Unofficial)」)は、物理的なSupernote電子インクデバイスのノートを、デバイスのローカル「Browse and Access」HTTPサーバー(http://<device-ip>:8089、デバイス機能の設計上、認証なし)を介してVaultに同期するObsidian.mdコミュニティプラグインです。

テスト済みバージョン

  • プラグイン: v2.9.1、コミット 48db5bf4dcfb100632c84699c830c1309da1abb9
  • サブモジュール supernote-typescript: コミット 195415b3a1f74147...(それ自体は関与していません — バグは完全にプラグイン自身の同期計画コードにあります)
  • ホストアプリ: Obsidianデスクトップ 1.13.4(実際のバイナリ、動的テスト済み)

推定CVSS v3.1

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

  • AV:A — デバイスのHTTPサーバーは平文で認証がなく、裸のIPv4アドレス(IP_VALIDATION_PATTERN、src/settings.ts:6)で設定されます。「デバイス」として到達するにはLAN隣接ネットワーク位置(ローグAP、ARPスプーフィング、またはIPの奪取)が必要であり、任意のリモートアクセスではありません。
  • AC:H — 悪用は、被害者のプラグインが directConnectIP:8089 と通信する時点で攻撃者がすでにそのネットワーク位置を占めていることに依存します。単発のリモートトリガーではありません。
  • UI:R — 攻撃者が制御するエンドポイントを向いた状態で、被害者が「Sync supernote notes now」を実行する(または自動同期トグルがすでに有効になっている)必要があります。
  • S:C — 脆弱なコンポーネントはVaultスコープのObsidianプラグインですが、書き込みはVaultの完全に外側、基盤となるホストファイルシステム上に着地し、これは異なるセキュリティスコープです。
  • C:N — これは書き込み専用のプリミティブであり、攻撃者に何も読み戻されません。
  • I:H — 攻撃者が制御するバイトが、攻撃者が選んだパスに、攻撃者が選んだファイル名で着地します。限定的な注意点: writeBinaryAt()(src/syncEngine.ts:40-47)は、プラグイン自身の同期マニフェストにまだ追跡されていないパスに対してのみ作成ブランチを取ります。また、Obsidianの Vault.createBinary() 自体が、解決されたパスにすでに物理的に存在するファイルを黙って上書きすることを拒否します(経験的に確認済み — PoC参照)— したがってこれは「任意の場所に新規ファイルを植え付ける」であり、「既存の任意のファイルを上書きする」ではありません。
  • A:N — 可用性への影響は実証されていません。

詳細

runDeviceSync()(src/syncEngine.ts:100-196)は、scanDeviceSupernoteTree()(src/FileListModal.ts:53-68)を介してペアリングされたデバイスのファイルを一覧表示します。これはデバイス自身のHTTPディレクトリ一覧を再帰的に処理し、name が /\.(note|spd)$/i に一致するエントリを保持します(src/FileListModal.ts:46,63)。各エントリの uri フィールド — デバイスから返される同じJSONオブジェクト内の、独立して制御される別の文字列 — は、name やその他何に対しても検証されません。

その生の uri は、そのまま 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 は \ : * ? " < > | を除去しますが、.. パスセグメントを除去したり拒否したりすることはありません。デバイスの uri が /../../PWNED.txt の場合、そのまま生き残り、設定された同期フォルダ(デフォルト "Supernote sync")に結合されて vaultPath = "Supernote sync/../../PWNED.txt" を生成します。

syncEngine.ts:128 はこの vaultPath を一覧の生の uri から計算し、次に ensureFolder()/writeBinaryAt()(syncEngine.ts:146-148、21-47)がそれをそのまま app.vault.getAbstractFileByPath() / createBinary() / modifyBinary() に渡し、トラバーサルチェックはありません。Obsidian自身のパス解決は、ディスク上の実際のVaultディレクトリに対して .. セグメントを正規化し、書き込みを同期フォルダの上に着地させます — そして、十分な数の ../ セグメントがあれば、Vaultルートの完全に上、ホストファイルシステム上、OSユーザー自身の権限スコープに着地させます。

兄弟チェック: このコードベース内の他のすべてのVault書き込みシンク(src/main.ts — 画面ミラーキャプチャ、PDF/markdownインポート、「ノートに添付」、src/FileListModal.ts:245-246 の DownloadListModal)は、Obsidian自身の app.fileManager.getAvailablePathForAttachment(file.name) を介して宛先パスを構築します。これはデバイスの name フィールドのみを消費し、この方法では悪用できません。新しい自動同期機能の deviceUriToVaultPath() は、代わりにデバイスの uri フィールドからパスを手作りする唯一のシンクであり、.. のサニタイズをスキップしたものです — 「他のすべての兄弟ではチェックされているが、これだけはされていない」という明確なケースです。

プラグイン自身の設定UIには次のように記載されています: 「同期コマンドはこのフォルダの外には決して書き込みません」(src/settings.ts、同期フォルダの説明)— このPoCはその保証を直接反証します。

概念実証

実際の、改変されていないObsidian 1.13.4デスクトップバイナリ(Xvfb + fluxbox + xdotool + scrot)に対して、プラグインの実際のコンパイル済み main.js を実行して、エンドツーエンドで動的に確認済み — プラグインコードのモックは一切なし。

  1. ソースからプラグインをビルドし(./scripts/build)、新しいテストVaultにロードしました(Supernote (Unofficial) v2.9.1、「Trust author and enable plugins」で有効化)。
  2. プラグイン設定 Supernote IP address を 127.0.0.1 に設定し、Sync folder はデフォルトの Supernote sync のままにしました。
  3. 127.0.0.1:8089 上に、デバイスの「Browse and Access」サーバーの1ファイルのNodeモックを立ち上げ、悪意のある/不正なデバイスをシミュレートしました。そのディレクトリ一覧は次を返します:
    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 は .note 拡張子フィルタを通過し、uri はトラバーサルを運びます。)任意のGETはファイルバイトとともに200で応答されます — 実際のHTTPクライアントは、送信リクエストパスから .. をワイヤーに到達する前に正規化します(RFC 3986)が、脆弱なコードは正規化されたリクエストURLからではなく、元のJSON文字列から書き込みパスを計算するため、ここでは無関係です。
  4. コマンドパレットのアクション 「Supernote (Unofficial): Sync supernote notes now」 を実行しました。
  5. 結果: 攻撃者のバイトを含む新しいファイル PWNED_BY_DEVICE_SYNC.txt が、Vaultルートの1つ上のディレクトリ(testvault/ の兄弟、Vaultの完全に外側)に作成されました。プラグイン自身の data.json は計算されたパスをそのまま記録していました: "vaultPath": "Supernote sync/../../PWNED_BY_DEVICE_SYNC.txt"。

証拠(本物のキャプチャ、~/engagements/supernote-obsidian-plugin/evidence/):

  • 01-vault-escape-file-write.png — 実際のターミナル: ls -la testvault/ PWNED_BY_DEVICE_SYNC.txt が、ファイルがVaultディレクトリの兄弟であることを示し、さらに cat による攻撃者制御の内容。
  • 02-plugin-data-json-vaultpath.png — プラグイン自身の永続化された同期状態ファイルが "vaultPath": "Supernote sync/../../PWNED_BY_DEVICE_SYNC.txt" を記録している。
  • 03-plugin-settings-security-claim.png — プラグインの設定UIが、同期コマンドは「このフォルダの外には決して書き込みません」と主張している。

影響

被害者の設定されたSupernoteデバイスとして応答できる攻撃者(LAN隣接: ローグAP、ARPスプーフィング、またはデバイスのIPの奪取)は、被害者のObsidianクライアントに、デスクトッププロセスが書き込み可能な任意のファイルシステムパスに、攻撃者が制御する新しいファイルを作成させることができます — Vault内(例: .obsidian/plugins/<new-id>/ の下の真新しいファイルで、さらなるプラグイン信頼の悪用の下地を築く)または完全にその外側(例: ~/.config/autostart/*.desktop、新しいcrontabドロップイン、または新規ファイル — 上書きではない — が実行や永続化を得るのに十分なその他の場所)。解決されたパスにすでに存在するファイルを黙って上書きすることはできません(その場合、Obsidianの createBinary は「File already exists」をスローします。経験的に確認済み)。これにより、プリミティブは普遍的な上書きではなく、純新規ファイルの植え付けに限定されます。

脆弱性

  • CWE-22: パス名の制限されたディレクトリへの不適切な制限(「パストラバーサル」)
  • CWE-73: ファイル名またはパスの外部制御(デバイスが提供する uri がディスク上の宛先を直接決定する)

修復

deviceUriToVaultPath()(src/deviceSync.ts:153-161)で、deviceUri を分割した後に ..(および空/. のみ)のパスセグメントを拒否または除去します。例:

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

さらに、scanDeviceSupernoteTree()(src/FileListModal.ts:63)は、一覧エントリの uri がその name と一致する(例: uri が同じファイル名で終わる)ことを検証すべきであり、2つのフィールドを独立して信頼すべきではありません — これはコードベースの他のすべての場所ですでに暗黙的に依拠されているのと同じクラスの防御であり、getAvailablePathForAttachment() を介して name/basename のみからパスを構築します。

クレジット

Dostxodjayev Abdullox

報告チャネル

このリポジトリには SECURITY.md が存在しません。GitHubのプライベート脆弱性報告は philips/supernote-obsidian-plugin で有効であることが確認されています(gh api repos/philips/supernote-obsidian-plugin/private-vulnerability-reporting --jq .enabled → true、以前に公開されたセキュリティアドバイザリは0件)。標準的なGHSAフローが適用されます: https://github.com/philips/supernote-obsidian-plugin/security/advisories/new。

ツールをダウンロード