Welcome to MSDN Blogs Sign in | Join | Help

Security Intelligence Report Volume 7 Released

Security researchers at Microsoft release a biannual "Intelligence Report" containing statistics about the software-related security incidents over the past 6 months. This report is called the SIR, and the latest version can be found here. There are many interesting charts and data points in the report, but I have two favorites from the latest edition.

As browser code quality improves, add-ons become a more appealing target:

Most browser attacks are against 3rd party (addon) code

Here's a chart of the types of malicious downloads that SmartScreen has blocked over the last six months:

SmartScreen blocks a wide range of malicious downloads

 

Microsoft remains committed to help protect you on the web-- IE8's SmartScreen and Microsoft Security Essentials are making a significant impact against the bad guys.

-Eric

Posted by EricLaw | 0 Comments
Filed under: ,

Using Meddler to Simulate Web Traffic

As mentioned back in July, IE8’s new lookahead downloader has a number of bugs which cause it to issue incorrect speculative download requests.

The “BASE Bug” caused the speculative downloader to only respect the <BASE> element for the first speculatively downloaded script file. Subsequent relative SCRIPT SRCs would be combined without respecting the specified BASE, which resulted in spurious requests being sent to the server. Eventually, the main parser would catch up and request the proper URLs, but the spurious requests waste bandwidth and could cause problems for some servers.

When first investigating the speculative downloader problems, I decided to use the Meddler HTTP Traffic Generation tool to build some test cases. Meddler is a simple little tool that allows you to write JavaScript.NET scripts to emulate a web server. Meddler allows for precisely timed delivery of responses, and includes classes to enable basic fuzzing scenarios. The best part of Meddler is that you can use a single MeddlerScript (.ms) file to contain an entire test case, even if that test case is made up of multiple pages, images, scripts, and other resources. These .ms files can be shared with others, run across multiple operating systems, and attached to bugs or test harnesses for future regression testing. The test machine only requires the .NET Framework and Meddler installed, and does not need IIS, Apache, Perl, ASP.NET, etc.

Because the base issue was so simple, I was able to quickly build a simple MeddlerScript which demonstrates the BASE Bug. If you’d like, you can follow along using my MeddlerScript: PreParserBaseBug.ms.

The test script generates the following sample HTML:

<html><head><base href="http://ipv4.fiddler:8088/pass/"></base>
<script type="text/javascript" src="inc/1.js"></script>
<script type="text/javascript" src="inc/2.js"></script>
<script type="text/javascript" src="inc/3.js"></script>
<script type="text/javascript" src="inc/4.js"></script>
<script type="text/javascript" src="inc/5.js"></script>
<script type="text/javascript" src="inc/6.js"></script>
<script type="text/javascript" src="inc/7.js"></script>
<script type="text/javascript" src="inc/8.js"></script>
<script type="text/javascript" src="inc/9.js"></script>
</head>
<body> Test page.</body></html>

Note that I plan to watch the network traffic with Fiddler, and because traffic sent to localhost isn’t proxied, I will use “ipv4.fiddler” as an alias to 127.0.0.1.

When visiting the Meddler test page, the traffic from IE is as follows:

Screenshot of original incorrect network traffic

As you can see, there are spurious download requests containing the wrong path; these are shown in red as the MeddlerScript is designed to return failure for such requests. Later, the correct URLs are downloaded as the main parser encounters the script tags and correctly combines the URLs.

Today's IE8 Cumulative Update (KB974455) fixes the BASE Bug. After installing the update, loading the sample HTML results in no spurious requests-- each script URL is correctly relative to the specified BASE.

Screenshot of corrected network traffic

Please note that while the BASE bug is fixed, the “4k Bug” is not fixed by this update. If you want to view that bug in action, try this script: PreParser4kBug.ms. As it is a timing issue, you may need to reload the “hammer” page a few times to encounter the problem.

While Meddler is rather simplistic, it can be very useful for sharing test cases and simulating the behavior of web servers. You can use Meddler to build reduced test cases that reliably generate problematic HTTP responses.

Until next time,

-Eric

Capturing Crash Dumps for Analysis

Sometimes, folks report crashes to the IE team that we are unable to reproduce internally. That’s usually because, as mentioned often, most crashes are caused by buggy browser add-ons.

In some cases, however, crashes occur even when running with browser add-ons off, and if we cannot reproduce the problem, the next best thing is a crash dump file from the affected machine.

Collecting crash dumps isn’t hard:

  1. Install WinDBG from http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx#ERB
  2. Configure WinDBG to run whenever a crash occurs: In an elevated command prompt, run WinDBG with the -I (case-sensitive) parameter.  For instance: 

    C:\debuggers\windbg.exe –I
  3. When the crash occurs, WinDBG opens.  Type the following command to generate a .DMP file:

    dump /ma %USERPROFILE%\Desktop\IECrash.dmp

Dump files tend to be dozens to hundreds of megabytes in size, so they typically cannot be readily passed around via email (although they often compress well). If a DMP file is requested, the person asking for the file will typically tell you how to return the file to them.

Depending on the problem reported, we may also want to get a network traffic log or a Process Monitor log.

-Eric

Posted by EricLaw | 1 Comments

Understanding DEP/NX

Despite being one of the crucial security features of modern browsers, Data Execution Prevention / No Execute (DEP/NX) is not well understood by most users, even technical experts without a security background.

In this post, I’ll try to provide some insight into how DEP/NX works, explain why you might encounter a DEP/NX crash, and convince you that turning off DEP/NX is almost never the right decision.

More than anything else, I hope you take away two important facts from reading this post:

  • In many cases where you encounter a DEP/NX crash, the browser would have crashed anyway.
  • The vast majority of DEP/NX crashes are caused by browser add-ons. If you run IE in No Add-ons Mode, it’s very unlikely that you will encounter a DEP/NX crash.

Background

I’ll begin by providing some background information on DEP/NX and how the browser makes use of it.

What is DEP/NX?

DEP/NX is a feature of modern CPUs that allows marking of memory pages as Executable or non-Executable. This allows the CPU to help prevent execution of malicious data placed into memory by an attacker. If the CPU detects that it is about to jump to (begin execution of) data which is in a memory page which is not marked as Executable, the CPU will raise an exception which results in termination of the process.

Stated another way, if DEP/NX determines that if a potentially dangerous jump is about to be made, the process is intentionally “safely crashed” to prevent a potential security exploit.

Checking Your Protection

You can see which processes are protected by DEP/NX using Task Manager’s Process tab. On Windows XP, you need to use Process Explorer instead. In either case, ensure that the “Data Execution Prevention box” is checked in the View > Select Columns menu, and a column in the process list will show the DEP/NX protection status.

Process Explorer showing DEP Permanent for iexplore.exe

As mentioned last year, Internet Explorer 8 enables DEP/NX protection by default. In IE7 and earlier, DEP/NX was disabled by default due to compatibility concerns that were resolved in IE8.

Opting-in to DEP/NX

Internet Explorer 8 uses the SetProcessDEPPolicy() API to enable DEP/NX. This provides the following benefits versus using the /NXCOMPAT linker flag:

  • It allows us to offer an Internet Control Panel checkbox and Group Policy option to disable DEP/NX if desired.
  • It enables DEP/NX on Windows XP SP3. The Windows XP loader does not check the NX Compatible bit.
  • It ensures that ATL_THUNK_EMULATION, an important compatibility feature, works properly.

Note: New applications without 3rd-party code compatibility concerns, targeted for use on Vista and later, should simply use the /NXCOMPAT linker flag.

Recognizing a DEP/NX Crash in Internet Explorer

When Internet Explorer 8 recovers from a DEP/NX-induced crash, it will not automatically recover the current tabs. This is a security measure designed to help prevent a malicious site from having multiple attempts to exploit a vulnerability. Instead of reloading the tabs, the browser will show the following error page:

Error page for DEP/NX Crash Recovery

Unfortunately, the nature of DEP/NX crashes makes it infeasible for the browser to “pin the blame” on the specific add-on that is responsible for the problem.

Why do DEP/NX Crashes Occur in the Real World?

Now, let’s take a look at why users encounter DEP/NX crashes in the real-world.

When the CPU is about to jump to a non-Executable memory page, there are three possible types of data in that page: malicious code, non-malicious code, and garbage data. I’ll discuss each of these in the following sections.

Jump Target: Malicious code

This is the scenario where DEP/NX shines. In this scenario, an attacker has put malicious data in memory that will be executed as x86 instructions if he can get the CPU to jump to it. The attacker then exploits some vulnerability to induce the CPU to jump to his data, typically using a memory-related vulnerability in an add-on or the browser itself.

In this scenario, the CPU notes that the attacker’s code is not in an executable memory page and prevents the interpretation of the attacker-supplied data as instructions. The attack is foiled and the user’s machine is protected. If not for DEP/NX, the attacker would have been able to execute his instructions and potentially infect the user’s machine with malware, steal their data, or achieve some other nefarious goal.

Now, the obvious next question is: What if the attacker can somehow get his data marked as executable?

The answer is that doing so is intentionally difficult. IE8 blocks the best known trick used to get the attacker’s data in an executable page. That means that the attacker must find some other way to get the memory page containing his instructions marked as executable.

The obvious choice would be for the attacker to call VirtualProtect() directly, passing PAGE_EXECUTE_READ as the flNewProtect flag. However, thanks to Address Space Layout Randomization (ASLR) it is difficult for the attacker to guess where the VirtualProtect function is in memory. If he guesses wrong (and he almost always will), the process will crash and not execute his attack instructions.

Jump Target: Non-malicious code

In this scenario, a browser add-on is designed in such a way that it expects to be able to execute data from memory pages which are not marked as executable, or otherwise makes a bad assumption.

There are a number of possible cases where this may happen.

Case #1: Code Generation

In the first case, the add-on (or the technology it is built upon) depends on the ability to execute dynamically generated instructions at runtime. Examples of this are the Java Virtual Machine (JVM) and the Active Template Library (ATL). These frameworks generate (“JIT compile”) executable code at runtime and jump to it. Older versions of these frameworks did not mark the memory pages containing the generated code as executable and would hence crash when DEP/NX was enabled. The Java team fixed this problem in the JVM years ago, and the ATL team also fixed this problem several versions ago.

Because ATL is so commonly used to build Internet Explorer add-ons, additional work was done to allow Windows to “emulate” the ATL Thunk code which violated DEP/NX, so that even if an add-on was compiled against an ancient version of ATL, ATL Thunk Emulation will ensure that the code runs properly inside Internet Explorer with DEP/NX enabled.

Case #2: Code Rewriting

In another common case, the add-on depends on “thunking” or modifying an existing Internet Explorer API or Windows function at runtime by rewriting the instructions in the existing function’s memory page. In order to accomplish this, the add-on uses VirtualProtect() to change the memory protection of the target page to allow Write and then update the memory with new instructions that point to some code that the add-on would like to have run inside the target function.

If the add-on fails to subsequently call VirtualProtect() to revert the memory protection back to allow Execute, the process will crash with a DEP/NX violation the next time that function is called.

More commonly, the add-on will later change the memory protection back to allow Execute, but the developer ignores the fact that it’s entirely unsafe to perform modification of shared code while any other threads are executing. While an add-on thread is modifying the code in a memory page, if any thread attempts to call any function in the same memory page, the process will crash. Internet Explorer makes extensive use of threads, so such crashes are likely if an add-on uses thunking.

Because timing is a critical factor here, the add-on may seem to “work fine” on one machine (e.g. a slower single-core machine) and always crash on another (e.g. a fast multi-core machine). This problem is just one of the major reasons why function thunking by Add-ons is not supported and is strongly discouraged.

Jump Target: Garbage data

In this scenario, inadvertent memory corruption has occurred such that the CPU is about to jump to arbitrary data somewhere in memory. This scenario is probably the most common source of DEP/NX crashes, particularly when the crash occurs at a seemingly random time, or when a browser tab is closed.

This arbitrary data isn't usually chosen by an attacker, and usually doesn’t even represent sensible x86 instructions. For instance, the jump may be to an address near 0x000000 where no code is loaded (near-null jump), if a virtual function was called off an object pointer which has been nulled. Or, the jump may be to some other address where code used to exist (stale pointer) but that memory was later freed and potentially reused for another purpose.

In this “garbage data” scenario, the process will almost always crash, even if DEP/NX were not enabled. That’s because the CPU is very unlikely to reliably execute arbitrary data as sensible x86 instructions. Most likely, the process will crash within a microsecond with an exception like “Access Violation”, “Invalid Instruction”,  “Divide by 0” or similar.

Attackers look for this type of memory corruption to use as an entry point in their attacks; they may, for instance, “spray the heap” with many copies of their malicious data, then trigger the memory corruption vulnerability with the hope that the CPU will jump into a copy of their malicious code.

Resolving DEP/NX Problems

Your best bet to resolve DEP/NX problems in Internet Explorer is to first confirm that the problem is caused by a buggy browser add-on. You can do this by running IE in No Add-ons Mode. After confirming that the problem is related to an add-on, you should use the browser’s Manage Add-Ons feature to disable unwanted add-ons and find updated versions of any add-ons that you wish to keep.

If you find that you’re encountering DEP/NX crashes in multiple software applications, it’s possible that you have malicious or buggy system software installed (e.g. malware or a buggy anti-virus product). You should check your system for malware and ensure that you install the latest updates for your system software.

Frequent DEP/NX crashes also suggest that your computer might have a hardware problem (e.g. bad system memory). To help rule out hardware failure, you can use the Windows Memory Diagnostic.

Conclusion

DEP/NX provides an important defense against malicious websites that may try to exploit vulnerabilities in your add-ons or web browser. By ensuring that you are running the latest version of add-ons and system software, you can improve your security and minimize the incidence of DEP/NX crashes. If you're currently using an older version (6 or 7) of Internet Explorer that does not have DEP/NX protections enabled by default, you should upgrade to IE8 as soon as possible.

Thanks for reading!

-Eric

DotNet UserControls Restricted in IE8

In the past, Internet Explorer supported a really easy way to host .NET UserControls in HTML. These controls worked much like ActiveX controls, but because they ran with limited permissions, sandboxed by the .NET Framework, they would download and run without security prompts.

It was a very cool technology, but didn’t see much use in the real-world, partly because the .NET Framework wasn’t broadly deployed when the feature was introduced. Later, ClickOnce, WPF, and other technologies took center stage, leaving this relic around, mostly unused beyond developer demonstration pages and tutorials.

Until the summer of 2008, that is. At BlackHat 2008, security researchers Dowd and Sotirov revealed that the loader for UserControls enabled bypass of memory-protection mechanisms, meaning that browser vulnerabilities could be exploited with improved reliability.

While Protected Mode and other features are useful to constrain the impact of vulnerabilities, DEP/NX and ASLR memory protection are a very important part of the overall mitigation strategy. After investigating the options, crawling the web to examine use “in the wild,” and consulting with the .NET team, we elected to disable UserControls in the Internet Zone by default for IE8.

Now, since the UserControls feature was first introduced, IE’s security settings allowed disabling ".NET Framework-reliant components," but the existing settings were overly broad. They controlled not only UserControls, but also out-of-process features like ClickOnce. Because out-of-process use of .NET is not a vector for memory-protection-bypass in the browser, we chose to create a new URLAction that would restrict only use of UserControls.

IE8 introduced the URLACTION_DOTNET_USERCONTROLS setting, which allows .NET UserControls to load only from Intranet and Trusted pages by default. On Internet pages, the controls are blocked as if they had failed to download. This setting is not exposed in the Internet Options dialog or in the Group Policy editor; it can only be controlled via the registry keys.

Reducing attack surface by removing an extensibility feature was painful decision, but ultimately a good one. Not long after we made this change, the new URLAction would cleanly block exploitation of a browser vulnerability that was unveiled at the CanSecWest security conference.

IE8 includes a number of important security features and defense-in-depth changes that raise the bar against the bad guys. If you haven’t upgraded yet, you should do so today!

thanks,

-Eric

Posted by EricLaw | 2 Comments
Filed under:

The User-Agent String: Use and Abuse

When I first joined the IE team five years ago, I became responsible for the User-Agent string. While I’ve owned significantly more “important” features over the years, on a byte-for-byte basis, few have proved as complicated as the “simple” UA string.

I (and others) have written a lot about the UA string over the years. This post largely assumes that you’re familiar with what the user-agent string is and what it’s commonly (mis)used for. 

In this post, I’ll try to summarize why the UA string causes so many problems (beyond browser version sniffing), and expose the complex tradeoff between compatibility and extensibility.

Background

First things first-- you can check the UA string currently sent by your browser using my User-Agent string test page.

Do you see anything in there that you weren’t expecting?

Changing the User-Agent String at Runtime

For IE8, we fixed significant bugs in the UrlMkSetSessionOption API, which allows setting of the User-Agent for the current process. Before IE8, calling this API inside IE would (depending on timing) set the User-Agent sent to the server by WinINET, or set the User-Agent property in the DOM, but never properly set both.

I developed a simple User-Agent Picker Add-on for IE8 that allows you to change your User-Agent string to whatever you like. You can then easily see how websites react to various UA strings. For instance, try sending the GoogleBot UA string to MSDN to see how that site is optimized for search.

Internally, the add-on simply exercises the URLMon API:

UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, szNewUA, strlen(szNewUA), 0)

Alternatively, Web Browser Control hosts can change the User-Agent string sent by hyperlink navigations by overriding the OnAmbientProperty method for DISPID_AMBIENT_USERAGENT. However, the overridden property is not used when programmatically calling the Navigate method, and it will not impact the userAgent property of the DOM's navigator or clientInformation objects.

Extending the User-Agent String in the Registry

It’s trivial to add tokens to the User-Agent string using simple registry modifications. Tokens added to the registry keys are sent by all requests from Internet Explorer and other hosts of the Web Browser control. These registry keys have been supported since IE5, meaning that all currently supported IE versions will send these tokens.

Other browsers (Firefox, Chrome, etc) do not offer the same degree of ease in extending the UA string, so it’s uncommon for software to extend the UA string in non-IE browsers.

The Fiasco

Unfortunately, the ease of extending IE’s UA string means that it’s a very common practice. That, in turn, leads to a number of major problems that impact normal folks who don’t even know what a UA string is. 

A few of the problems include:

  1. Many websites will return only error pages upon receiving a UA header over a fixed length (often 256 characters).
  2. In IE7 and below, if the UA string grows to over 260 characters, the navigator.userAgent property is incorrectly computed.
  3. Poorly designed UA-sniffing code may be confused and misinterpret tokens in the UA.
  4. Poorly designed browser add-ons are known to misinterpret how the registry keys are used, and shove an entire UA string into one of the tokens, resulting in a “nested” UA string.
  5. Because UA strings are sent for every HTTP request, they entail a significant performance cost. In degenerate cases, sending the UA string might consume 50% of the overall request bandwidth.

Two real-world examples:

My bank has problem #1. They have security software on their firewall looking for “suspicious” requests, and the developers assumed that they’d never see a UA over 256 bytes.

Some major sites are using super-liberal UA parsing code (problem #3) to detect mobile browsers. Unfortunately, for instance, Creative Labs adds the token “Creative AutoUpdate” to the UA string. Naive server code sees the characters pda inside that token and decides that the user must be on a mobile browser. The server might then return WML content that the desktop browser will not even render, or provide an otherwise degraded experience. Worse still, some sites don’t send a Vary: User-Agent response header when returning the mobile content, meaning that network proxies will sometimes start sending everyone content designed for mobile devices.

Ultimately, the problem is what economists call the Tragedy of the Commons, although personally I prefer the visual representation. You might remember that the extensibility of the Accept header leads to the same problem, although that header is sent so unreliably that no sane website would depend upon it.

Standards

It’s tempting to look to the standards for restrictions on the UA string. Unfortunately, the RFC for HTTP has little to say on the topic:

14.43 User-Agent

The User-Agent request-header field contains information about the user agent originating the request. This is for statistical purposes, the tracing of protocol violations, and automated recognition of user agents for the sake of tailoring responses to avoid particular user agent limitations. User agents SHOULD include this field with requests. The field can contain multiple product tokens (section 3.8) and comments identifying the agent and any subproducts which form a significant part of the user agent. By convention, the product tokens are listed in order of their significance for identifying the application.

User-Agent = "User-Agent" ":" 1*( product | comment )

Example:

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

Notably, the RFC does not define a maximum length for the header value, and does not provide much guidance into what “subproducts which form a significant part of the user agent” means. It suggests a few broad uses of the UA string on the server-side, without discussion of what problems such usage might introduce.

Motivations for UA Modification

OEMs and ISVs have a number of motivations for adding to the UA string.

  1. Metrics. Every server on the web can easily tell if your software is installed.
  2. Client capability detection. JavaScript can easily detect if your (ActiveX control / Protocol Handler / Client application / etc) is available.
  3. User Tracking. I don’t know of any current offenders, but at some point in the past some software would add a GUID token to the UA string. This token would effectively act as an invisible “super-cookie” that would be sent to every site the user ever visited.

Now, scenario #3 is clearly evil, and we have no desire to support it. Scenarios #1 and #2 aren’t inherently bad—but advertising to every site in the world that a given piece of software is available on the client is probably the wrong design.

Known UA Tokens

Here are some explanations of common tokens found in real-world IE UA strings.

Token Meaning / Component
SV1 Security Version 1- Indicates that XP SP2 was installed. Removed from IE7.
SLCC1 Software Licensing Commerce Client- Indicates Vista+ AnyTime Upgrade component is available. 
MS-RTC LM 8 Microsoft Real Time Conferencing Live Meeting version 8
InfoPath.2 InfoPath XML MIME Filter
GTB6 Google Toolbar
Creative AutoUpdate Creative AutoUpdate software
Trident/4.0 IE8 version of HTML Renderer installed
Zune 3.0 Zune Software client
Media Center PC 6.0 It's a Media Center PC
Tablet PC 2.0 It's a TabletPC
.NET CLR 3.5.30729 The .NET Common Language Runtime
chromeframe Google ChromeFrame addon
fdm FreeDownloadManager.org add-on
Comcast Install 1.0 Comcast High-speed Internet installer
OfficeLiveConnector.1.3 ??
OfficeLivePatch.0.0 Comcast browser installer
WOW64 Running in 32bit IE on 64bit Windows
Win64; x64 Running in 64bit IE
msn OptimizedIE8 Installed with MSN branding and services
yie8 Installed with Yahoo! branding and services

Alternatives to UA Modification

In many cases, allowing client-side script to detect a capability without forcing the browser to send that information to the server would be sufficient. While new APIs might be proposed for this purpose, we need an alternative that already works in all versions of IE.

You probably know that Conditional Comments can be used to detect the IE version, but they can also be used to detect custom information about any component listed in the registry’s version vector key. For instance, Windows 7 uses the new WindowsVersion entry to allow script to detect the OperatingSystemSKU.

To expose your capabilities via conditional comments, simply create a REG_SZ inside HKLM\SOFTWARE\Microsoft\Internet Explorer\Version Vector. The new entry should be named uniquely (e.g. EricLaw-SampleAddon) and contain a string in the format x.xxxx (e.g. 1.0002).

You can then detect the version (or absence) of your component using conditional comments:

<!--[if !EricLawSampleAddon]><script>alert("You don’t have my IE add-on yet. Go install it!");</script><![endif]-->
<!--[if lt EricLawSampleAddon 1.0002]><b>You have an outdated version. Go upgrade!</b><![endif]-->

These conditional comments are hidden from non-IE browsers, and will work properly in IE5 and above.

Conclusions?

Extensibility is an important aspect for any major software project, but can also be the source of severe compatibility problems that are extremely painful to fix in the future. As we increase the power of the web platform, we need to find ways to ensure that extension points and the tragedy of the commons don’t destroy the user’s experience.

Until next time,

-Eric

Good News: Microsoft Security Essentials Released

Microsoft’s free new anti-virus / anti-malware realtime scanner is now available as a free download. Installing MSE, a traditional signature-based scanner, alongside IE8’s URL Reputation-based SmartScreen Filter yields comprehensive protection to help keep your computers safe from malicious software.

There are a few things I like about MSE over other scanners:

  1. You won’t see advertisements trying to “upsell” you to a professional version.
  2. You won’t see “scareware” style warnings trying to convince you that MSE is providing value-- “oh my gosh, we found a cookie! Panic!”
  3. Signature updates are free—there’s no “subscription” that will expire and leave you unprotected.
  4. The product doesn’t install a bunch of 3rd party toolbars or other such nonsense— unfortunately, a common business model for other “free” products.

The product has been getting some great reviews.  I’ll definitely be installing this on my parent’s computer the next time I’m home.  :-)

-Eric

Posted by EricLaw | 0 Comments
Filed under: ,

Internet Explorer Cannot Download https://something

Earlier today, I was asked to troubleshoot a secure site where file downloads were always failing. Having seen this problem many times often over the years, I immediately suspected that the web developer wasn’t aware that

if a user tries to download* a file over a HTTPS connection, any response headers that prevent caching will cause the file download process to fail.

* Note that this applies to “downloaded” files that open in programs other than IE. It does not apply to resources that render inside IE’s HTML rendering engine, like images/script/css/etc.

When Internet Explorer encounters a HTTPS download that will not be cached, the download is aborted with the following dialog box:

Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found.

The Fiddler web debugger allows you to easily check to see whether a download contains headers that prevent caching.

Cache-preventing headers include:

  • A Cache-Control header with the tokens no-cache, no-store, or max-age=0
  • An Expires header that specifies a time in the past
  • A Vary header that specifies almost anything 

Without changing the site’s code, you can easily confirm that the problem is caused by cache-prevention headers using Fiddler’s Filters tab:

Fiddler Filter UI: Remove Cache-Control Header

Fiddler allowed me to determine that today’s instance was caused by cache-preventing headers. After the web developer updates these headers to allow local caching (e.g. Cache-Control: private, max-age=15) the file download process will work correctly.

-Eric

PS: In the unlikely event that the user has checked the Do not save encrypted pages to disk option inside Tools / Internet Options > Advanced, this error dialog may be shown for any file downloads from secure sites, regardless of caching headers. I recommend that folks avoid enabling this option, and use the Delete Browser History on Exit feature instead.

Posted by EricLaw | 14 Comments

New Tool: Compare IE Security Settings

“IE Zone Comparer” was designed to provide additional visibility into URLMon's security zone settings.  Pick any two collections of security zone settings, and IE Zone Comparer displays the values of those settings, highlighting any differences between the two collections.

http://blogs.technet.com/fdcc/archive/2009/10/01/viewing-and-comparing-ie-security-zone-settings.aspx

Posted by EricLaw | 0 Comments
Filed under: , ,

Understanding Domain Names in Internet Explorer

Web browsers use domain names for a variety of purposes, but how they’re used is much more complicated than most developers realize. In this post, I’ll attempt to cover the most important aspects of this topic.

Definitions

When talking about “domains” the terminology alone is confusing (and contentious).  So, let’s start with some simplistic definitions for terms used in this post:

  • A label is a single component of a domain name string, delimited by periods. For instance, “www” “microsoft” and “com” are the three labels in the domain name “www.microsoft.com
  • A plainhostname is an unqualified, single label hostname like “Payroll”, which typically refers to a server on a local intranet.
  • A FQDN is an absolute, fully-qualified domain name, like “www.microsoft.com
  • A Public Suffix is the suffix portion of a FQDN under which independent entities may register subdomains. For example, ltd.co.im is a Public Suffix. A Public Suffix contains one or more labels. Sometimes the term “effective TLD” is used as a synonym.
  • A TLD is a top-level-domain, the right-most label of a domain name
  • A gTLD is a generic TLD, like ".com”, “.net”, “.gov”, etc
  • A ccTLD is a country-code TLD, like “.us” or “.ru
  • ICANN (the Internet Corporation for Assigned Names and Numbers) is responsible for the creation and management of TLDs

When web developers talk about “the domain,” they’re often referring to what this post calls the Private Domain:

  • A Private Domain is a single label with a Public Suffix appended.

For instance, the two Private Domains “Acme.ltd.co.im” and “Bayden.ltd.co.im”, are each independently operated subdomains of Public Suffix “ltd.co.im”.

Okay, now on to the fun stuff.

Domains and the IURI Interface

First, some foreshadowing…

IE7 and above use a Consolidated URI handling feature which exposes the IURI interface.  Let’s have a quick look at a partial list of IURI property values from a sample URI: http://www.example.com/path/file.ext?query=val#frag

Uri_PROPERTY_ABSOLUTE_URI "http://www.example.com/path/file.ext?query=val#frag"
Uri_PROPERTY_DISPLAY_URI "http://www.example.com/path/file.ext?query=val#frag"
Uri_PROPERTY_RAW_URI "http://www.example.com/path/file.ext?query=val#frag"
Uri_PROPERTY_SCHEME_NAME "http"
Uri_PROPERTY_DOMAIN
aka Private Domain
"example.com" 
Uri_PROPERTY_HOST
aka FQDN or Plainhostname
"www.example.com"
Uri_PROPERTY_HOST_TYPE 1
Uri_PROPERTY_PORT 80
Uri_PROPERTY_PATH "/path/file.ext"
Uri_PROPERTY_QUERY "?query=val"

 

It’s important to note that if the URI contains only a plainhostname (e.g. “http://example/”) or a Public Suffix (e.g. “http://co.uk/”), then Uri_PROPERTY_DOMAIN is null.

Why Do Browsers Care About Domains?

Every browser must be able to determine the Private Domain for a number of uses, but in this post I’ll concentrate on IE’s use of this information.

1. Domain Highlighting in the Address Bar

IE8’s Domain Highlighting feature renders the Private Domain in black text and the rest of the URL in gray to help prevent the use of misleading URLs in spoofing attacks.

If the URL contains a plainhostname, the address bar will render the plainhostname in black instead.

2. Quota management for Local Storage

IE8 applies a per-Private Domain quota to values stored using the HTML5 Local Storage API.

If the Uri_PROPERTY_DOMAIN is null (because the URL contains a plainhostname) the browser will enforce the quota against Uri_PROPERTY_HOST instead.

3. document.domain relaxation

Same-Origin-Policy typically means that two pages must have exactly-matching FQDNs in order to script against each others’ DOM. However, HTML allows a page to relax its document.domain property to a suffix of its current value to enable cross host DOM communication within a single Private Domain. Script is not permitted to change its document.domain property to a string shorter than the private domain. This prevents sites from unrelated organizations from intentionally or inadvertently scripting against each others’ DOM.

4. HTTP Cookies

When setting a cookie, a website may specify which hosts the cookie should be sent to using the domain attribute. The browser must block attempts to set a cookie where the domain attribute does not end with the current page’s Private Domain. Failure to do so results in privacy and security concerns.

Privacy: Allowing unrelated domains to share cookies can result in “super-cookies”-- cookies which are sent to multiple unrelated organizations that happen to share a Public Suffix.

Security: Session-fixation attacks, where a good site and an evil site share a Public Suffix, and the evil site sets a malicious cookie on the Public Suffix so that the Good site is sent the evil cookie.

5. Security Zones – Mapping Domains to Zones

Because Public Suffixes are typically shared by multiple unrelated organizations, URLMon does not permit users to add all sites in a given public-suffix to a security zone.

We are aware that there are scenarios where such assignments may be desirable to some organizations (e.g. perhaps I would like to assign *.mil to the Trusted Sites Zone).

6. Security Zones – Automatic Zone Determination

URLMon (subject to some caveats) is configured by default to map plainhostnames to the Intranet zone.

7. Per-site ActiveX

When the user uses the Information Bar to allow an ActiveX control to run, Internet Explorer 8’s Per-Site ActiveX feature adds the current Private Domain to the Allow list for that control.

8. Compatibility View

Internet Explorer 8’s Compatibility View button adds the current Private Domain to the compatibility view list.

9. XSS Filter

IE8’s XSS Filter uses the Private Domain to determine whether a given navigation crosses from one Private Domain to another.

10. InPrivate Filtering

IE8’s InPrivate Filtering feature uses Private Domain information to help determine whether a given request is being sent to a 3rd party site.

11. Preserve Favorite Website Data

IE8’s Delete Browsing History feature includes a new “Preserve Favorites website data” option. As I described back in this post from June, this feature relies on the Private Domain to help determine whether stored data is related to one of the user’s favorite websites.

The Challenge of ccTLDs

In the early days of the web, most ccTLDs were organized in such a way that it was relatively easy to heuristically determine the Public Suffix of any FQDN. Over time, however, different ccTLDs decided that they wanted to create new Public Suffixes within their ccTLD, or decided to allow registration of Private Domains that the heuristics would incorrectly treat as Public Suffixes. Some nations (like Tuvalu) have outsourced registration of subdomains and allow anyone to obtain Private Domains within their ccTLD (.TV).

Prior to IE8, there was no one codepath in IE where the Private Domain was calculated, so over time several point-fixes were made to liberalize cookie setting in certain ccTLDs.

The heuristic Private Domain determination algorithm in IE5+ is:

1> If the final label is empty, drop it for the purposes of this algorithm 
Otherwise "www.example.com." would have four labels "www", "example", "com", "".  Instead, we drop the final label.

2> Name the labels Ln,...,L3,L2,L1; decreasing from start (Leftmost=Ln) to finish (Rightmost=L1). 
If at any point in this algorithm the result demands >n labels, getPrivateDomain returns "".

3> Check n > 1.  If not, there's no PublicSuffix, just a plainhostname. Return ""; exit. 
Dotless FQDNs consist of a host only, there is no domain.

4> Check L1 == "tv".  If so, getPrivateDomain returns L2.L1; exit. 
"tv" is a special-case "completely flat" ccTLD for historical reasons.

5> Check Len(L1) > 2.  If so, getPrivateDomain returns L2.L1; exit. 
Len(L1)>2 suggests L1 is a gTLD rather than a ccTLD. 
If Len(L1)<=2 we assume L1 is a part of a ccTLD.

6> Check if L2 in gTLD list "com,edu,net,org,gov,mil,int".  If so, getPrivateDomain returns L3.L2.L1; exit. 
gTLDs, when they appear immediately left of a ccTLD (modulo exception in step 4), are considered a part of the Public Suffix.

7> If L1 is in the list "GR,PL" AND L2 is NOT in the gTLD list, getPrivateDomain returns L2.L1; exit. 
GR and PL are considered "flat" ccTLDs EXCEPT when a gTLD appears in L2. 
getPrivateDomain("a.pl") returns "a.pl" 
getPrivateDomain("a.uk") returns ""

8> If Len(L2) < 3 getPrivateDomain returns L3.L2.L1; exit. 
getPrivateDomain("aa.bb.cc") returns "aa.bb.cc"

9> Otherwise, getPrivateDomain returns L2.L1 
getPrivateDomain("aa.bbb.cc") returns "bbb.cc"

While this heuristic worked pretty well for many years (and still works reasonably well in general) it clearly was becoming increasingly complicated due to the fact that each ccTLD established different operating practices (and those, in turn, changed over time).

Changes in Internet Explorer 8

For IE8, we’ve updated major codepaths to use CURI’s Uri_PROPERTY_DOMAIN for Private Domain determination, helping to ensure consistency throughout the various browser components.

IE8's version of URLMon maintains a list of special-cases which are used as exceptions to the default heuristics that CURI uses. You can click this link to view the list maintained as an XML resource inside URLMon.dll. The list contains elements which should be treated as Public Suffixes (the XML nodes named “tld”) and elements which should be treated as private domains (the XML nodes named “domain”).

From a browser architecture perspective, lists like this one are the option of last resort, for a number of important reasons. However, there’s no currently no standard that promises relief. One proposal which has been discussed in a few forums is to allow the DNS itself to indicate (via a new record) which names are part of a Public Suffix and which are part of a Private Domain, but that approach is not without problems.

The (Coming) Challenges with gTLDS

ICANN recently voted to allow organizations to create new generic TLDs. Introduction of new gTLDs may introduce additional problems, because previously most of the “special cases” were found only in ccTLDs. Other parties (like Certificate Authorities) would also likely be significantly impacted by this liberalization of gTLDs.

As this area is still developing, it will likely be the topic of a future post.

Until then…

-Eric

Posted by EricLaw | 4 Comments

Two New Tools Available from the SDL Team

Yesterday, IE Team alumnus Jeremy Dallman posted over on the Security Development Lifecycle team’s blog, announcing the release of BinScope and MiniFuzz. These two tools are part of the toolset that the Internet Explorer team uses to help verify the security of our product code.

If you’re building an Internet Explorer add-on (or any other product really), they’re great (free) additions to your toolbox to help ensure that the bad guys can’t abuse your code. The SDL team also posted two demo videos (BinScope video & MiniFuzz video) explaining the tools, and a whitepaper on how to integrate the SDL into an existing VSTS project.

-Eric

Posted by EricLaw | 0 Comments
Filed under: , ,

Preventing Automatic Hyperlinking in ContentEditable HTML

Today, a question from the mail bag…

Q: Is there a way to stop IE from “auto-magically” recognizing and creating hyperlinks inside HTML?

First, a bit of context. Web developers can use the ContentEditable property to allow users to edit part of a HTML page. This mechanism is often used to allow users to edit “rich text” when composing a blog post, comment, or HTML email. Similarly, Client Application developers can use the same property when hosting the Web Browser Control (WebOC), again for similar purposes.

However, you’ll notice that if you type text that looks like a hyperlink (e.g. http://example or a@example) into the editable HTML region, the web browser will automatically convert that text into an active hyperlink. In many cases, this automatic conversion is desirable, but in some cases it may not be.

Client Application developers can call IOleCommandTarget::Exec, passing IDM_AUTOURLDETECT_MODE and a boolean value specifying whether or not automatic detection should occur. Unfortunately, this command ID is not mapped to a command identifier string which can be used when calling document.ExecCommand().

This means that, unfortunately, current versions of IE do not offer a way to disable automatic hyperlink recognition from script in the page. There’s no great workaround for this. Some web developers have pointed out that script may execCommand(Unlink) to remove all hyperlinks from the current selection, but this may not be desirable for all scenarios.

-Eric

Posted by EricLaw | 5 Comments
Filed under: , , , ,

The Mystery of the Forgetful Browser Settings

A friend recently wrote to me, alarmed that the SmartScreen Filter feature was constantly turning off on his laptop with IE8. Despite manually re-enabling the feature using the Safety menu multiple times per hour, it was mysteriously and repeatedly turned off without any action on his part.

He was worried for two reasons: first, because he wanted to benefit from the great protection provided by SmartScreen’s anti-malware feature, and second, because he feared that perhaps he was already infected by malware and that it was turning off SmartScreen. I suggested that it wasn’t likely that a malware infection was disabling SmartScreen—if his machine was already infected by malware, the attacker need not bother trying to socially-engineer him into installing additional malicious code.

Fortunately, he was willing to let me have a quick look at his laptop to figure out what was going on. Process Monitor is a great tool for hunting down more than performance bottlenecks— it’s also easily used to watch for unexpected changes in Internet Explorer’s registry settings.

As it turns out, I happened to know that SmartScreen’s state is controlled by a registry key named EnabledV8, but using ProcMon’s filters to watch registry keys containing the word “phishing” would have worked just as well. After re-enabling SmartScreen and restarting the browser, ProcMon reported the following reads and writes to the EnabledV8 key:

EnabledV8 registry key reads and writes

As you can plainly see, IE initially reads the SmartScreen state as enabled (“1”) but shortly afterwards, a different process comes along and writes the value “0” to the key, disabling SmartScreen.  But what is ccSvcHst.exe?

Double-clicking on the first RegSetValue operation opens the Event Properties dialog, where we can see details about the event. By clicking on the Process tab, we easily can learn more about the ccSvcHst.exe process:

Norton360 Process

It turns out that this version of Norton 360 intentionally disables IE8’s SmartScreen Filter. Looking around the Norton control panel, I wasn’t able to find anywhere to turn off this behavior. I did notice that the control panel offered an “Anti-Phishing” checkbox. Experimentation revealed that when you use this checkbox to disable Norton’s phishing filter, Norton does not automatically re-enable SmartScreen Filter. However, with Norton’s filter disabled, the Norton 360 service stops repeatedly disabling SmartScreen.  If you uncheck the checkbox in the Norton control panel, and manually re-enable SmartScreen, your protection from phishing and malware sites resumes without further interruption.

(Update: Symantec has changed the SmartScreen-disabling behavior in updated versions of the Norton 360 product.)

While this wasn’t one of the harder cases I’ve been asked solve, the moral of the story is clear: using the right tools takes most of the work out of detective work.

Until next time,

Eric Lawrence

Posted by EricLaw | 0 Comments

HTML5 Implementation Issues in IE8

IE8 introduced support for some of the more stable features in the HTML5 spec. However, web developers have reported some problematic scenarios in IE8's support for these features, as described below.

1. postMessage only works for IFRAMES/FRAMES

The HTML5 postMessage function provides a great way for mutually distrusting documents (even cross-domain) to communicate securely and with high performance and reliability. Unfortunately, as reported on Connect, the HTML5 postMessage function does not work between tabs/windows in IE8.

Attempting to send a message to a different window or tab results in an exception with the text "Error: No such interface supported." You can test for this problem at the following test page. Click the Create Popup button and then in the popup window, click the Call postMessage directly button to attempt to send a message to the subframe from the popup window. In IE8, this demo will fail and the script will display the exception.

The test page demonstrates one case where there is a workaround for this problem. If the popup window instead calls a script function in its window.opener page (click the Call opener's proxy function button), that script function can call postMessage to send a message to the child frame. Unfortunately, this workaround often isn't possible, because same-origin-policy dictates that the popup window and the window.opener page must be from the same origin in order to call each other's script functions.

2. sessionStorage isn't properly shared between child frames

By design, the HTML5 sessionStorage feature is designed such that even tabs within the same browser session have independent sessionStorage objects.  If you change a sessionStorage attribute’s value in one tab, that change should not be reflected within another tab, even within the same browser session. 

However, sessionStorage is intended to be isolated per top-level-browsing-context, meaning that a page and any subframes on that page are intended to share sessionStorage values. IE8 does not reliably share sessionStorage objects between frames on a page.

A test page demonstrates this problem. Choosing a color from any of the three select controls on the page does the following:

  • Sets a cookie named sessionColor containing the color name
  • Sets a sessionStorage property named sessionColor to the color name
  • Sets a localStorage property named sessionColor to the color name

A timer runs in each frame.  Every 500 milliseconds, the timer does the following:

  • Changes the background color of the frame to the color specified in the cookie.
  • Updates the display of the current localStorage.sessionColor value
  • Updates the display of the current sessionStorage.sessionColor value
  • Updates the Current time value

When interacting with the demo in IE8, you will likely notice that while the cookie/backcolor changes properly across the frames, often one or more of the sessionStorage values are not properly updated.

Unfortunately, there's no trivial workaround for this problem; a page can use the postMessage function to push state changes between frames, but this is somewhat more complex than simply querying the value of properties on the sessionStorage object.

3. Changes to localStorage values are not reflected across active tabs/processes 

In contrast to sessionStorage, localStorage is meant to be shared across all browser instances, much like a persistent cookie. However, Internet Explorer's new session command does not properly interact with localStorage, so new browser sessions do not properly share localStorage information with other instances.

Using the same test page as in the previous example, change the localStorage session color to, say, blue. Then, use File > New Session to open a new browser session. Navigate that new window to the test page, and observe that while the background color of the page is properly reset (because session cookies are isolated by session) the localStorage value is improperly reset. You will notice that changing the localStorage values in the new session does not impact the local storage values of the prior session. Such isolation is not intended.

A Caveat about InPrivate Browsing

Note that scenarios #2 and #3 intentionally have somewhat different isolation behaviors when browsing with an InPrivate Browsing session instance. InPrivate Browsing sessions are intentionally isolated, and cookies and storage values intentionally start blank and are intentionally cleared at the end of the browser session.

-Eric Lawrence

Appendix
Cross-browser remarks: Firefox 3.5.3 and Safari 4.0.2 had no problem with scenarios #2, #3. Opera 10 and Chrome 3.0.195.21 could not complete the test because they do not support the storage objects. When using the "Private Browsing" feature, Safari throws a "Quota exceeded" exception when trying to use the storage objects. None of these browsers had problems with scenario #1.

Posted by EricLaw | 4 Comments

Welcome to Security Theater...

From the things that make you go hmm.... department:

http://personal.fidelity.com/misc/buffers/coming-soon-identity.shtml.cvsr
Choose a question like “In what city was your high school?” then enter the answer. This kind of information gives us a way to identify you that someone else won’t know or be able to fake.

In this century, I find the claim that this "significantly improves your online security" rather dubious. In the pre-2000 days before social networks and massive free databases, maybe this might have been more useful.

Posted by EricLaw | 1 Comments
Filed under: , ,
More Posts Next page »
 
Page view tracker