Recently, a colleague sent me an email which provided a flashback into my own past:
Why do we show this when opening HTML locally? What are we protecting the user from?
I myself had sent an email with almost the same text nearly seven years ago, and the surprisingly complicated answer is one of the key reasons I joined the IE team a few months later.
At the time, I was working as a Program Manager on the Office Online website, and I’d come across the specs for the Windows XP SP2 (codename “Springboard”) updates to the web browser. Now, by this time, I’d been working on the web for nearly 8 years, and I “knew” what everyone else did about web security—you’re supposed to treat web content on the Internet as hostile, but script running from your local computer was obviously more trusted and thus should run freely. What were these Springboard guys thinking? Didn’t they know how the web was supposed to work?
The recipient of my message (and my new boss, a few months later) tersely explained how ActiveX controls running locally often ran with unlimited permission, and hence a downloaded HTML file could be as dangerous as an executable program. In the late 1990s and early 2000s, the most common way of taking over a Windows machine was to simply inject some script content into the local system (either literally planting an HTML file or via an XSS attack). When viewed, the malicious content ran at full-trust (because almost all XP users ran as administrator) and hence it was “Game Over” any time a new way was found to inject content into the Local Machine Zone.
The ActiveX threat was subsequently mitigated by Springboard’s introduction of a new set of “Lockdown” settings for content running in the Local Machine Zone—these settings were such that an attacker who executed the attack described would be “breaking into jail”—he’d go from the Internet Zone, where ActiveX and Script were allowed but restricted, to the Local Machine Zone Lockdown, where active content wasn’t permitted to run at all!
That seemed sensible enough, I admitted after I understood the threat. Still, something seemed off—I understood why ActiveX was so dangerous, but what was wrong with script? Script alone, without any ActiveX controls, seemed like it should be safe. Right?
His terse response was “Do you understand Same-Origin-Policy?”
Now, I assumed the answer was “yes, of course, same-origin-policy allows content from one site to read content only from itself.” That’s true as far as it goes, but it overlooks one of the many subtleties in this very complicated security mechanism. The problem is that all content on your local computer is inherently same-origin to itself. That means that the attacker needs only to get any HTML into the local computer zone and then he can steal any file from your machine by simply loading that file into a frame, reading its contents into a string, and emitting that string out to the site he controls. This is a pretty glaring attack, and it requires no ActiveX controls or other plugins at all.
So, Local Machine Zone Lockdown also disables script from running in HTML content opened locally; a handful of other URLAction permissions are also restricted.
If any of the restricted URLActions are checked when running content in a page loaded locally, the permission is denied and the user is notified by the notification bar shown at the beginning of this post. If the user clicks “Allow Blocked Content” then the page is refreshed using the unlocked Local Machine Zone settings and it then runs with high trust.
Now, for most users this system works well—they rarely generate HTML content on their local computers and thus rarely see this prompt. However, for web developers, this notification can be a serious annoyance, and it’s especially annoying because, like my 2004-self, it seems to them to be a pointless security restriction.
The remainder of this article is for web developers to understand how to benefit from the security provided by LMZL without it unduly interrupting their work.
The Wrong Approach: Disabling Local Machine Zone Lockdown
By default FEATURE_LOCALMACHINE_LOCKDOWN is enabled for Internet Explorer, Windows Explorer, and many other applications that host the Web Browser Control. If you’ve written such an application, you should enable it too; you can see the list of applications that have opted in by viewing the contents of the registry key HKLM\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN.
The Internet Control Panel offers a checkbox that unsets the Feature Control key for iexplore.exe; you can find it inside Tools > Internet Options > Advanced > Security.
I strongly recommend that you leave the Allow active content to run in files box unticked, as it is by default.
You’ll notice that there’s also an individual setting for web content running from CDs that I’ll discuss in a minute.
Why do I recommend that you leave this unticked?
The first and most obvious reason is security—if you change this setting, the attacks mentioned back in the first section all become possible again. Local Machine content runs outside of the Protected Mode sandbox so it provides no protection against local content. While User Account Control likely means that it will only run with your permissions instead of full Administrator permissions, malicious local content could still utterly devastate your privacy and security.
The second and more subtle reason is predictability—there are a number of features that subtly change their behavior when LMZL is disabled, and this is not a configuration that is well-tested. For example, when LMZL is off, content retrieved using the RES:// protocol is no longer mapped to the Internet Zone and will instead be mapped to the Local Machine zone; this can result in functionality bugs because the content is running in an unexpected zone. There are a handful of these very subtle behaviors and folks have wasted quite a bit of time discovering that some “major issue” was in-fact caused by having a non-default setting here.
A Word about CDs
Remember back when we got our bits on little plastic disks that spun like Frisbees? Those were somewhat common back in the early 2000s, and the IE team didn’t want to force users to turn off LMZL entirely to get CD-based HTML and script content working again.
Because CDs were inherently read-only, the end user couldn’t simply fix the HTML content to make it work. Hence, we provide an independent setting that allows content from CDs to run with unlocked permissions. If GetDriveType returns DRIVE_CDROM for a given file, then we consult the state of the \Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN\Settings\LOCALMACHINE_CD_UNLOCK registry key; if it’s set to 1, then Internet Explorer will allow content to run with full local permissions.
While you’re unlikely to ever need to change this setting (who uses HTML on CDs anymore), it’s reasonably safe to change the Allow active content from CDs setting if you need to do so for some reason.
The Right Approach #1: Serve content from a web server
As a web developer, your best bet is to simply serve your web content from a web server, just like you’ll do in production. This allows you to avoid the Local Machine Zone Lockdown problem, and can also make your testing more accurate by eliminating other factors that differ between HTTP-served content and FILE-loaded content.
There are plenty of great options to take advantage of—IIS Express, the Visual Studio Test Server (“Cassini”) or even Apache or another 3rd-party server product. In a pinch, if you’re not looking to do anything complicated, you can simply drag-drop your files into the Fiddler AutoResponder tab and Fiddler will dutifully return them over HTTP to your browser.
The Right Approach #2: Use the Mark-of-the-Web
The Mark-of-the-Web (MotW) is a technology introduced in XPSP2 along with the Local Machine Zone Lockdown feature. A MotW allows a file to be tagged as having originated in the Internet Zone. That way, the rest of the system can behave accordingly, recognizing that a given file might not deserve the same degree of trust that is normally afforded to local files.
For instance, an executable file with a MotW on it will result in a security prompt when opened by the shell:
Importantly for web developers, HTML content that bears a MotW will open in the Internet Zone by default; this allows script and ActiveX controls to run with their default Internet-zone permissions, avoiding the notification bar.
The Mark of the Web comes in two forms: HTML Comment and Alternate Data Stream.
Mark of the Web via HTML Comment
When you save a HTML file from the Internet, Internet Explorer will inject a mark of the web comment into the file on your behalf—that way, when the file is loaded, no Local Machine security prompts are shown.
Web developers can easily inject their own MotW into files they’re working on to avoid the annoyance of LMZL. Simply save your file as UTF-8 or Big Endian Unicode (Little Endian is not supported). Within the first 2kb of the file, just inside the document type declaration, add the following HTML comment:
<!– saved from url=(0014)about:internet –>
Warning: A CRLF sequence (\r\n) must appear directly after the closing –>. If anything (including whitespace) is placed between the > and the end of line, the MOTW will be ignored.
This comment directs Internet Explorer to load this file with Internet-zone permissions; it will not be able to load or frame other HTML files that lack a Mark-of-the-Web.
Mark of the Web via Alternate Data Stream
Not all file types downloaded from the Internet are textual (for instance, my dumptrash.exe executable shown above), so another mechanism was needed to mark such files as originating from the Internet.
The NTFS file system supports Alternate Data Streams (ADS) which are associated with a given file and contain additional metadata. For instance, Internet Explorer stores a Favorite’s FavIcon image in an alternate data stream on the .URL file that represents the favorite. We use a similar strategy for storing mark of the Web information.
The Mark of the Web is stored as a Zone ID (Internet == 3) in an ADS named Zone.Identifier that is attached to a downloaded file; this ADS is created when the application uses the IAttachmentExecute::SetSource method or an IZoneIdentifier is manually added. You can discover Alternate Data Streams using the SysInternals Streams tool, and view their contents with notepad:
The Alternate Data Stream travels with the file as it’s copied between NTFS disks, but will be lost if the file is ever copied to a FAT file system disk (like many USB keys, CDs, etc) that doesn’t support ADS. If you use Windows Explorer to extract a ZIP file with the MotW ADS, it will be copied to each file extracted from the archive.
You can also direct Windows Explorer to remove the MotW stream using the Unblock button at the bottom of the file properties dialog.
This (utterly non-obvious) step may be required to properly interact with some types of files—in particular, if you download a CHM file, the embedded help topics will not properly display until you remove the MotW.
Implict MotW: Integrity and File Path
Files that lack a MotW in a comment or an ADS may be implicitly assigned to the Internet Zone for one of two other reasons. First is the integrity level of the file. Every file written by a Protected Mode browser instance running at Low Integrity will be tagged with a Low Integrity Label. You can view this label using the ICACLS tool:
Additionally, any file within the Temporary Internet Files folder path will automatically be assigned to the Internet Zone; this is useful for Windows XP, which does not support the Integrity Level system.
Whew! That was a lot to cover, but hopefully I’ve helped you understand why Local Machine Zone Lockdown exists, and how web developers can avoid annoyance.
 Not all browsers behave the same way with regard to same-origin-policy for local files. There’s no standard for this behavior, and compatibility with existing scenarios required that Internet Explorer maintain our existing behavior when XP SP2 shipped.