I’m super excited because after eight months at EMC, I’m a part of my first software release, EMC Virtual Storage Integrator (VSI) 4.0 for VMware vSphere. VSI 4.0 not only contains all of the functionality of previous incarnations, it also represents a completely new approach to cross-team collaboration and feature interoperability. Stay tuned for an upcoming post all about VSI 4.0!
This post, however, is all about two issue we ran into when we released VSI 4.0 to industry insiders. Right off the bat people had problems downloading the installers. One person even had an issue running the installer because of the operating system’s restrictive security settings. This is known as “The Caper of the Internet Sandboxes and Digital Signatures!”
The first problem that we encountered prevented some users from downloading our installers from PowerLink, EMC’s software distribution platform. Our installers are built using a .NET installer technology and
are were (now they are zipped up to prevent the discussed issue from occurring) portable execution images (EXE files). When attempting to download the installers customers found that Internet Explorer (IE) would simply hang and eventually crash. Other browsers, however, worked without issue. I managed to reproduce the issue using the following systems:
- Windows 2003 Server x86 with IE8
- Windows 2008 Server R2 x64 with IE9
- Windows XP SP3
- Windows XP SP3 x86 with IE8
- Windows 2003 Server x86 with IE8
- Windows 2008 Server R2 x64 with IE8
As you can see there does not seem to be a commonality between OS or browser versions. The downloads simply hung on some systems and not others. I even moved the file to multiple web servers (both IIS and Apache) to rule out a server issue, and attempting to download the EXE from any web server on a system that failed would always fail. So it’s definitely a client-side issue. Not only that, but it is an issue that is specific to .NET EXEs, as existing EXEs produced with C++ were not exhibiting the same issue.
At this point I decided to take our own EXEs out of the equation since they are both digitally signed (more on this later) as well as embedded with a special manifest which demands User Access Control (UAC) privilege elevation. I created a brand new .NET 3.5 Console Application using Visual Studio 2010 and added no additional code beyond the boiler-plate code inserted by Visual Studio. I compiled the application as TestExe.exe and placed it on a web server. It too exhibited the same symptoms as the VSI 4.0 EXEs.
On Windows 2008 Server an actual error would occur as opposed to the browser simply crashing on Windows 2003 Server, and I was able to gain further insight into the underlying problem. We were receiving errors such as System.BadImageFormatException and System.Security.SecurityException. It was then that I noticed the errors were not being thrown from the iexplore.exe process (as expected, since that is the image that spawns the IE process), but rather an image that I had not heard of until Saturday, ieexec.exe.
It turns out that ieexec.exe is a program that IE uses to host remote programs in an “Internet Sandbox”. This is where my debugging of the issue spun off into many unproductive tangents. The most promising one (at first) centered around the idea the type of processor architecture that ieexec.exe was compiled for versus the EXEs that were being download. The platform architecture angle turned out to be a bust, specifically since I was able to reproduce the issue on x86 systems.
However, investigating the aforementioned possibility did cause me to use Process Explorer to filter ieexec.exe during a download attempt. And what I found surprised me! The files were in fact being downloaded in their entirety and then ieexec.exe was crashing.
It dawned on me that ieexec.exe was treating these EXEs as remote programs that should be launched directly instead of saved to disk. And of course the programs would throw exceptions upon launch because executing an image from a remote web server would violate just about every .NET security policy known to man!
To prove my theory I relaxed the security on the system by turning it off with the caspol.exe tool. And voila! Clicking on a link to my TestExe.exe application caused a command prompt to briefly appear and vanish — the application had been successfully hosted from within ieexec.exe. Not only that, but I could also launch my installers. Of course, this was not a permanent solution for customers, and it certainly did not explain why IE was treating these EXEs as remote programs instead of simply downloading them. Isn’t an EXE on a web server simply an octet stream that is saved to disk?
Luckily, thinking along these lines led me to the following StackOverflow post. It turns out that .NET installs a client plug-in into IE that examines the stream of remote EXE images to determine if they are CLR code. If so they then are not treated like regular downloads, instead they are hosted as remote programs inside of ieexec.exe. Just one more reason not to use IE in my opinion.
So what is the solution? There are a few:
- Don’t use IE. Although IE8 and 9 are pretty good browsers, they are still too intertwined with the OS to treat the web as a remote resource. Issues like this one illustrate that well. Chrome is a great, light-weight browser. I use Safari myself.
- As the aforementioned StackOverflow article mentions, add a Content-disposition header to all .NET EXEs. You can test this out on my web server. I created a page where you can download TestExe.exe with the header and TestExe2.exe without the header. On systems that fail, the second link will not work while the first one will.
- Zip any .NET EXEs you post for download. This is probably the best solution.
I’m still not sure why this bug? occurs on some systems when it doesn’t on others. It seems to me that the MIME type filter that is installed inside of IE by .NET should be present on all Windows systems, but clearly there is some specific set of settings that cause .NET EXEs to be treated differently on different systems. For what it’s worth, I was also able to resolve the issue by playing around with client-side security settings, but never found a universal answer.
Once we rectified the download issue we were faced with yet another fun problem. It seems that the digital signature we signed our installers with was not valid according to one of our early adopters.
Now, I have to take a minute and point out that we have a fairly rigorous testing process. Before our software is ever distributed to customers it runs on all of the engineers’ systems, goes through Design and Verification Testing (DVT), Quality Assurance (QA), and finally some of our sales staff and vSpecialists take it for a spin. Not to mention that some of the functionality we develop is also certified by VMware. So you can see, we don’t develop in a vacuum. The fact that we ran into the download issue caught us off guard, but I think the issue with digital signatures did even more so.
Regardless, the evidence was explicit, the signature chain did not appear valid on one of customer’s systems. Normally this isn’t a problem, as only Windows drivers by default require valid digital signatures to be installed. However, on this particular system the security was restrictive enough to prevent the user from installing VSI 4.0. Obviously this is not a good thing.
It turns out that the Thawte-provided code signing certificate is issued by an intermediate certificate authority (CA) with a common name (CN) of Thawte Code Signing CA which is not present on Windows systems by default. The code signing CA is issued by the Thawte Premium Server CA, which is installed by default on Windows systems via Microsoft security updates. Thus, the digital signatures appear as invalid because the intermediate CA in the chain is not present on most users’ systems.
Why wasn’t this caught in testing? Simply put, most of the time an invalid signature chain won’t prevent you from installing software, but given the right security constraints it can. That singular case managed to pop up. What can we/you do about it? Glad you asked.
- Customers who encounter issues with the digital signature with VSI 4.0 should follow the instructions posted at the following Thawte knowledge base (KB) article. This particular article also states that the absence of the intermediate CA shouldn’t prevent the EXE from running, but clearly it can if the security is restrictive enough.
- Future versions of VSI 4.0 will include the Thawte Code Signing CA as part of their digital signature’s certificate chain. This will cause the digital signature to be valid without any action taken on the part of a user since the chain will be valid on their system since they already have the root certificate that issued the intermediate code signing certificate.
Both solutions aside, most customers won’t have this issue. As I mentioned above, the installers were tested quite thoroughly prior to release. This particular error will only occur on a very small sub-set of uber security-conscious users’ systems (I’m looking at you Ed Haletky!).
If you’re curious as to why the intermediate CA was not included in 4.0 release’s digital signatures, the answer is simple — the signtool.exe utility from Microsoft does not include an option to do so from the command line. It turns out, however, if the PFX container contains the intermediate CA in addition to the public and private key of the signing certificate, or if the Local Computer’s Intermediate Certificate Authorities store contains the Thawte Code Signing CA at the time of the signing, the intermediate CA is automatically included in the signature. We’ve added the intermediate CA to the Intermediate Certification Authorities store on our build agent, so future installers will ship with enough of the certificate chain to validate it.
Having my first release out the door feels great. Hopefully the lessons I learned from it can benefit others in the future. I had a heck of a time finding the answers to these two problems in particular, so maybe with this blog post out there, Google has been kinder to you if you’re reading this now.
Hope this helps!