Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Never Write an Insecure ASP.NET Application Ever Again : Page 4

Learn to take advantage of the inner workings of ASP.NET's security model to help eliminate security vulnerabilities from your web applications.


advertisement
Change the Default Trust Level
Recall that the root web.config file has a setting that looks like this in a pristine installation of .NET:

<trust level="Full" originUrl="" />

There is nothing stopping you from changing this setting in the root web.config file and, in fact, that is what many web hosting companies do to provide a layer of security between the many web applications that might be running on a single server. By the way, the originUrl attribute is used to specify the URL of origin for the application for the WebPermission class, such as to allow connectivity back to the host of origin. You don't need to set this for the sample application.

You can override the trust level setting in any application by adding the trust element to your application's web.config file. To change the trust level for this article's sample application, add this line to its web.config (in the sample application you can instead uncomment the line if you wish):

<trust level="Medium" />

When you change from running with Full trust, the CLR and ASP.NET have to do a little more work when the assembly loads. They run through a basic five-step operation:

  1. The CLR parses the appropriate <trust> level setting and retrieves the value.
  2. The CLR loads the appropriate policy file, in this case web_mediumtrust.config.
  3. Placeholder variables, such as $AppDir$, are replaced with the actual runtime values.
  4. The CLR calls the AppDomain.SetAppDomainPolicy method to set the trust level for the application domain and the code executes. (Remember that this is the fourth policy level for .NET applications.)
  5. While the assembly is loaded, the CLR monitors the appropriate policy file for any changes. If any changes occur, the CLR tears down the app domain and rebuilds it with the new settings.
Make the change in the trust level and re-run the application. Click on the Get Contents or Get Path buttons and, given the absence of exception handling in the code, you'll be greeted by the unhandled exception shown in Figure 5. The crucial part of the message is "Request for the permission of type 'FileIOPermission' failed." Attempting to read the PATH environment variable returns no better results as you can see in Figure 6. Here the permission that is unavailable is EnvironmentPermission. In a real application, of course, you'd catch these exceptions either at the method level or in a global exception handler.

 
Figure 5: When the sample application runs with Medium trust, you can no longer read eula.txt in the System32 directory.
 
Figure 6: In Medium trust, you also cannot read the PATH environment variable.
So what's going on? Aren't the FileIOPermission and EnvironmentPermission part of the Medium trust level? They are. So what gives? The problem is that each of those permissions is granted in a restricted form, and the restrictions don't include reading eula.txt (or any file in System32) nor reading the PATH environment variable. This means that the Medium trust level won't work for this application.

What are the options to make the application run? You can choose from several:

  • If the protected operations—here to read eula.txt and the PATH variable—are not critical application requirements, get rid of the features. If they aren't critical, it is better to get rid of them rather than fiddle with security and maybe open nasty vulnerabilities!
  • Use another standard trust level. Besides Full trust, the only other more permissive option than Medium is High trust. But this is likely to have way more permissions than your application requires, which opens up potential security vulnerabilities. That pretty much eliminates this as a viable option.
  • Create a custom trust level with exactly the permissions your application needs. This is often the best choice since none of the standard trust levels are likely to exactly fit your needs.
  • Sandbox dangerous code into a separate, well-protected assembly. This is often a good choice when the entire application doesn't need elevated privileges, just a small section of the code. This way the potential security vulnerabilities are strictly limited.
The option you select depends on the nature of your application and its requirements. For the example in this article, I'm going to alter the scenario of the sample application a bit. Let's say that the ability to read eula.txt is something that has to happen throughout the application—Microsoft would be so proud!—and that slightly different code is needed each time. This means that you couldn't easily partition the file access code into a separate assembly. So the entire application needs the ability to read the eula.txt file—and only read it. For this I'll create a custom trust level to add the necessary permission.

Let's say that reading and updating the PATH variable is needed in just one place in the entire application, or that you want to use the same code over and over to do the same thing. This is a perfect use for sandboxing the Environment code—putting it in a separate assembly that receives the elevated privileges while leaving the main application's permissions alone.

Create a Custom Trust Level
You have to follow three basic steps to create a custom trust level and apply it to the sample application:

  1. Create the custom policy level file.
  2. Put the required permissions in the custom policy file.
  3. Set the application to use the custom trust level.
In the first step you create the policy level file. It is usually easiest to start with one of the standard policy files, and since the Medium trust level is close to what you need, you can copy that file to your application directory and rename it. So copy web_mediumtrust.config from the .NET Framework CONFIG directory to the application directory and name it web_customtrust.config.

Next you need to change the policy file to provide the FileIOPermission needed. You don't need to change the SecurityClasses section because FileIOPermission is already listed. And you don't need to change the CodeGroup section because the application will still meet the membership condition for the code group associated with the ASP.Net permission set. So you only need to change the permission set. Using the FileIOPermission (which is already part of the set) you can modify that element by adding the eula.txt file to the Read attribute of the permission, delimiting it from other entries with a semicolon:



<IPermission class="FileIOPermission" version="1" Read="$AppDir$;C:\WINDOWS\system32\eula.txt" Write="$AppDir$" Append="$AppDir$" PathDiscovery="$AppDir$" />

If FileIOPermission were not already in the policy file, we'd have to add it. How do you know what XML to use? The SecurityClass and IPermission elements in the policy file are derived from the serialized form of the permission object. So you can write code like this to generate the elements and attributes you need in a console application:

EnvironmentPermission envPerm = new EnvironmentPermission( EnvironmentPermissionAccess.Read, @"C:\WINDOWS\system32\eula.txt"); Console.WriteLine(envPerm.ToXml().ToString());

This code generates the following output, from which you can extract the information you need:

<IPermission class=" EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="C:\WINDOWS\system32\eula.txt"/>

In the final step you'll change the application web.config file to use the custom trust level. This requires both a securityPolicy element to define the trust level and associate the policy file with the custom level, and a trust element to actually set the trust level:

<securityPolicy> <trustLevel name="CustomTrust" policyFile="web_customtrust.config"/> </securityPolicy> <trust level="CustomTrust" originUrl=""/>

That's all that is necessary. Run the application again and see that it can read the eula.txt file without problem. Try entering ..\..\boot.ini however, and it raises an exception saying that the FileIOPermission needed is not available. That's because the CLR will only allow the operations defined in the IPermission element above, none of which involve boot.ini. Now, the application can only read eula.txt; any other file will throw the exception. The sample application is already more secure by using a modification of the Medium trust level rather than Full trust.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date