ADS は若手アナリストを驚かせ続ける NTFS の機能です。ひとつのファイルが複数の $DATA 属性を持つことがあります。名前のない $DATA 属性が dir で表示されるサイズに対応します。それ以外、識別子にコロンが含まれるものは、多くの人が手にする一般的なツールからは見えません。攻撃者はこれを知っています。Microsoft も知っています。IR レポートをレビューする監査担当者も知っているべきです。
仕組みを簡単に
MFT レコード内で、属性タイプ 0x80 は $DATA を表します。ヘッダにはオプションの名前が含まれます。ひとつのレコードに複数の $DATA 属性を持たせることができます。名前のないもの(プライマリストリーム)が 1 つと、任意の数の名前付きのものです。ユーザランドからは filename:streamname の形式でアクセスします。
echo payload > readme.txt:nope
type readme.txt:nope
readme.txt はエクスプローラで見える限りどんな測定方法でも 0 バイトです。名前付きの nope ストリームがペイロードを保持しています。同じ MFT レコード、同じ親ディレクトリのインデックスエントリ、独立した 2 つのデータ属性です。
これはバグではありません。1993 年の設計判断であり、Services for Macintosh がリソースフォークを格納できるように NTFS が HPFS から継承したものです。今ではほとんど誰もそうした用途で ADS を使いません。Microsoft を含めた他の関係者は、アドホックなメタデータの格納に使っています。
Windows 自体が ADS を残す場所
Zone.Identifier は有名な例です。Edge、Chrome、Firefox、Outlook はいずれもセキュリティ境界を越えたものに対してこれを追加します。中身はソース URL、リファラ、そして Office や SmartScreen の Mark-of-the-Web 保護を起動する ZoneId=3 の行を含む INI フラグメントです。MFT を読んでいて Downloads\ のバイナリに Zone.Identifier がない場合、その理由を考える必要があります。誰かが Unblock-File を実行したか、ストリームを破棄するアーカイブを経由してファイルをコピーした可能性があります。
その他、Microsoft 公認のストリームでよく見るものです。
- アジア言語キーボードレイアウトファイルに付く
$KSP。 - ディスクに保存された Outlook 添付ファイルに付く
OECustomPropertyなどです。 - WIMBoot や CompactOS 配下の圧縮ファイルに付く
Wofリパースデータです。 - Defender がフィンガープリント化した実行ファイルに付く
SmartScreen。 - ConfigMgr キャッシュディレクトリに付く
encryptable。
これらは日常的に現れます。ストリームを疑わしいと判断する前に、ベースラインがどんな見た目になるのかを学んでおいてください。
攻撃者が ADS で実際にしていること
繰り返し見るパターンは 3 つです。
- ペイロードの隠し場所と、別のランチャー。 可視ファイルは無害(Word 文書、PDF、ライセンスファイル)です。名前付きストリームが実際の PE を保持します。WMI、
wmic process call create、rundll32のいずれかがlegit.docx:payload.exeを直接起動します。Defender は最近、名前付きストリームをスキャンしますが、信頼されたプロセスがストリームを作成した場合、いまだに多くの EDR はスキャンしません。 - Living-off-the-land の隠し場所。 PowerShell のペイロードを
ads:script.ps1に書き込み、Get-Content -Streamで実行します。レッドチームのリテーナー案件では、パスのみの IOC 検索を回避できるため意外と多用されます。 - システムファイルの代替ストリームによる永続化。
C:\Windows\System32\drivers\etc\hosts:backdoorが教科書的な例です。hosts ファイルは触られていないように見え、タイムスタンプさえオリジナルのままかもしれません。ほとんどのファイル整合性監視ツールは名前のないストリームしか見ません。
共通する性質はこうです。dir では見えない、エクスプローラでも見えない、可視ファイルをハッシュ化しても見えない、しかし MFT レコードを読めば見えます。
ライブホストでの検出
dir /R は cmd でストリームを列挙します。PowerShell の Get-Item -Stream * も同じことを、より整然とした出力で行います。Sysinternals の streams.exe はツリーを再帰的に走査します。3 つともマウント中のボリュームでは問題なく動作します。ボリュームがオフラインの場合や、どのファイルをチェックすべきか不明な場合には役立ちません。
dir /R C:\Users\bob\Documents\
Get-ChildItem -Recurse | ForEach-Object { Get-Item $_.FullName -Stream * } |
Where-Object Stream -ne ':$DATA'
2 つ目のワンライナーは、ツリー上のすべての非デフォルトストリームを列挙します。新規 Windows インストールで実行すると、ほぼ Zone.Identifier で数百件のヒットが既に出ます。数百バイト以上のストリームに絞ると、ノイズが急速に減ります。
なぜ MFT がより良い視点なのか
ホスト上のコマンドはファイル単位で列挙します。チェックすることを思いつかなかったものは見落とします。MFT はそうではありません。すべての $DATA 属性は、名前の有無に関わらず、属性タイプ 0x80 としてレコードに書き込まれます。テーブルを走査し、すべてのレコードの $DATA 属性を名前とサイズと共に列挙すれば、ボリューム上のあらゆるストリームを一度のパスで網羅的に把握できます。
ファイル単位の列挙では得られないことが、いくつかあります。
C:\Windows\Temp\やC:\$Recycle.Bin\など、調査対象として考えもしないディレクトリ内のファイルに付随するストリームです。- 削除済みファイルに付随するストリームです。MFT レコードは削除後も残り、ADS は属性ストリームにそのまま列挙されています。Sleuth Kit の
flsとistatは表示しますし、MFTECmd やomerbenamram/mftCLI も同様です。 - 内容が MFT レコード内にインラインで存在するレジデントストリームです。小さなペイロード(PowerShell ローダー、base64 ブロブ、エンコードされた設定)は、1,024 バイトのレコードのスラックに収まることが多いです。データ領域に触れることなく、MFT 抽出から直接読み取れます。サイズしきい値については resident data を参照してください。
- ストリーム名です。MFT は攻撃者が選んだ名前を保持しています。
:payload.exeはサイズの一覧では無害に見えますが、属性ダンプをexeで grep すれば目立ちます。
私が実際に使っているトリアージフィルタ
MFTECmd や mft_dump で MFT を解析した後、$DATA 属性が複数あるレコードをすべてエクスポートします。次に以下を除外します。
- 追加ストリーム名が
Zone.Identifierで、サイズが 1 KB 未満のもの。 \Windows\WinSxS\配下のもの(マニフェストストア、正規ストリームが大量にあります)。- ベンダー署名済みアプリケーションのディレクトリ配下で、ストリームが既知のサムネイルやメタデータキーであるもの。
残ったものがワーキングセットです。クリーンなワークステーションでは通常 100 レコード未満です。何か興味深いことが起こったホストでは、差分が即座に浮かび上がります。
生き残ったレコードを USN journal と相互参照して、各ストリームがいつ作成または最後に変更されたかを確認します。02:14 に出現してそれ以降変更されていない名前付き $DATA 属性は、詳しく見る価値があります。手元にあれば Sysmon と Security イベントログ と組み合わせます。Sysmon Event ID 15(FileCreateStreamHash)は、ADS 作成をストリーム内容のハッシュ付きで捉える唯一のイベント ID です。
Defender に関する注意
最新の Defender はデフォルトで ADS をスキャンします。「既知の悪性 PE をストリームに置く」というブルートフォースなパターンに対しては、本当に良い性能を発揮します。ストリームに隠された小規模で難読化された PowerShell に対してはそれほど強くなく、除外パスのストリームには必ずしも触れません。Defender が何も言わないことを「存在しない証拠」とは決して見なさないでください。
参考資料
- Microsoft, File Streams。すべてのストリームをコピーする
BackupRead/BackupWriteAPI を含む公式なメカニクスです。 - Sleuth Kit の
istatとfls。ADS を浮かび上がらせるオフライン列挙に有用です。 - Microsoft の Mark of the Web ドキュメント。
Zone.Identifierの実際の動作と Office での使われ方が説明されています。