• Stream form Outer Network

Webブラウザでインターネットからダウンロードしたファイルには、Zone.Identifierという、代替データストリーム(Alternate Data Stream。ADS)が付く。Windows XP SP2で搭載されたWindows SmartScreenがこの情報を使って、ファイルを開こうとしたときに警告などを表示していた。

しかし、Windows 11では、この機能はMicrosoft Defender SmartScreenに引き継がれている。これは、Microsoftが作成したデータベースを元に、サイトやファイル名などから危険性を判断するもの。なので、Windows 11では、この代替データストリーム自体は利用されていない。しかし、これを付けるのは、ブラウザ(ダウンロードするプログラム)である。調べたところChrome、Edge、Firefoxは、例外はあるもののダウンロードしたファイルに、Zone.Identifierを付けるようだ(後述)。

代替データストリームとは、NTFSが持つ機能の1つ。1つのファイルに独立した複数の「内容」(ストリーム)を追加するもの。メタ情報の格納や、このZone.Identifierのようにセキュリティなどに利用する。代替データストリームはファイルの一部なので、コピーやリネームなどの操作でもそのまま残る。ただし、エクスプローラーは、代替データストリームを扱うことができないため、コマンドラインを使う必要がある。

ファイルに代替データストリームが付いているかどうかは、cmd.exeの内部コマンドdirの/rオプションを使って表示できる。PowerShellからなら“cmd.exe /c dir /r”とする(写真01)。

  • 写真01: cmd.exeの内部コマンドdir /rを使うとファイルと代替データストリームを表示できる(①)。PowerShellコマンドなら、②のように代替データストリームのみ表示できる。パイプラインの中央部分は、代替データストリーム以外を表す。giは、Get-Itemコマンドのエイリアス。また、カレントディレクトリでZone.Identifier代替データストリームを持たないファイルは、コマンドのエラーを使って③のようなコマンドで表示可能。代替データストリームの中身を表示するなら、cat(Get-Contentコマンドのエイリアス)の-Streamオプションを使う(④)。代替データストリームを削除するなら、Remove-Itemコマンドを使う(⑤)。digital.svgの代替データストリームが削除されたので、⑥のコマンドは、残ったtestfile.txtだけを表示する(②と比較)

PowerShellのコマンドだけを使うなら、


Get-Item * -Stream * | ? stream -ne ':$DATA' | select PSchildname

とすることで、カレントディレクトリにあるファイルのうち、代替データストリームを持つファイルを出力できる。ファイル名の後ろのコロン“:”以降が代替データストリーム名である。Windowsではコロンをファイル名に使えないため、この表記が可能になる。

ファイルに対して特定の名前の代替データストリームが「ない」ことを調べる直接のコマンドはないが、エラーメッセージを使う方法がある。


Get-Item * -Stream "Zone.Identifier" | out-null

とすることで、エラーメッセージからカレントディレクトリにあるZone.Identifierを含まないファイルを知ることができる。

代替データストリームの内容は、


Get-Content ファイルパス -Stream ストリーム名

とすることで表示できる。

WSLのローカルファイルシステムに代替データストリームのあるファイルをコピーすると、代替データストリームが別ファイルとしてコピーされてしまう。代替という名前ではあるが、ファイル内容には変わりないため、勝手に落としてしまうようなことは行われない。しかし、Linuxから扱うときには、邪魔になることがある。もちろん、Linux側で削除してしまうことができるが、Win32側ファイルシステム(NTFS)にあるなら、PowerShellで、


remove-item ファイルパス -stream *

とすることで、代替データストリームを全て削除できる。ファイル名にはワイルドカードが利用できる。

現在ではほとんど使われていないZone.Identifierだが、Webブラウザは、ダウンロード時に代替データストリームを付加するようになっている。Chromeのソースコードにあるcomponents/services/quarantine/quarantine_win.ccや、Firefoxのソースコードのtoolkit/components/downloads/DownloadIntegration.sys.mjsなどでダウンロード時に代替データストリームZone.Identifierを書き込んでいる。

これを見る限り、現在では、Zone.Identifierには、1つのセクション名“[ZoneTransfer]”と以下の3つの要素しか書き込まれていないようだ。


ZoneId  ダウンロードしたゾーンのID
ReferrerUrl ダウンロードしたサイトのURL(リファラー)
HostUrl ダウンロードリンク

かつては、他の要素も使われていたようだが、前記のソースコードを見る限り、この3つの要素しか使われていない。ReferrerURLは、HTTPヘッダのリファラーで、以前はダウンロードリンクのあったページのURLだったが、プライバシー対策などのため、いまでは、単にサイトのトップページのURLになっている。これに対してHostURLには、ダウンロードリンクが記述されている。代替データストリームなので、ファイルを実行することなく情報を得られる。なお、ZoneIdは、インターネットを表す3以上の数値となっている。0~2は、ローカルやイントラネットを表し、Windows SmartScreenの対象ではなかったため、Zone.Identifierは付かない。Windows SmartScreenが使われなくなったのは、IEが使っていたゾーンによるセキュリティ管理が廃止されたからでもある。

ダウンロードしたファイルは残っているが、どこからダウンロードしてきたのか、setup.exeじゃ何のプログラムだかわからない、といったとき、この情報を手掛かりにすることができる。

今回のタイトルネタは、1957年の映画「Plan 9 from Outer Space」。内容はともかく、何といってもタイトルが秀逸。そのため、ベル研のオペレーティングシステムの名前など、様々な「ネタ」になった映画。