On the Microsoft Security Blog, Tim Rains, the director of the Trustworthy Computing division, published the top 8 cyber threat predictions for 2014:
- Cybersecurity Regulatory Efforts Will Spark Greater Need for Harmonization
- Service-Impacting Interruptions for Online Services Will Persist
- We Will See an Increase in Cybercrime Activity Related to the World Cup
- Rise of Regional Cloud Services
- Dev-Ops Security Integration Fast Becoming Critical
- Cybercrime that Leverages Unsupported Software will Increase
- Increase in Social Engineering
- Ransomware will Impact More People
The list includes perspectives from senior cybersecurity leaders at Microsoft, so definitely worth to read them in detail.
We have an application that is built on .NET 4.0 Client Profile and uses SQL Server Compact Edition. Because it does not rely on the latest core OS technologies, it runs very well on older Windows versions, which is required by the end-users. To test the latest version I booted a fresh Windows XP virtual machine, and successfully installed the app on it. However the app crashed at the first database operation with the following exception:
System.DllNotFoundException: Unable to load DLL ‘sqlceme35.dll’: The specified module could not be found. (Exception from HRESULT: 0x8007007E)
Obviously, the requested file was in the right folder, and we didn’t change anything in the last version of the app that could explain this exception. So what has been changed?
I couldn’t reproduce the issue neither on Windows 8.1, nor on Windows 7, and not even on older XP machines that had the previous version of the app. And although the previous version was running perfectly on XP, it crashed in the fresh VM, so my conclusion was that something is different in the VM.
First I used the VM downloaded from the modern.ie site, and I thought that VM has some specificity that breaks our app. So I installed Windows XP from ISO and spent hours and hours to install all the patches from Windows Update. However it didn’t help, the app crashed like before.
Finally I used ILSpy and peeked into the System.Data.SqlServerCe assembly, and because it was referencing .NET Framework 2.0, I gave it a try and installed that older Framework version side-by-side to the new version. And to my surprise the issue was gone!
The beauty of the case:
- Windows Update was not installing .NET Framework 2.0, only the newer version. It was not the case previously.
- The .NET 4.0 Client Profile was not enough, SQL Compact Edition required version 2.0 as well.
- I understand that there was no problem on Windows 7, because that OS contains .NET 2.0, but why didn’t the app crash on Windows 8.1 which doesn’t install .NET 2.0 by default?
I received the following error message when I tried to compile a project:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\CodeAnalysis\Microsoft.CodeAnalysis.targets(214,5): error MSB4175: The task factory "CodeTaskFactory" could not be loaded from the assembly "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll".
Could not load file or assembly ‘file:///C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v12.0.dll’ or one of its dependencies.
The system cannot find the file specified.
The specialty of the case is that this machine had no VS 2012 installed, but only VS 2013.
The root cause of the issue may be that from VS 2013 MSBuild is part of Visual Studio instead of the .NET Framework, and therefore the related files are relocated in the file system. The error message says that the system looks for the Microsoft.Build.Tasks.v12.0.dll file in the C:\Windows\Microsoft.NET\Framework64\v4.0.30319 folder, however I have that file in the C:\Program Files (x86)\MSBuild\12.0\Bin directory. So, I simply copied the file and voila, the error was gone.
This is probably not the most elegant solution to fix this error. But because I couldn’t change the source environment, and the fix works on my machine, I can live with it very well.
One of the most terrible pain points of correctly implementing authentication is to define how to handle unauthorized requests. So for example neither unauthenticated users, nor users who are not the members of the Admins group can request the /admin URL.
Thankfully the FormsAuthenticationModule in ASP.NET provides a built-in solution to this problem. When the module is initialized, it subscribes to the EndRequest event with the OnLeave event handler, and when the HTTP status code is 401, this event handler redirects the user to the login page. This is a very convenient feature for classic requests, however it may cause serious headaches for Ajax.
When the module redirects the request, the client receives a HTTP 302 Redirect header instead of the original 401 Unauthorized error code. As defined in the standard, the XMLHttpRequest client transparently follows the redirect and downloads the content from the URI specified in the Location header, which is usually the Login.aspx page. So when the success handler of the XHR is called, it will see the HTML markup of the login page as the result of the call, and the result code will be 200 OK which indicates success. Well, how you can handle this easily?
Until .NET 4.0 you had no other option to fix this behavior than adding a custom HTTP module to the ASP.NET pipeline. But ASP.NET 4.5 introduced a new HttpResponse.SuppressFormsAuthenticationRedirect property, which you can set to true to avoid the redirect, and force the FormsAuthenticationModule to send the original 401 error code to the browser. Because this property is attached to the Response, you cannot set it globally, but instead you have to flip this switch in every handler that requires this behavior. If you want to set it for every response, then you can implement this in the Application_EndRequest handler in global.asax.
Most cryptography related features of the ASP.NET platform relies on the machine key, therefore it is very important to assign unique machine keys to independent applications. Thankfully the default configuration looks like ensuring this both for the validation key and the decryption key:
The AutoGenerate option frees you from manually setting the keys, and the IsolateApps options ensures that unique keys are generated for every application.
But not always!
ASP.NET will definitely generate a key, but it is neither the validation key, nor the decryption key, but instead a base key (let’s call it the machine key), which is then transformed into the validation key and the decryption key. The base machine key is stored in the registry in the following location:
Note that this key sits in the HKEY_CURRENT_USER hive, so the generated machine key belongs to the user’s that runs the application profile. This means that if you have two applications in IIS which are running with the same process identity, they will use the same machine key! One more reason why you should forget the SYSTEM, LOCAL SERVICE and NETWORK SERVICE accounts, and run all your web applications with separate ApplicationPoolIdentity. This also shows that the application pool is the real app isolation boundary.
Having two applications that share the same base key is not necessary a problem, because the keys used to validate and encrypt are created with additional transformations from this key. This transformation is determined by the second modifier after AutoGenerate. If you set IsolateApps, the runtime will use the value of the HttpRuntime.AppDomainAppVirtualPath property, which is different for two applications sitting in different virtual directories on the same website, so the generated keys will be different (which is good).
On the other hand, if you have two applications in the same path but on different websites, the value of this property will be the same for both apps. For example for an app that sits in the site root, the value is “/”, so IsolateApps does not provide you the isolation you expect!
To solve this problem ASP.NET 4.5 introduced a new modifier called IsolateByAppId, which uses the HttpRuntime.AppDomainAppId property instead of the AppDomainAppVirtualPath. The value of this property is something like this:
The “3” in the middle is the ID of the site in my case, and “ROOT” means that the app sits in the site root.
To summarize: the default AutoGenerate,IsolateApps setting does not necessarily provides you with unique keys, but if you host your apps in their own application pools which are running with ApplicationPoolIdentity, and you use IsolateByAppId instead of IsolateApps you can be sure, that your apps will use unique autogenerated keys.
The simplest way to test these setting is to use the localtest.me domain to create two separate websites, and then create a simple webpage that uses Milan Negovan’s code to retrieve and display the autogenerated keys.
If you use the IIS Express which comes with Visual Studio 2013, you may notice that as opposed to the previous versions, the webserver shuts down when you stop debugging. This behavior is thanks to the fact that from VS 2013 you not only have Edit and Continue support in 64-bit environments, but this feature is enabled by default for web applications:
If you don’t need this feature, and you turn it off, IIS Express will remain running.
IIS Express stores its configuration settings in the %USERPROFILE%\Documents\IIS Express\config\applicationHost.config file which eliminates the need for administrative permissions for changing it. As a consequence when you uninstall Visual Studio, the webserver configuration remains in the user’s profile folder.
It may happen, that you uninstall VS 2012, install VS 2013 and then when you create a new web application it behaves very strange, for example it asks for Windows authentication every time. This may be caused because you have created a website with the same name earlier in IIS Express, and its settings are preserver in the configuration file.
If you often create new web applications in Visual Studio, it is a good practice to clean up IIS configuration once in a while. Because there is no GUI for IIS Express, you can edit the applicationHost.config file directly or you can use the command line.
You can find the appcmd.exe for IIS Express in the C:\Program Files (x86)\IIS Express folder. You can use it to list the websites:
C:\Program Files (x86)\IIS Express>appcmd list site SITE "WebSite1" (id:1,bindings:http/:8080:localhost,state:Unknown) SITE "MyProject" (id:2,bindings:http/*:44441:localhost,https/*:44300:localhost,state:Unknown) SITE "WebSite1(1)" (id:3,bindings:http/*:44468:localhost,state:Unknown) SITE "WebSite2" (id:4,bindings:http/*:44465:localhost,state:Unknown)
If the names of the websites do not tell too much, then you can list the virtual directories, because that list shows the physical paths as well:
C:\Program Files (x86)\IIS Express>appcmd list vdir VDIR "WebSite1/" (physicalPath:%IIS_SITES_HOME%\WebSite1) VDIR "MyProject/" (physicalPath:W:\Projektek\MyProject) VDIR "WebSite1(1)/" (physicalPath:W:\Temp\WebSite1) VDIR "WebSite2/" (physicalPath:W:\Desktop\WebSite2)
You can even give them meaningful names by renaming them:
C:\Program Files (x86)\IIS Express>appcmd set site WebSite1(1) -name:Master SITE object "WebSite1(1)" changed
And you can delete the sites you don’t need any more:
C:\Program Files (x86)\IIS Express>appcmd delete site WebSite2 SITE object "WebSite2" deleted