セキュリティチームの多くは、NTFSジャンクションやシンボリックリンクをニッチなファイルシステム機能として捉えています。これらはあるディレクトリを別のディレクトリに向けるもので、OSが実体として扱うショートカットのようなものです。後方互換性やストレージ管理のために存在しており、SOCで話題になることはほとんどありません。しかし、攻撃者の視点から見ると興味深い特性があります。それは、誰でも作成できるという点です。
管理者権限は不要で、対象フォルダへの書き込みアクセス以外に特別なパーミッションも必要ありません。
今回、ジャンクションを自身の親ディレクトリに向けることで、攻撃者が事実上無限のファイルパスを生成する再帰的ループを作り出せることを発見しました。EDR製品を含め、ディレクトリを再帰的にスキャンしようとするツールはこのループを追い続け、処理が終わらなくなります。
同じフォルダに置かれた悪意あるファイルは検査されることなく見過ごされます。私たちはこの手法を「GhostTree」と名付けました。
NTFSジャンクションの仕組み
Windowsのファイルパスはオペレーティングシステムの根幹を成す要素ですが、その仕組みは複雑です。多くのユーザーはシンプルなフォルダ構造を扱うだけですが、NTFSファイルシステムにはジャンクションやシンボリックリンクといった高度な機能が備わっています。
これらの機能は、ディレクトリのリダイレクト、特定の場所にファイルがあることを前提とするレガシーアプリケーションとの後方互換性維持、ファイルを物理的に移動せずに再編成するといった正当な用途に用いられます。
ジャンクションはNTFSの再解析ポイントの一種で、あるディレクトリを別のディレクトリにリダイレクトします。作成に必要なのは書き込み権限とCMDでの一行のコマンドだけです。
mklink /J C:\LinkToFolder C:\TargetFolder
このコマンドで「LinkToFolder」というジャンクションが作成され、透過的に「TargetFolder」を参照します。ジャンクション経由でファイルにアクセスするアプリケーションは、対象ディレクトリの内容をローカルにあるかのように参照できます。
ただし、一つ重要な制約があります。従来のWindowsシステムでは、レガシーソフトウェアとファイルシステム設計の経緯から、最大パス長が260文字に制限されています。
レジストリキーによってこの上限を最大32,767文字まで拡張することは技術的に可能ですが、260文字を超えるパスを扱えないアプリケーションやユーティリティも少なくありません。
NTFSが長いパスをサポートしていても、実際の使用は既存ソフトウェアの制約を受けます。この制限が、再帰ループの深さとGhostTreeが生成できるユニークなパスの数を決定します。
知らないことが脅威になります。
機密データの保護は、情報の所在・アクセス権者・利用状況を把握する「可視性」から始まります。
Varonis データセキュリティプラットフォームは、公開されたデータを自動的に保護し、SaaS・IaaS・オンプレミス・データベース全体のアクティビティを継続的に監視し、インサイダー脅威・ランサムウェア・AIの悪用を検知・対応します。
GhostBranch
GhostBranchは二つの手法のうちよりシンプルなものです。誰でもフォルダジャンクションを作成でき、ジャンクションの名前と参照先を自由に設定できます。次のフォルダ構造を例に考えてみましょう。
C:\Parent\program.exe
次のコマンドを実行します。
mklink /J C:\Parent\Child C:\Parent
これにより、子フォルダが親フォルダを参照する論理ループが作成されます。子ディレクトリはその中に自分自身を含む、親と同じ内容を持つことになります。結果として、同一ファイルへの有効なパスが無限に生成されます。
C:\Parent\Child\Program.exe
C:\Parent\Child\Child\Program.exe
C:\Parent\Child\Child\Child\Child\Program.exe
ループが存在するため、パスに「Child」フォルダをいくつ追加しても有効なままです。これらのパスはすべて同じ実行ファイルを参照します。

GhostTree
GhostTreeはGhostBranchの概念を発展させ、一つではなく複数の子フォルダを作成します。例えば、次のように子フォルダを二つ作成します。
mklink /J C:\Parent\Child1 C:\Parent
mklink /J C:\Parent\Child2 C:\Parent
これにより、パスの各階層でChild1またはChild2のどちらかを通ることができ、両方とも親フォルダにループバックします。結果として、以下のようなさまざまなパスが生成されます。
C:\Parent\Child1\Program.exe
C:\Parent\Child2\Program.exe
C:\Parent\Child1\Child1\Program.exe
C:\Parent\Child1\Child2\Program.exe

パス数の計算
GhostBranchとGhostTreeはいずれも、Windowsが許容する最大長まで延びるパスを生成できます。違いはパスの多様性にあり、GhostTreeでは子フォルダが追加されることで状況が大きく変わります。
GhostBranch
Windowsにおける従来の最大パス長は260文字です。ディレクトリ数を最大化するには、Cドライブ直下に一文字のフォルダ(例:「P」)を作成し、「1.exe」という名前の実行ファイルを置く方法が効果的です。
生成されるパスの例は以下の通りです。
C:\P\1.exe
C:\P\P\1.exe
C:\P\P\P\...\1.exe
この構成では、パス長の制限により約126通りのユニークなディレクトリ構造が生成できます。
GhostTree
GhostTree手法では、従来の単一フォルダ構造とは異なり、「P」と「B」の二つの親フォルダを導入します。生成されるパスの例は以下の通りです。
C:\B\1.exe
C:\P\B\1.exe
C:\P\B\P\B\...\1.exe
最大深度は約126フォルダで変わりませんが、各階層を「P」または「B」のどちらかで命名できるため、事実上二分木のような構造が生まれます。この構成では各ノードが異なるパスを表し、可能なノードの総数は次のように計算されます。
2^126 ≈ 8.5 × 10^37
これがどれほど大きな数かというと、地球上の砂粒の数(8.5 × 10^18)や人体を構成する原子の数(10^27)をはるかに超える値です。
防御側への影響
たった2行のコードで、誰でも無限に有効なパスを生成でき、dirコマンドによる再帰的な親ディレクトリのスキャンを完了不能にできます。フォルダ内の悪意あるファイルをスキャンするEDR製品も同様です。攻撃者は親ディレクトリにマルウェアを配置してGhostTree構造を設定するだけで、そのフォルダは事実上スキャン不能になります。スキャンはハングし、悪意あるファイルは検査されないまま放置されます。
この手法をWindows Defenderに対してテストし、フォルダスキャンを回避できることを確認しました。
この問題をMicrosoftに報告したところ、「Defenderのバイパスはセキュリティ境界を越えるものではない」との説明でチケットはクローズされました。その後、この問題は結果的にパッチが適用されています。
GhostTreeのような手法は、エンドポイントスキャンが防御の一層にすぎないことを改めて示しています。データ層でのファイルシステムアクティビティの監視により、スキャナーが見落とすもの、すなわち異常なジャンクションの作成や通常業務では存在しえない再帰的なディレクトリ構造を検知できます。
Varonisはファイルアクセスパターンを監視し、ファイルシステムおよびクラウドインフラ全体でこのような異常なアクティビティを検知します。