Administrator and Developer Guide to Code Access Security in SharePoint Server 2007
Summary: Understand Microsoft .NET Framework code access security (CAS) and how to work with it in custom SharePoint solutions. Explore configuration options, get best practices for managing CAS in SharePoint environments, and walk through a complex CAS scenario. (19 printed pages)
Andrew Connell, Critical Path Training, LLC
Applies to: Microsoft Office SharePoint Server 2007, Windows SharePoint Services 3.0
Introduction to Code Access Security and SharePoint
What Is Identity Security?
What Is Code Access Security?
Link Demands and Allowing Partially Trusted Callers
Understanding the Components of CAS in ASP.NET
Why CAS Is Important to SharePoint Administrators
Why CAS Is Important to SharePoint Developers
Working with CAS in SharePoint
Best Practices for Managing CAS in SharePoint
Real-World SharePoint and CAS Walkthrough
Download the code sample that accompanies this article:MSDN Sample—SharePoint CAS White Paper Demo Code.
Introduction to Code Access Security and SharePoint
Code access security (CAS) was introduced in the first version of the Microsoft .NET Framework. However, many developers using the .NET Framework have not needed to address the details of how CAS worked in most custom applications and so could simply ignore CAS. The story is different for SharePoint developers. Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0 make significant use of CAS for protection from malicious or dangerous code. All SharePoint developers should have a working knowledge of CAS so that they can identify and resolve security issues. All SharePoint administrators should have a working knowledge of CAS so that they can secure and manage their SharePoint servers and understand the implications of changing a Web application's trust level for third-party components.
This article provides a brief introduction to CAS, and explains why CAS is important to both SharePoint administrators and developers. It also explains how SharePoint uses CAS, describes the different options available to developers and administrators to manage CAS, and walks through the process of identifying and modifying CAS for a sample application.
What Is Identity Security?
The concept of CAS might not be familiar to you. CAS is better understood when put in the context of another type of security: identity or user security. Under identity security, code will execute under the permissions of the account that triggered the execution. For example, when installing Microsoft SQL Server on a new server, you are prompted for the user or domain account that will be used as the service account. The SQL Server Windows Service runs under this account and thus, all permissions granted to this account are granted to the SQL Server Windows Service (the SQL Server engine). Removing permissions from the service account will likely disable SQL Server or cause SQL Server to throw errors.
One problem with identity security is that it is not a very secure way to control access on distributed computers or servers used by many authenticated users. Consider another common problem. Many users log on to their workstations by using an account that is in the local Administrators group. Therefore, they have unrestricted access to everything on their local computer. The user can then browse to a seemingly innocent Web site that prompts to install an ActiveX control. Because the user's account is in the local Administrators group, after this control is installed it inherits the permissions of the user and can do anything the user can do, such as modify the registry, access network shares, or as in the case of the Melissa computer worm found in 1999, access the user's e-mail mailbox and send itself to everyone in the user's address book.
What Is Code Access Security?
CAS is unlike identity security. Instead of the code assuming the permissions of the user who is executing the code, code is given explicit permissions and can run only under those permissions, regardless of the permissions of the user who executed the code. Using the previous example, if the ActiveX control is denied access to the registry, then even if the user who executed the ActiveX control has rights to read and write to the registry, the ActiveX control fails when it tries to access the registry and throws a SecurityException.
The .NET Framework includes many CAS permissions that can be granted to code, such as SqlClientPermission for establishing database connections, EnvironmentPermission for controlling access to things like environment variables, and FileIOPermission for controlling access to the file system. When writing an application, developers can add security demands as attribute decorations on classes, events, properties, and methods, which trigger a run-time security check before executing the code. If an application is not explicitly granted a permission, the .NET Framework prohibits it from performing that action. Instead, it throws a SecurityException exception.
For more information about CAS in the .NET Framework, see Introduction to Code Access Security. Another good resource is the MSDN patterns & practices group's online book, Improving Web Application Security: Threats and Countermeasures, specifically, Chapter 9—Using Code Access Security with ASP.NET.
Link Demands and Allowing Partially Trusted Callers
Another piece of CAS developers should understand are link demands and the System.Web.Security.AllowPartiallyTrustedCallers attribute. In CAS, a link demand happens at run time during just-in-time compilation. Link demands occur when your code is linked to another assembly that contains a method or type reference. If the assembly that is calling your assembly is not fully trusted, the link is not permitted and a run-time exception is thrown. This is important in custom SharePoint assemblies containing Web Parts and controls because they will be called by assemblies that are not fully trusted, such as ASP.NET.
SharePoint developers have a way to address this issue and tell the .NET Framework that their custom assemblies can be called, or have link demands established, by assemblies that are not fully trusted. This is done by adding the assembly-level attribute System.Web.Security.AllowPartiallyTrustedCallers to the custom assembly.
Understanding the Components of CAS in ASP.NET
CAS has many components that come together to make up a very secure solution. Before diving into why CAS is important and how to manage it, it is important to understand the different components of CAS with respect to ASP.NET.
CAS Policy Files
As discussed earlier, applications must be granted specific permissions to run. The .NET Framework uses CAS policy files to define the permissions and grant these permissions to assemblies. There are three components to a policy file: security classes, named permission sets, and code groups. The following code snippet demonstrates the basic structure of a CAS policy file.
<configuration> <mscorlib> <security> <policy> <PolicyLevel> <SecurityClasses /> <NamedPermissionSets /> <CodeGroup /> </PolicyLevel> </policy> </security> </mscorlib> </configuration>
The security classes section of the policy file is where all the permissions used in the policy file are registered. Permissions are actually .NET Framework classes. When referencing them, it can be quite cumbersome to type and read the fully qualified name of the permission, which includes the namespace, type name, and strong name of the assembly that the class is found in. This is also known as the five-part name. To make things easier, you can register the permission in the security classes section of the policy file and give it a friendly name, for example, FileIOPermission instead of System.Security.Permissions.FileIOPermission, mscorlib, Version=188.8.131.52, Culture=neutral, PublicKeyToken=b77a5c561934e089. The following is a sample security class element.
<SecurityClass Name="FileIOPermission" Description="System.Security.Permissions.FileIOPermission, mscorlib, Version=184.108.40.206, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
These permissions are grouped together into a named permission set. Named permission sets take one or more configured permissions and assign the set of permissions a name that is easy to read. This makes it easier to assign the same permissions to multiple assemblies at one time. The following is an excerpt from the SharePoint SPRestricted named permission that grants assemblies the ability to perform actions such as retrieve the name of the user (from EnvironmentPermission), and read and write to the Web application's
<PermissionSet class="NamedPermissionSet" version="1" Name="SPRestricted"> <IPermission class="AspNetHostingPermission" version="1" Level="Medium" /> <IPermission class="DnsPermission" version="1" Unrestricted="true" /> <IPermission class="EnvironmentPermission" version="1" Read="TEMP;TMP;USERNAME;OS;COMPUTERNAME" /> <IPermission class="FileIOPermission" version="1" Read="$AppDir$" Write="$AppDir$" Append="$AppDir$" PathDiscovery="$AppDir$" /> [[..]] </PermissionSet>
A named permission set is then applied to code by using code groups. A code group applies a named permission set in different ways. The named permission set can be applied to all assemblies in a particular folder or applied to a specific assembly by using the signed assembly's public key BLOB (a signature; each signed assembly has a unique public key BLOB that is based off the key used to sign the assembly). This enables a named permission set to be applied to a group of assemblies or to a specific assembly. For example, the SharePoint CAS policy files grant all assemblies signed with the Microsoft key full trust. This ensures that all SharePoint code is not restricted.
The following is an example code group that grants the built-in SharePoint restricted named permission set to all assemblies that are deployed to the Web application's
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="SPRestricted"> <IMembershipCondition class="UrlMembershipCondition" version="1" Url="$AppDirUrl$/*" /> </CodeGroup>
After a CAS policy is defined in a policy file, it must be applied to assemblies running in a specific .NET Framework application domain to have any real use. The next section explains how to apply a CAS policy to a Web application.
Creating and Assigning Trust Levels in a Web Application's web.config File
Although CAS policies are defined in the policy file, they must be applied to an application domain to assign the effective permissions on executing assemblies. This is done by creating and assigning trust levels inside a Web application's
web.config file. Policy files are first registered in the
web.config file and assigned a name. This is done by using the trustLevel element nested in the
<system.web><securityPolicy> section of the
web.config file. By default, SharePoint registers two CAS policy files in all new Web applications: minimal and medium.
<configuration> <system.web> <securityPolicy> <trustLevel name="WSS_Medium" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_mediumtrust.config" /> <trustLevel name="WSS_Minimal" policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_minimaltrust.config" /> </securityPolicy> </system.web> </configuration>
These CAS policy files are found in the SharePoint
[..]\12\CONFIG folder. After registering the policy files, one policy must be applied to the ASP.NET application domain. You do this by specifying the trust level by using the trust element nested in the
<system.web> section of the
<configuration> <system.web> <trust level="WSS_Minimal" originUrl="" /> </system.web> </configuration>
This tells the .NET Framework which current policy file to use for the current application domain that the Internet Information Services (IIS) application pool is running in, and thus the trust level for the application pool, to apply to get the effective permissions on assemblies that are called.
For more information about CAS trust levels and policy files, see ASP.NET Trust Levels and Policy Files.
With an understanding of how CAS works and of the components of CAS in the .NET Framework, SharePoint administrators and developers must next understand why CAS is important to them. Many people new to SharePoint and those unfamiliar with CAS usually see CAS as a burden and cumbersome to manage. However, CAS in SharePoint is a very powerful tool when used correctly because it can provide a very robust level of security, control, and protection over your SharePoint environment.
Why CAS Is Important to SharePoint Administrators
So why is CAS so important to SharePoint administrators? When hosted on-premise, SharePoint is a portal solution that contains data, files, and content that is used by many different people, groups, and departments throughout an organization. When SharePoint is hosted off-premise, all the same things apply as in an on-premise solution, but with the addition that it is likely that multiple organizations will have their content stored in the same infrastructure. In either case, SharePoint administrators will be managing servers in a farm and are responsible for the health and availability of the farm. Although content does not cause an issue with the stability of a SharePoint farm (aside from the proper capacity and scaling considerations), custom and third-party code can cause issues. In fact, custom code is by far the root cause for the majority of the SharePoint support calls when dealing with performance, server health, and stability.
Organizations have different models for how the development of custom code is carried out for use in a SharePoint environment. Some organizations have a central development shop that does all custom development for the entire organization and handles the acquisition of third-party components. Some groups or divisions within an organization have their own development staff. Development can also be outsourced to external consultants and managed through a central group or by each group individually. Regardless, administrators can be given custom assemblies from many different sources and be requested to deploy these custom assemblies to the SharePoint servers. This poses a challenge because administrators are being asked to deploy custom code on which they may or may not have had the opportunity or ability to perform a thorough code review. Administrators must be able to exert some control on custom assemblies that they deploy to the server without having an intimate understanding of what the code does. This situation is exactly the one in which SharePoint administrators can use CAS to advantage.
When SharePoint administrators use CAS policies effectively, they can control what rights custom code and third-party assemblies have, without performing detailed code reviews. Code reviews are the responsibility of the development and quality assurance staff, not the administrators who are responsible for managing the server health and overall health of the SharePoint farm. Therefore, administrators can configure the CAS policies so that custom code can do only certain things, which the administrators have explicitly granted, and nothing else.
CAS also enables administrators to manage the health of the SharePoint farm and to enforce certain organization guidelines. For example, some organizations may not allow content to be sent to, or retrieved or received from, an external party. A developer could create a Web Part that consumes data from an RSS feed or Web service hosted within the organization's trusted network. However, a user of the Web Part could modify the Web Part in the browser to change the URL of the RSS feed or Web service to a location outside the organization's trusted network. Using CAS, specifically using WebPermission, administrators could allow custom assemblies to interact with RSS feeds or Web services for a specific DNS address.
Another added benefit to SharePoint administrators is an extra level of security. While an organization might perform a thorough code review and the custom code might have been thoroughly tested with a very high code coverage percentage, if the component is compromised in some way, it can still do things it was not designed to do. For example, consider if a custom Web Part was built to aggregate content and show sales figures from content already in the SharePoint site. This Web Part is written to use the SharePoint API only to get the data it needs. However, if the CAS policy the site is running allows the SqlClientPermission, the Web Part could potentially be compromised by a hacker and used to read data to and write data from any SQL Server database it can connect to. By using CAS, the SqlClientPermission can be removed as an allowed permission that the assembly could do.
Why CAS Is Important to SharePoint Developers
SharePoint developers need to understand CAS and why it is important for two reasons:
To understand the CAS policies, or rules, that the administrators have put in place for custom code
To understand the implications for their custom code and for the entire SharePoint farm when requesting that the trust level be changed
The previous section described why CAS is important to SharePoint administrators and how it can be effectively used to control custom code within SharePoint Web applications. Developers need to understand the reasons why, how, and what—what can be secured by SharePoint administrators using CAS. When developing custom solutions, developers should check early in the discovery and requirements stage of a project to see what CAS policy their custom code will run under and what, if any, changes can be applied to the policy for their custom code. Addressing CAS issues later can be a challenge because code may need to be rewritten to work around certain organizational rules if custom CAS policies are not allowed, as there is no way to circumvent CAS policy rules from custom code.
How SharePoint Uses CAS
SharePoint does not do anything special with respect to the .NET Framework CAS implementation. As far as the .NET Framework is concerned, SharePoint is just another Web application that will run within its own IIS application pool. All Web Parts, server controls, and user controls are subject to CAS in SharePoint. Many custom components that developers build, such as event receivers, workflows, and Feature receivers, are not subject to CAS in SharePoint, because they are global and run within the SharePoint object model. Microsoft did include two CAS policies for use in SharePoint Web applications that make the management of CAS easier. However, administrators and developers might need more granular control and might need to create their own custom CAS policies for use in SharePoint (which is supported by Microsoft).
Default CAS Trust Levels
When a new Web application is created and extended for SharePoint from Central Administration, SharePoint adds a
web.config file that includes many things such as safe control entries, HTTP modules, and HTTP handlers that SharePoint needs in order to run. It also registers two CAS policies that Microsoft has preconfigured to make managing CAS a bit easier: WSS_Minimal and WSS_Medium. These two CAS policies are listed in the
<securityPolicy /> section of
web.config. The default SharePoint
web.config is also configured to use the WSS_Minimal CAS policy, as indicated in the
<trust /> node of
web.config. In addition to these two policies, administrators can also configure the Web application's CAS policy to Full, a special reserved policy. All three policies are explained in the following sections.
In addition to these three policies (WSS_Minimal, WSS_Medium, and Full), developers and administrators can create custom policies, register them, and configure the Web applications to use the new policies.
WSS_Minimal SharePoint CAS Policy
The WSS_Minimal CAS policy is what all new SharePoint Web applications are configured to use by default. This is the most restrictive policy provided by Microsoft. It contains a named permission set called SPRestricted. This named permission set is applied to all assemblies that are deployed to the Web application's
bin folder. SPRestricted allows only the most basic permissions:
AspNetHostingPermission Sets the access permissions in the ASP.NET application. This permission's Level property specifies the hosting permission level of the ASP.NET application. Level is assigned a value from the AspNetHostingPermissionLevel enumeration. By default, all ASP.NET applications are assigned the Unrestricted permission level; however, in the WSS_Minimal CAS policy, it is assigned Minimal. This enables the code to execute, but not interact with, resources on the system. For more information about this permission, see AspNetHostingPermission Class.
SecurityPermission This permission has a Flags property that specifies what the code can do. The WSS_Minimal CAS policy sets the Flags property to SecurityPermissionFlag.Execution, which grants the code permission to run, but nothing else. For more information about this permission, see SecurityPermission Class.
WebPartPermission This permission has a Connections property that accepts a Boolean value if Web Part connections are allowed. The WSS_Minimal CAS policy sets this value to TRUE, allowing Web Part connections. For more information about this permission, see WebPartPermission Class.
Notice that the WSS_Minimal CAS policy does not permit requests to external Web services, SQL database connections, access to the file system, or retrieval of system environment variables. This is the most restricted CAS policy and provides a very secure SharePoint environment with just enough rights to facilitate a collaborative experience, locking down custom code as much as possible.
WSS_Medium SharePoint CAS Policy
The WSS_Medium CAS policy is an additional policy Microsoft included that grants more permissions that are commonly needed by custom code. It allows everything WSS_Minimal allows, and these additional permissions:
DnsPermission Enables applications access to DNS services. For more information about this permission, see DnsPermission Class.
EnvironmentPermission Controls access to the server's and user's environment variables, such as retrieving the USERNAME, COMPUTERNAME, or TEMP folder location. The WSS_Medium policy grants custom code read access to the TEMP, TMP, USERNAME, OS, and COMPUTERNAME environment variables as they are set in the Read property of this permission. For more information about this permission, see EnvironmentPermission Class.
FileIOPermission Grants access to files and folders on the server. The type of access is defined in four properties: Read, Write, Append, and PathDiscovery. PathDiscovery returns information about the path without granting access to the folder or files specified. The WSS_Medium policy grants custom code Read, Write, Append, and PathDiscovery to the Web application's
binfolder. For more information about this permission, see FileIOPermission Class.
IsolatedStorageFilePermission This permission grants custom code the permission to use the .NET Framework protected file system: isolated storage. Isolated storage allows applications to store data, but isolates this data to a specific assembly and user. This permission has two properties: UsageAllowed and UserQuota. UserQuota specifies the maximum allowable size of the user's total isolated storage quota. UsageAllowed specifies the type of containment allowed (WSS_Medium sets this to IsolatedStorageContainment.AssemblyIsolationByUse, which isolates the storage by assembly and then by user. For more information about this permission, see IsolatedStorageFilePermission Class.
PrintingPermission Controls access to printers. For more information about this permission, see PrintingPermission Class.
SharePointPermission Controls access to the SharePoint object model. WSS_Medium grants custom code the ability to call the SharePoint object model. This permission is one of the more common reasons why administrators change the trust level from WSS_Minimal to WSS_Medium, because under WSS_Minimal no custom code can make even the simplest calls to the object model, such as SPContext.Current.Web.Title. For more information about this permission, see SharePoint Permission Class.
SmtpPermission Controls access to e-mail (Simple Mail Transport Protocol [SMTP]) servers. Without this permission, custom code is not permitted to send e-mail messages. For more information about this permission, see SmtpPermission Class.
SqlClientPermission Enables custom code to connect to and query a database. For more information about this permission, see SqlClientPermission Class.
WebPermission Grants access to HTTP resources, such as RSS feeds or Web services. Without this permission, code cannot issue requests to external resources by using HTTP. This permission has two public properties: ConnectList and AccessList. These properties grant access to respective remote and local HTTP addresses. HTTP addresses can be specified by using regular expressions or a specific URL. The WSS_Medium permission level grants custom code the ability to connect to HTTP resources from the same hosting domain. For more information about this permission, see WebPermission Class.
When the WSS_Minimal permission set does not grant enough permissions for custom code to run, one easy option is to raise the trust level of the SharePoint Web application to WSS_Medium. This enables administrators to grant all custom code additional rights without losing complete control, but also avoid the tedious task of creating custom CAS policies. This article describes the process of working with CAS in Options for Managing CAS on SharePoint Web Applications, and offers some best practices in Best Practices for Managing CAS in SharePoint.
Full CAS Policy
The Full CAS Policy effectively turns CAS off. By specifying this CAS policy, the .NET Framework is configuring CAS to treat all custom code in the Web application as fully trusted code and thus, the code has unrestricted access to do anything it wants to do. Keep in mind this does not just tell CAS to fully trust all custom code your organization deploys, but also any third-party components deployed to your servers. Use extreme caution when setting the CAS policy to Full, because it is somewhat like leaving all the locks on your house unlocked or granting the Everyone built-in group on your server's root drive access to Full Control.
What Code Is Subject to CAS in SharePoint?
All code in a SharePoint application is subject to CAS without exception. The two built-in policies, WSS_Minimal and WSS_Medium, are differentiated only by what permissions are included in the SPRestricted named permission set. This named permission set is then applied to all custom code that is deployed to the Web application's
bin folder. These policies also grant Microsoft-signed assemblies (such as those that run SharePoint) full trust. By default, assemblies deployed to the server's global assembly cache are fully trusted.
Working with CAS in SharePoint
Up to this point, this article has provided an overview of what CAS is, the components involved with it, and how SharePoint uses it. Now, let's look at how developers and administrators can identify CAS issues in SharePoint, how to manage CAS in SharePoint deployments, and review some best practices for working with CAS.
Identifying and Isolating CAS Issues in Custom Components
Exceptions in a production environment are never a welcome sight. Developers creating custom components can easily be confused by security exceptions, because to the untrained eye, they can appear to be logic issues instead of security problems. Thankfully, identifying and isolating CAS issues in custom components is easy.
Consider a Web Part that calls a Web service in a domain that is different from where the current site is located. When the Web Part is added to a page (one that is in a site collection within a Web application that is configured to use the WSS_Minimal trust level), SharePoint will notify the user of an unknown exception on a friendly error page, as shown in Figure 1.
Figure 1. User-friendly SharePoint error page
Unfortunately, this error is not helpful to administrators and developers because it does not clearly explain the problem. SharePoint uses custom error pages and does not always report the exact exception to the user for security reasons. To get a detailed error, turn off custom errors and turn on the call stack. Do this by modifying the
web.config file of the Web application to change the <customErrors> mode attribute from On to Off (this attribute is case-sensitive) and the <SafeMode> CallStack attribute from false to true. This should provide a much richer error by using the ASP.NET yellow exception page after the page is refreshed, as shown in Figure 2.
Figure 2. ASP.NET error page with exception details
Notice that the exception details state that the exception that was thrown was a SecurityException. This indicates there is a CAS issue causing this exception. Further investigation of the exception shows the SecurityException is being raised because the Web Part requested the WebPermission but it failed. This is because the Web application is configured to use the WSS_Minimal trust level, which does not grant the WebPermission.
There is an easy way to verify if this is in fact a CAS issue: increase the trust level from WSS_Minimal to Full. This effectively grants all permission requests by all assemblies. Do this by changing the web.config <trust> element's level attribute to Full (this attribute is case sensitive). Recycle the application pool and refresh the page; the Web Part should run without issues, as shown in Figure 3.
Figure 3. Functioning Web Part
Leaving the trust level set to Full is not acceptable, but this was a very easy and quick way to determine whether this Web Part's problem was related to CAS and not a logic problem. This exercise has shown how to identify CAS issues; it demonstrated the trial-and-error approach to identifying CAS issues. Another option is to determine what permissions are needed from the Microsoft Office SharePoint Server SDK. For example, consider if a project required a custom code-behind file for an Office SharePoint Server 2007 page layout file. Good practice says that these code-behind files should inherit the Microsoft.SharePoint.Publishing.PublishingLayoutPage class. Looking at the PublishingLayoutPage object in the SDK, notice the syntax section includes an attribute that specifies the level of trust this class requires, as shown in Figure 4.
Figure 4. PublishingLayoutPage in the SharePoint Server SDK
From the SDK documentation, the PublishingLayoutPage class requires full trust. This means that the assembly containing this class must be deployed to the global assembly cache or must be fully trusted.
Now that the CAS issue is identified, the next step is to determine how to resolve it. The next section addresses the options available to developers.
Options for Managing CAS on SharePoint Web Applications
Instead of the option of the developer or vendor modifying the assembly that is unable to execute properly because of the set CAS policy, the developer or administrator has a few other options with which to address CAS issues. Some of these options are big changes that affect all custom assemblies in a Web application; others are more granular that affect a specific custom assembly. The broader changes are easier and faster to implement, but they are less secure. The most secure option, creating custom CAS policies that target specific assemblies, is much more complicated and tedious but it is also the most secure option. The following is an explanation of the available options and their implications.
Deploy Custom Assemblies to the Global Assembly Cache
When an assembly throws a SecurityException when it executes, it is an indicator that the current CAS policy does not grant the assembly a permission it requires to function. One option is to grant this assembly full trust. That effectively removes all CAS checks and lets the assembly do anything it needs to do, with no security checks. The easiest way to do this is to deploy the custom assembly to the global assembly cache of the server. All assemblies in the global assembly cache are fully trusted. The advantage to this approach is that it is quick to implement. But there are a few disadvantages, as follows:
Now that the assembly is in the global assembly cache, it is fully trusted and, therefore, administrators lose the ability to control what this assembly is allowed to do or what it can access.
Extending the previous point, if the assembly is somehow compromised, the hacker could use the assembly to do anything on the server, including making database calls, sending e-mail messages, or connecting to external HTTP resources.
When an assembly is in the
binfolder of a Web application, it can be used only by the SharePoint site collections available in that Web application. But when deployed to the global assembly cache, it can be accessed by any application on the server. This means any SharePoint Web application could call the assembly and any other application installed on the server.
Increasing the trust level of the Web application might grant the necessary permission to the assembly, but it also grants other permissions that the assembly may not need and thus, increases the surface area of attack. For example, if a custom Web Part needs to establish a connection to a database to issue queries, deploying it to the global assembly cache grants it those permissions. However, it also allows the assembly to send e-mail messages and connect to external HTTP resources because of the other permissions allowed when the assembly is fully trusted in the global assembly cache.
Use caution when deploying custom assemblies to the global assembly cache. They should undergo a thorough code review and endure scrutiny by the development and administrative staff because of the level of trust they will run within.
Remember that this method of granting the assembly full trust only affects the specific assembly and no others.
Increase the Web Application's Trust Level
Another option to address CAS issues is to increase the trust level of the entire SharePoint Web application. In this case, the assembly remains deployed to the Web application's
bin folder so it is accessible only to the current SharePoint Web application. This involves changing the trust level of the entire Web application. As previously discussed, there are three built-in CAS policy options available. The most secure and restrictive is WSS_Minimal, which all SharePoint Web application start out as, then WSS_Medium, and finally Full.
Changing the trust level is very easy. Simply find the <trust /> element in the Web application's
web.config file and set the level attribute to the desired CAS policy (WSS_Minimal, WSS_Medium, or Full). After changing the trust level of the Web application, the IIS application pool must be reset, because an application pool cannot have two different CAS policies loaded. If the application pool is not reset, ASP.NET throws an exception stating two CAS policies cannot be loaded in the same application pool at the same time.
The advantage to this approach is that it is quick to implement. However, there are disadvantages, as follows:
Changing the trust level for an entire Web application affects not only the assembly that is throwing the SecurityException, but it also increases the trust level for all custom code in the Web application. This includes all currently deployed assemblies and those deployed to the Web application in the future.
As with deploying the assembly to the global assembly cache, increasing the trust level of the Web application might grant the necessary permission to the assembly, but it also grants other permissions that the assembly may not need and thus, increases the surface area of attack. For example, if a custom Web Part needs to establish a connection to a database to issue queries, increasing the trust level to WSS_Medium would grant it those permissions. However, it would also allow the assembly to send e-mail messages and connect to external HTTP resources because of the other permissions included in WSS_Medium.
Increasing the trust level to Full can be a very dangerous thing to do because it affects all custom code in the Web application. It is strongly recommended that you do not increase the trust level of a Web application to Full. Instead, consider deploying the single assembly in question to the global assembly cache, because it will grant that assembly full trust, but it will not affect any other custom code deployed to the Web application.
Create Custom CAS Policies
The last option this article describes for addressing CAS issues is to create a custom CAS policy that applies a new named permission set to the specific assembly or to a group of assembles. This is by far the most secure method of granting an assembly additional permissions. The steps for granting an assembly special permissions via creating a CAS policy are as follows (this process is demonstrated in the Real-World SharePoint and CAS Walkthrough section later in the article):
Create a new named permission set in a new CAS policy file and add the required permissions that the assembly needs.
Create a new code group in the CAS policy file that applies the new named permission set to the specific assembly. A good way to do this is by having the code group match the assembly by the signed assembly's public key BLOB signature.
Add a new entry to the web.config <securityPolicy /> section, giving the new trust level a unique name, and point it to the new CAS policy file.
Update the web.config <trust /> element to change the trust level of the Web application to use the new CAS policy.
Recycle the application pool that hosts the Web application so that the application pool will unload all CAS policies and load only the new specified policy.
There are two reasons why this option is the most secure method. First, the new CAS policy targets only the specific assembly in question (or multiple assemblies if they are all signed with the same key and so have the same public key BLOB signature). Second, the assembly is granted only the minimal permissions required and no more. This follows the principle of least privilege, which states someone or something is granted access to what it needs and nothing else. Therefore, if the assembly needed to connect to a database, it could be granted the SqlClientPermission, but not the SmtpPermission or WebPermission, which it would not need. This is much more secure than simply increasing the trust level of the entire Web application to WSS_Medium.
As with the other options, this approach has one major disadvantage: creating and testing custom CAS policies is a tedious and complex process. Many .NET Framework administrators and developers avoid this option because it can be so time-consuming, but it is by far the most secure option available.
One thing Microsoft did to make this process easier in Windows SharePoint Services 3.0 was to include a custom CAS policy implementation mechanism in the deployment process of custom code. A SharePoint best practice is to deploy all custom code and files to SharePoint servers by using SharePoint solution packages (.wsp files). All solution packages include a
manifest.xml file in the root of the package, which serves as the descriptor and set of instructors for the package. SharePoint uses this
manifest.xml file to determine where to deploy files on the server, what changes to apply to the
web.config (such as <SafeControl /> entries), and where to deploy assemblies. Microsoft added another section to the
manifest.xml file, the <CodeAccessSecurity /> element, which enables developers to define a custom named permission set for an assembly deployed in the solution package. When the solution package is deployed, SharePoint makes a copy of the CAS policy file that is currently in use by the Web application, adds the new named permission set and associated code group, makes the necessary changes to the
web.config file to register the new CAS policy and change the trust level to use the new CAS policy, and finally, recycles the application pool. What is good about this approach is that administrators can then look at the
manifest.xml file before deploying the solution package to see what permissions this assembly will be granted before deploying the solution package.
When selecting this option, ensure the SharePoint Web application CAS policy starts configured to use the WSS_Minimal trust level, because it is the most secure level available. It will be used as the template with adding named permission sets.
Best Practices for Managing CAS in SharePoint
With all the options presented in this article for addressing and managing CAS, it might not be obvious which option is best or what the best practices are for managing CAS in SharePoint. Remember, there is no one single right answer to managing CAS. The option an organization selects depends on the security guidelines within the organization, the resources—including the people, time, and money that are involved in implementing the solution—and the desired level of complexity.
Before looking at the options, consider the investment you want to make with your CAS policy management strategy. This is very similar to password complexity requirements. Different applications have different password complexity requirements. The more secure systems require passwords that are no shorter than eight characters long, include a combination of uppercase and lowercase letters, include numbers and special characters, do not contain natural words found in the dictionary or a variation of a previously used password, and are changed every 30 days. Other systems might relax some requirements, such as allowing natural words and not checking new passwords against previously used passwords. Even more relaxed systems might require only that the password be at least eight characters long with no complexity requirements. The point here is that the more stringent the requirements are, the larger the management burden that is imposed upon the users (in the case of passwords) or system managers (in the case of CAS policy implementers). Thus, each organization is different.
Following the principle of least privilege, the following best practice recommendation starts with the most secure and granular approach, which is also the most complex and time-consuming to implement, and then moves to the options that are easier to implement, but less secure.
The most secure approach to managing CAS policies in SharePoint is to require developers and third-party consultants or vendors to deploy their custom code by using solution packages (.wsp files) that include a custom CAS policy defined within the
manifest.xml file. This makes it easy for administrators to examine what permissions the custom code requires, and grants only the minimally required permissions needed by the custom code.
The disadvantage of this approach is that creating custom CAS policies, even in solution packages, is tedious and can be challenging to the developers.
The next best option is to increase the trust level of the Web application from WSS_Minimal to WSS_Medium. Although WSS_Minimal is very secure, it does not grant some commonly required permissions, such as access to the SharePoint object model (SharePointPermission) or access to databases (SqlClientPermission). The WSS_Medium trust level does include these and other permissions, described earlier in this article. This approach is very easy and quick to implement, and usually resolves the most common CAS policy issues.
The disadvantages of this approach are:
All custom code is affected and will be granted this new CAS policy.
The custom code is likely granted more permissions than it requires.
The final realistic option is to simply deploy the custom assembly to the server's global assembly cache. It will grant the assembly full trust and thus, the assembly will have all the permissions it needs—and many more it does not require. This approach is easy and quick to implement. When this approach is selected, the assemblies deployed to the global assembly cache should undergo intense scrutiny in code, security, and threat reviews because this assembly will have unrestricted access to the server and can be called by any application deployed to the server.
Many organizations prefer this option because it is the easiest to develop for and maintain. It does not require the creation of custom CAS policies for each component, which can be a tedious process for many developers.
The disadvantage of this approach is that it grants the assembly more permissions than it might require, and it is fully accessible to all applications on the server.
In this approach, the Web application's trust level is increased to Full. This grants all assemblies and custom code in the Web application full trust, both those that are currently deployed and those deployed in the future. Although this is technically an option of last resort, this approach should never be considered. It is by far the most sweeping approach and dramatically increases the surface area of attack. Instead of selecting this option, strongly consider the previous option of deploying select assemblies to the global assembly cache because that option does not have such dramatic and sweeping implications.
When requested by custom assembly developers, third-party consultants, or vendors, this approach should raise a warning to SharePoint developers and administrators.
Real-World SharePoint and CAS Walkthrough
The previous section, Identifying and Isolating CAS Issues in Custom Components, demonstrated how to find and verify a CAS issue in custom code. After the issue is identified, the developer has a few options. As described earlier, the easy approach is to change the deployment to put the assembly in the server's global assembly cache or to increase the trust level from WSS_Minimal to WSS_Medium, because the Web Part in the sample was missing only the WebPermission. Either option works well, but maybe an organization requires a higher level of security. The more secure option is to create a custom CAS policy and deploy it as part of the solution package and thus, it is defined in the solution package's
The first step is to ensure the Web application's
web.config trust level is reset to WSS_Minimal, in case it was changed to Full to help isolate the issue as a CAS issue. Next, the
manifest.xml file must be modified to include a CAS policy.
manifest.xml of a solution package does not allow the solution package to be upgraded, because the same solution cannot change a CAS policy between deployments. Therefore, if creating a custom CAS policy is the desired option, the solution package and custom component must be retracted after identifying a CAS issue.
Following is the general process for creating a custom CAS policy for an assembly:
Add a CAS policy to the
Assign the new policy a specific assembly or multiple assemblies.
Create a named permission set that includes everything that the SPRestricted named permission set includes in the WSS_Minimal trust level. This helps ensure that the custom code has at least the minimal permissions granted by the SPRestricted permission set.
Add the additional permissions required by the custom code.
Step 1. Add a CAS Policy to the SharePoint Solution Package
In this first step, add the CAS policy to the
manifest.xml file. The following markup shows how the
manifest.xml file looks for this sample. The file deploys an assembly to the Web application's
bin folder, adds a <SafeControl> entry to the
web.config file, and deploys a Feature. Upon activation, the Feature provisions the Web Part definition file to the site collection's Web Part Gallery.
<?xml version="1.0" encoding="utf-8" ?> <Solution xmlns="https://schemas.microsoft.com/sharepoint/" SolutionId="AE28EF44-2A0D-460E-A891-16E0AEB6829F" DeploymentServerType="WebFrontEnd" ResetWebServer="FALSE"> <Assemblies> <Assembly DeploymentTarget="WebApplication" Location="SampleWebPartWithCas.dll"> <SafeControls> <SafeControl Namespace="MSDN.SharePoint.Samples" Safe="True" TypeName="*" /> </SafeControls> </Assembly> </Assemblies> <FeatureManifests> <FeatureManifest Location="SampleWebPartWithCas\feature.xml" /> </FeatureManifests> </Solution>
Add the custom CAS policy after the closing <FeatureManifests> element, before the closing <Solution> element.
<CodeAccessSecurity> <PolicyItem> <Assemblies></Assemblies> <PermissionSet></PermissionSet> </PolicyItem> </CodeAccessSecurity>
Notice the two child elements in the <PolicyItem> element. The <Assemblies> element is where the assembly is associated with the new named permission set; the <PermissionSet> element is where the named permission set is defined.
Step 2. Associate the Assembly with the New CAS Policy
Next, add the assembly to the CAS policy. You can add the assembly to the CAS policy in a few different ways. One way is to associate the policy with the assembly's public key BLOB. This is a public signature that the assembly has after it is signed with a key file. The advantage to this method is that multiple assemblies can be signed with the same key file and so have the same CAS policy applied to all of them.
To get the public key BLOB, open a Visual Studio 2008 Command Prompt window, and enter the following (the arguments are case-sensitive).
sn.exe -Tp [path to DLL]
This returns something similar to what is shown in Figure 5.
Figure 5. Obtaining the public key BLOB
Copy the public key BLOB value (the long cryptic string) returned by the strong name utility, and add the attribute PublicKeyBlob to a new <Assembly> child element in the CAS policy that you previously added to the
Be sure to remove line breaks from the public key BLOB when copying it from the Command Prompt window.
<CodeAccessSecurity> <PolicyItem> <Assemblies> <Assembly PublicKeyBlob="00240000048000009400000006020000002400005253413100040 00001000100d333cc35f79de0bf82d13f9423a206a947ef30779f32c60b2893d8b79 9a883f3677a0710d2daa8193361d2f0cb7b78db1cbdaabbe6d724429423ce57795b1 ea860dd05cbbf9b762e25b9208237dc606949edb815fa921b3b765630b341bf2ee5e 3e2061aa87abf17f65793a22e9e8b16894c23978bd51ecdabf4e6be9b74e2be" /> </Assemblies> <PermissionSet> </PermissionSet> </PolicyItem> </CodeAccessSecurity>
Step 3. Mimic the SPRestricted Named Permission Set
Next, you create a new named permission set that mimics the SPRestricted named permission set.
Modify the <PermissionSet> element to specify that this is a named permission set by using the class attribute (see the following code example).
Set the name and version of the policy (see the following code example).
Add the three core permissions included in the SPRestricted named permission set in the WSS_Minimal trust level (see the following code example).
<CodeAccessSecurity> <PolicyItem> <Assemblies> <Assembly PublicKeyBlob="00240000048000009400000006020000002400005253413100040 00001000100d333cc35f79de0bf82d13f9423a206a947ef30779f32c60b2893d8b79 9a883f3677a0710d2daa8193361d2f0cb7b78db1cbdaabbe6d724429423ce57795b1 ea860dd05cbbf9b762e25b9208237dc606949edb815fa921b3b765630b341bf2ee5e 3e2061aa87abf17f65793a22e9e8b16894c23978bd51ecdabf4e6be9b74e2be" /> </Assemblies> <PermissionSet class="NamedPermissionSet" Name="MsdnCasSample" version="1"> <IPermission class="System.Web.AspNetHostingPermission, System, Version=220.127.116.11, Culture=neutral, PublicKeyToken=b77a5c561934e089" Level="Minimal" version="1" /> <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=18.104.22.168, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="Execution" version="1" /> <IPermission class="Microsoft.SharePoint.Security.WebPartPermission, Microsoft.SharePoint.Security, Version=22.214.171.124, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Connections="True" version="1" /> </PermissionSet> </PolicyItem> </CodeAccessSecurity>
At this point the new named permission set is simply duplicating the SPRestricted named permission set in the
WSS_Minimal trust level.
Step 4. Add Required Permissions
The last step is to add the permissions that the custom assembly requires. In the case of this example, the assembly needs the WebPermission, as indicated by the error that was reported by the ASP.NET error page. Add the WebPermission after the WebPartPermissionIPermission element.
<CodeAccessSecurity> <PolicyItem> <Assemblies> <Assembly PublicKeyBlob="00240000048000009400000006020000002400005253413100040000 01000100d333cc35f79de0bf82d13f9423a206a947ef30779f32c60b2893d8b799a883f 3677a0710d2daa8193361d2f0cb7b78db1cbdaabbe6d724429423ce57795b1ea860dd05 cbbf9b762e25b9208237dc606949edb815fa921b3b765630b341bf2ee5e3e2061aa87ab f17f65793a22e9e8b16894c23978bd51ecdabf4e6be9b74e2be" /> </Assemblies> <PermissionSet class="NamedPermissionSet" Name="MsdnCasSample" version="1"> <IPermission class="System.Web.AspNetHostingPermission, System, Version=126.96.36.199, Culture=neutral, PublicKeyToken=b77a5c561934e089" Level="Minimal" version="1" /> <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=188.8.131.52, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="Execution" version="1" /> <IPermission class="Microsoft.SharePoint.Security.WebPartPermission, Microsoft.SharePoint.Security, Version=184.108.40.206, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Connections="True" version="1" /> <IPermission class="System.Net.WebPermission, System, Version=220.127.116.11, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="True" version="1" /> </PermissionSet> </PolicyItem> </CodeAccessSecurity>
Step 5. Verify and Test
At this point, the new named permission set is finished. Upon deploying the assembly, SharePoint will do the following extra steps from the typical deployment that did not include a custom CAS policy.
Create a copy of the currently selected trust level's CAS policy file (here, WSS_Minimal).
Add the new named permission set defined in the
manifest.xmlto the new CAS policy file.
Add a new code group to the CAS policy file that associates the deployed assembly with the new named permission set.
Add an entry to the
web.configfile registering a new trust level (WSS_Custom) that points to the new CAS policy file.
Change the trust level of the Web application to the new registered trust level.
Recycle the application pool.
Now, rebuild the solution package and add the solution to the SharePoint solution store. Select the added solution in the Solution Store and view its property page. Notice it indicates that it has a custom CAS policy included in the solution package, as shown in Figure 6.
Figure 6. Custom CAS policy detected in solutions
Now, deploy the solution to the desired Web application. Look in the
[..]\12\CONFIG folder and notice a newly created CAS policy file (Figure 7).
Figure 7. New CAS policy file
Also, look at the
web.config file to see how the new CAS policy was registered as a new trust level and that the Web application is configured to use this new trust level.
SharePoint administrators and developers need to understand CAS when deploying custom components and managing SharePoint farms. Because of the collaborative characteristics of SharePoint, and the fact that most SharePoint farms host information and custom components for various groups within an organization (or multiple organizations), administrators need a way to sandbox custom code and establish rules around what custom components are allowed and denied permissions to do. This is where CAS fits in. CAS is a powerful tool when used effectively. This article explains what CAS is and the various components of CAS. It then explains why CAS is important to SharePoint administrators and developers, and the options that are available to manage CAS in SharePoint. Finally, the article presents some best practices for managing CAS in SharePoint and a walkthrough of a real-world CAS issue.
For more information, see the following resources:
Chapter 9—Using Code Access Security with ASP.NET (see "Improving Web Application Security: Threats and Countermeasures")