Geeks With Blogs
Blog Moved to Blog Moved to
In previous posts, I talked about designing your classes with security in mind.  Designing assemblies is no different when it comes to keeping security in mind at all times.  Today I will cover what things to keep in mind when designing secure assemblies.
The basic points we will be covering today with regards to assembly security is:
*  Who is the target for the assembly
*  Identify Potentially Sensitive Code
*  Identify the Resources Needed
*  Explore Trust Levels
*  Abstract or Sandbox Highly Privileged Code
*  Define the Public Contract/Interface
Who is the Target for the Assembly
When designing assemblies, one must keep in mind what the target and function of your assembly is.  Some applications such as Windows Forms have different security mechansims and concerns than an ASP.NET application.  The overall function of the assembly should define which sets of security features you need to implement.  For example, the Data Application block should focus on database access security features.
The Enterprise Library is a good example of this.  There are three assemblies involved with logging features.  Each is separated so that each one can function on its particular target.  In this case, we have a central dll, and two providers, one for database logging and one for MSMQ technology.
To Strong Name or Not to Strong Name
As part of this subject, we need to determine whether strong naming the assembly makes sense.  The typical response is that you only strong name assemblies that you intend to share among other applications.  But is this really the case? 
I posted last week about Rocky Heckman's screencast about Assembly Hijacking in which an assembly without a strong name could be replaced with a malicious assembly if it has the same signatures.  This of course brings up all sorts of security questions to look over as well.  I tend to strong name most assemblies, especially those mission critical.  If you haven't seen the webcast, I recommend that you do.
Identify Potentially Sensitive Code
If you are working with more secure functions, it might be a good idea to put specific permissions as to whom can execute it.  For example, we may only want a System Administrator to be the only one to reset a password.  We need to identify all sensitive and privileged events and utilize the PrincipalPermissionAttribute class on the classes, methods or properties as appropriate. 
Below is an example of how we would restrict the access to a class:
[PrincipalPermission(SecurityAction.Demand, Role=@"DOMAINNAME\Administrator")]
public class SystemConfigurationManager { ... }
Identify the Resources Needed
You should also identify which resources their associated permissions that you assembly requires.  For example, your data access assembly will require access to a SQL Server 2000 database as well as needing permission to log information in the Event Log.  These permissions must be taken into account when deciding how you should implement security with your assemblies.
Explore Trust Levels
The target environment may have restrictions on which resources can be accessed by your assembly.  There may ben operations that are not permitted unless the assembly is fully trusted.  Let's explore the various trust levels.
Full Trust
By marking an assembly with Full Trust permissions, the assembly has unrestricted access set of code access security permissions.  This means that the assembly has unrestricted access to your system resources within the restrictions of the operating system security context.  When you install your assembly into the Global Assembly Cache (GAC), your assembly has a Full Trust by default.  Web applications also by default have Full Trust unless overridden in the configuration file.
You can specify in your AssemblyInfo.cs in Visual Studio 2003 for FullTrust by doing the following:
[assembly:PermissionSet(SecurityAction.RequestMinimum, Name = "FullTrust")]
In Visual Studio 2005, the Full Trust is on by default on the Project Properties for your Windows, Console or ASP.NET applications.  For class libraries, you can use the method from above.
Partial Trust
Partial Trust is defined as anything not marked Full Trust.  This includes other built-in permission sets such as Nothing, Execution, Internet, LocalIntranet, and SkipVerification.  As you can see, the trust level depends on executing code's origin, such as having a different trust level for an assembly on a network drive versus on your local machine.
You will want to be careful about supporting partially trusted aseemblies, as they bring another set of risks into your project.  By default, partial trusts do not work unless you mark your assembly with AllowPartiallyTrustedCallersAttribute or you do not have a strong name to your assembly. 
To use this, put this in your AssemblyInfo.cs:
Abstract or Sandbox Highly Privileged Code
In order to avoid granting too many permissions just to satisfy a small portion of your application, it would be best to extract these methods and place them in a separate assembly.  This term is called sandboxing, which is to take this code and give it its own sandbox which its privileges. 
For example, with my BITS wrapper that I wrote, the ability to call unmanaged code is necessary.   You may also want to move all your P/Invoke methods to a common area for that same purpose, as they can require special permissions that the rest of the application does not need.
To be able to use unmanaged code from your assembly, you must have this in your AssemblyInfo.cs:
[assembly: SecurityPermission(SecurityAction.RequestMinimum, UnmanagedCode = true)]
Define the Public Contract/Interface
When defining assemblies, you must also keep in mind which classes must be public and which can stay internal to the assembly.  The best way to reduce the attack surface is to minimize the number of public classes available.  We want to expose only things that will go along with our public contract (which means what me must provide in order to get the job done). 
For example, we should not expose internal classes which could contain possibly sensitive information.  We should design our assemblies so that they are self containing and not making a lot of extraneous calls to external assemblies.
In conclusion, I hope I gave you a few things to think about when designing your assemblies.  Security is involved at all levels of design from the prduct as a whole, down to each assembly, class, method and property.
Posted on Monday, June 5, 2006 2:34 PM .NET , C# | Back to top

Comments on this post: .NET Code Access Security - Assembly Design Considerations

# re: .NET Code Access Security - Assembly Design Considerations
Requesting Gravatar...
Very Useful one.Nice Article.
Left by MaheshKumar.R on Jun 07, 2006 11:00 PM

Your comment:
 (will show your gravatar)

Copyright © Matthew Podwysocki | Powered by: