Zone.Identifier: what the Mark of the Web records about a download
How Windows marks downloads in an NTFS alternate data stream: where it lives in the MFT, the zone and URL keys, hunting it at scale, and how it disappears.
On this page
When a browser saves a file on Windows, it usually leaves a small note beside it: an NTFS alternate data stream named Zone.Identifier. Windows, SmartScreen and Microsoft Office use it to decide whether to warn, block or open in Protected View. Investigators use it to answer a different question: where did this file come from?
This post covers the stream at the file-system level, what it contains, how to read it on a live system and in an image, how to hunt for it across a disk, and every way it can go missing.
What the stream is
Link to section: What the stream isMicrosoft’s file system specification describes it plainly: Internet Explorer stores URL security zones in a stream named Zone.Identifier, and the fully qualified form for a file called sample.txt is sample.txt:Zone.Identifier:$DATA. The minimal content is two lines of text:
[ZoneTransfer]
ZoneId=3The feature is widely called the Mark of the Web (MOTW). Because it lives in an alternate data stream, a normal directory listing does not show it and the file’s reported size does not change.
Where it lives in the MFT
Link to section: Where it lives in the MFTAn NTFS file’s content is its unnamed $DATA attribute (type 0x80). An alternate data stream is simply another $DATA attribute with a name, stored in the same MFT record. A Zone.Identifier stream is a few dozen to a few hundred bytes, so it is normally resident: its bytes sit inside the 1,024-byte MFT record itself rather than in clusters elsewhere on the volume.
That has two practical consequences:
- The stream shares the file’s MFT record and timestamps. It has no
$STANDARD_INFORMATIONof its own, so there is no separate “stream created” time to report. - When the file is deleted, the stream’s text can remain in the unallocated MFT record until the record is reused, and carving MFT records for
[ZoneTransfer]can recover download origins for files that are gone.
What the zone values mean
Link to section: What the zone values meanZoneId takes a value from Windows’ URL security zone enumeration (URLZONE in Urlmon.h):
| ZoneId | Zone | Typical meaning for a downloaded file |
|---|---|---|
| 0 | Local machine | Content from the computer itself |
| 1 | Local intranet | Content from an intranet site |
| 2 | Trusted sites | A site the user or policy marked as trusted |
| 3 | Internet | Most web content; the usual value for a download |
| 4 | Restricted sites | A site marked as untrusted |
Microsoft’s Office documentation notes that, by default, the mark is only applied to files from the Internet and Restricted sites zones, and only on NTFS volumes. A file with ZoneId=1 or 2 exists, but only where policy or the downloading application chose to write it.
More than a zone
Link to section: More than a zoneCurrent browsers usually write more than the ZoneId line. A typical stream on a file saved by a Chromium-based browser looks like this (illustrative values):
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://intranet-portal.example/announcements
HostUrl=https://files.example-cdn.net/d/7f3a/Invoice_0714.zip| Key | What it holds |
|---|---|
HostUrl | The address the file was downloaded from, after redirects |
ReferrerUrl | The page that linked to it |
LastWriterPackageFamilyName | The app package that wrote the stream (the Sleuth Kit’s documentation notes that Edge writes it) |
These extra keys are not part of the specification quoted above, and which ones appear depends on the browser and its version, so treat them as present when you find them rather than expected. When they are there, HostUrl can answer the question that otherwise needs browser history: the exact URL a file came from.
A HostUrl pointing to a file-sharing or paste site, on an executable that a user says they never downloaded, is the kind of detail that is worth checking against the browser’s download history and the proxy logs for the same minute.
Why Windows and Office care
Link to section: Why Windows and Office careThe mark is a security control before it is an artifact:
- SmartScreen and Attachment Manager check it before running executables and scripts, which is where the “Windows protected your PC” and “Open File - Security Warning” prompts come from.
- Microsoft Office opens marked documents in Protected View, and since 2022 blocks VBA macros in files from the Internet zone. Microsoft’s documentation is explicit that the block applies to
ZoneId=3and not toZoneId=2(Trusted sites).
That is why attackers work to get rid of it, and why the absence of the mark on a malicious file is itself worth explaining. CVE-2022-41091, a Mark of the Web security feature bypass fixed in November 2022, was exploited in the wild and is listed in CISA’s Known Exploited Vulnerabilities catalog.
Reading it
Link to section: Reading itOn a live system
Link to section: On a live system# List every stream on a file
Get-Item -Path .\Invoice_0714.zip -Stream *
# Read the Mark of the Web
Get-Content -Path .\Invoice_0714.zip -Stream Zone.IdentifierFrom the command prompt, dir /r lists alternate data streams next to each file, and notepad Invoice_0714.zip:Zone.Identifier opens the stream in Notepad.
Hunting across a folder or a volume
Link to section: Hunting across a folder or a volumeReading streams one file at a time does not scale. This collects every marked file under a path, parses the stream, and exports the result:
$root = 'C:\Users'
Get-ChildItem -Path $root -Recurse -File -Force -ErrorAction SilentlyContinue |
ForEach-Object {
$zi = Get-Content -LiteralPath $_.FullName -Stream Zone.Identifier -ErrorAction SilentlyContinue
if ($zi) {
$kv = @{}
foreach ($line in $zi) { if ($line -match '^([^=\[]+)=(.*)$') { $kv[$Matches[1]] = $Matches[2] } }
[pscustomobject]@{
Path = $_.FullName
SizeBytes = $_.Length
Created = $_.CreationTimeUtc
Modified = $_.LastWriteTimeUtc
ZoneId = $kv.ZoneId
HostUrl = $kv.HostUrl
ReferrerUrl = $kv.ReferrerUrl
}
}
} | Export-Csv -Path .\motw.csv -NoTypeInformation -Encoding utf8Sort the CSV by Created and the result reads like a download log that survives browser history being cleared. Filter HostUrl for domains seen in the incident, or Path for executables and scripts in user-writable folders.
Run this against a mounted image or a copy where possible. On a live system, Get-ChildItem -Recurse over a profile touches access times on directories and cannot read files that are locked or that the account has no rights to.
In a forensic image
Link to section: In a forensic imageThe Sleuth Kit addresses each attribute separately. fls lists streams as name:streamname, istat shows the record’s $DATA attributes with their IDs and names, and icat reads one by its inode-type-id address:
fls -r -p image.dd | grep ':Zone.Identifier'
istat image.dd 104233 # note the $DATA attribute ID named Zone.Identifier
icat image.dd 104233-128-5 # 128 = 0x80 ($DATA); 5 = that attribute's IDThe attribute ID differs from file to file, so read it from istat rather than assuming it. Autopsy’s Recent Activity module extracts the same keys into its results automatically.
Correlating with browser history
Link to section: Correlating with browser historyWhen both survive, the mark and the browser’s own download records should agree. In Chromium-based browsers, the History SQLite database stores downloads in two tables: downloads (one row per download) and downloads_url_chains (every URL in the redirect chain, in order). Times are microseconds since 1601-01-01 UTC:
SELECT d.id,
d.target_path,
datetime(d.start_time / 1000000 - 11644473600, 'unixepoch') AS start_utc,
d.referrer,
c.chain_index,
c.url
FROM downloads AS d
JOIN downloads_url_chains AS c ON c.id = d.id
ORDER BY d.start_time, c.chain_index;The last URL in a chain normally corresponds to the stream’s HostUrl, and referrer to ReferrerUrl. A disagreement (a file whose HostUrl has no matching download row) suggests history was cleared, a different browser profile was used, or the file came from another program entirely.
On hosts running Sysmon, event ID 15 (FileCreateStreamHash) records the creation of named streams, with the process that wrote it, the time, a hash of the file’s main content and the contents of the named stream. Microsoft’s description says it is aimed at exactly this case: the browser attaching a Zone.Identifier stream to a download. That gives the stream the creation timestamp NTFS never stored.
Where the evidence disappears
Link to section: Where the evidence disappearsThe Mark of the Web is easy to lose, and an investigator should know every way it can go missing:
- Copying to a non-NTFS volume. FAT32 and exFAT have no alternate data streams, so the stream is dropped when the file is copied to a USB stick formatted that way, and does not come back when the file is copied home again.
- Archives. Windows’ built-in ZIP support propagates the mark to extracted files. Third-party tools vary: 7-Zip 22.00 added a “Propagate Zone.Id stream” setting (No / Yes / For Office files) and the
-snzcommand-line switch, so whether files extracted with 7-Zip carry the mark depends on how it was configured and invoked. - Container files. Disk images and other containers have been used to deliver files without the mark; CVE-2022-41091 is one fixed example of a bypass in this area.
- Cloud sync. Microsoft’s Office documentation notes that files synced by OneDrive, files opened with “Open in Desktop App” from OneDrive or SharePoint, and files in known folders synced to OneDrive do not get the mark.
- Unblocking. The Unblock checkbox in a file’s properties, or PowerShell’s
Unblock-File, deletes the stream. - Other transfer paths. Files written by tools that do not use the Attachment Manager (many command-line downloaders, SMB copies, remote management tools) may never get the stream at all.
So the rule is one-directional: a Zone.Identifier stream is evidence of where a file came from; its absence is not evidence that the file was created locally.
Like any alternate data stream, the Zone.Identifier stream is part of the file on NTFS. Acquire with a method that preserves alternate data streams (a full image, or a logical collection tool that records them), or the evidence is gone before analysis starts. Copying files out to an analysis share formatted as exFAT, or zipping them with a tool that ignores streams, destroys it silently.
Related artifacts
Link to section: Related artifactsAlternate data streams are not only written by Windows. An executable can be launched from a stream, and Windows then writes a prefetch record that itself lives in a stream. Eric Zimmerman’s PECmd gained an --ads switch to scan alternate data streams for hidden prefetch, and Prefetch Parser recovers the same records. The prefetch post covers that case in detail.
References
Link to section: References- Microsoft, MS-FSCC: Zone.Identifier Stream Name: the stream name and its
[ZoneTransfer]/ZoneIdformat. - Microsoft, URLZONE enumeration: the zone values.
- Microsoft, Macros from the internet are blocked by default in Office: which zones get the mark, NTFS only, the OneDrive exceptions, and the ZoneId 2 versus 3 behaviour.
- Microsoft, Unblock-File: removing the mark.
- MITRE / NVD, CVE-2022-41091, and CISA’s Known Exploited Vulnerabilities catalog.
- 7-Zip, version history: the 22.00
-snzswitch and Zone.Id propagation setting. - The Sleuth Kit, Autopsy Zone Identifier extraction: the keys a forensic tool reads from the stream.
- Microsoft Learn, Sysmon: event ID 15, FileCreateStreamHash.