Common Security Pitfalls for Web Part Developers

I've wanted to write this post for a long time, the trigger to actually write it was my interview by Chris Kunicki for his Office Zealot podcast last week. During this podcast (which was really fun to do, thanks for having me Chris!) we discussed briefly some security problems web part developers could face. Podcasts are great but they are not suited to communicate code, so here's the accompanying post! When you're developing web parts, security could be one of the biggest problems to deal with. First of all you may face some problems to get your web part deployed and secondly you may have some Code Access Security problems. Let's take a look at both of them!

When you develop web parts using the traditional way (using the Visual Studio.NET Templates), you have to create your web part class and a DWP file before you can deploy your web part. Additionally you must alter the Web.Config of your SharePoint site, and add your web part in the SafeControls section. Once everything is in place, and you want to drag and drop your brand new web part on a page, you may get the message "A Web Part or Web Form Control on this Web Part Page cannot be displayed or imported because it is not registered on this site as safe". If you get this message, either something is wrong in your DWP or something is wrong in your Web.Config. Common mistakes are:

  • Wrong AssemblyName in DWP: if you have a strong named assembly (using a SNK file) your assembly element should contain the complete name (including the version, culture and public key token. An easy way to retrieve that name is the using the Reflector tool.
  • Wrong Assembly in Web.Config: same remark, the Assembly attribute should contain the complete name of your assembly.
  • Wrong TypeName DWP: the type name of your class is prefixed with the namespace. By default your namespace is the same as your Visual Studio project name.

Example of a DWP file:

<?xml version="1.0" encoding="utf-8"?> <WebPart xmlns="http://schemas.microsoft.com/WebPart/v2" > <Title>SmartPart 1.0.0.0</Title> <Description>The SmartPart User Control Webpart</Description> <Assembly>SmartPart, Version=1.0.0.0, Culture=neutral, 
PublicKeyToken=dd064a5b12b5277a</Assembly> <TypeName>SmartPart.UserControlWebpart</TypeName> </WebPart>

Example of SafeControl node:

<SafeControl 
Assembly="SmartPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=dd064a5b12b5277a"
Namespace="SmartPart" TypeName="*" Safe="True" />

Using the SmartPart to create web parts solves these issues. You don't need to create a DWP file and you don't need to change your Web.Config! Once you have deployed your web part, you may have some problems regarding Code Access Security. Out-of-the-box SharePoint is running with a trust level that contains very limited privileges. For example: you can not access the object model or a web service; this will give you a security exception. If you take a look at the Web.Config file, you will see that SharePoint is running using the WSS_Minimal trust level (<trust level="WSS_Minimal" originUrl="" />). Where is this WSS_Minimal defined? Well if you look in the securityPolicy section of the Web.Config you will find:

<securityPolicy> <trustLevel name="WSS_Medium" 
policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\config\wss_mediumtrust.config" /> <trustLevel name="WSS_Minimal"
policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\config\wss_minimaltrust.config" /> </securityPolicy>

So WSS_Minimal is pointing to a trust level which is defined in the wss_minimaltrust.config on your hard disk. As you can see, another default trust level is WSS_Medium which will add permissions to access the object model. If you write a web part that uses the SharePoint object model, make sure you set the trust level to WSS_Medium. What about web parts that contain really dangerous stuff like accessing a web service or, even worse, writing a file on the hard disk? Well you need to make sure that you web part is running with elevated privileges. So far the theory, how can we do this? There are several possibilities:

  • Set the trust level in the Web.Config to full. This will solve all your CAS problems because everything will be running with full trust. Of course this is not a good solution, so use it only on your dev machine for testing reasons!
  • Deploy your web part assembly to the GAC instead of to the BIN folder. Assemblies deployed to the GAC will run with full trust, so it solves all CAS issues for the assembly in the GAC. Is this a good solution? In my opinion this is abusing the GAC to gain full trust permissions. I know some people would argue differently, but my advice: do not abuse the GAC for this. Especially during your development cycle, assemblies deployed to the GAC are cached so you will need an IISReset when you deploy a new version.
  • Create a custom policy file that will grant full trust to your own assembly. This is my favorite solution; it's the most difficult to implement, but it's very secure and you only have to do the work once.

In the custom policy file, you can grant for example full trust permissions only to your code. But what is your code, how do you identify your code? Well (once again in my opinion) the nicest way is to grant full trust to code that is signed with a specific public key. It's very secure and reusable, as long as you keep using the same public/private key pair (SNK) to sign your code, all your code will be running with full trust. If you want to use this technique, follow these steps:

  • Create your web part, and give your code a strong name by using a public/private key pair (SNK).
  • Create a customized policy file. The easiest thing to do is to start from the default policy files, for example the wss_mediumtrust.config file.
  • Copy that file and name the new file wss_customtrust.config for example. In this policy file you will need to add the following section, right after the FirstMatchCodeGroup:
<CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust"> <IMembershipCondition version="1" class="StrongNameMembershipCondition" 
PublicKeyBlob="your public key blob"> </IMembershipCondition> </CodeGroup>
  • By adding this section to the policy file you will assign full trust permissions to all the code that is signed with that specific public key blob.
  • How do you retrieve the public key blob? The easiest way to do this is to use following little trick:
    • Start the Microsoft.NET Framework 1.1 Configuration (from the Administrative Tools)
    • Open Runtime Security Policy/Enterprise/Code Groups/All Code (actually what you open doesn't matter because we're not going to make any changes in this tool).
    • Right click on the All Code node and choose "New..."
    • Choose "Dummy" as the name (don't worry we are not going to save this!)
    • As the condition type choose Strong Name.
    • Click the Import button and point to your web part dll.
    • The public key blob will appear in the text box so you can easily copy and paste it in the IMembershipCondition node.
    • Cancel everything in the Microsoft.NET Framework 1.1 Configuration tool. (Do not save any changes!)
  • Once you have saved the wss_customtrust.config in the same folder as the default policy files, you need to alter the Web.Config file so your new policy file will be used. So change the trust node to
<trust level="WSS_Custom" originUrl="" />

In the securityPolicy node, add following node:

<trustLevel name="WSS_Custom" 
policyFile="C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\config\wss_customtrust.config" />

You're done. When you test your hard work, you may end up with the "Assembly <assemblyName> security permission grant set is incompatible" exception. Don't worry, you'll need an IISReset. To give you all a head start I've uploaded my own prepped wss_customtrust.config. It's a modified version of the wss_mediumtrust.config that already contains the UnionCodeGroup to give code singed with a specific public key blob full trust. The only thing you need to replace is CHANGE_THIS, put in your own public key blob over here. This may look like an awful lot of work, my advice do it right the first time and you won't have any CAS issues anymore.

Although using the SmartPart to create web parts has some advantages, it doesn’t solve your CAS problems. Make sure you’ve assigned a strong name to your Web Application project that contains your user control, and use that strong name in a custom policy file as described above.

If you want to learn more about CAS, I would recommend visiting Maxim Karpov’s blog. He has written a couple of must-read articles and he has helped me with my own CAS problems some times. :-)

11 Comments

  • Jan,



    Why base your custom trust configuration off of the wss_medium and not wss_minimal?

  • Nice work, Jan. This type of overview of web parts and CAS was needed in the SharePoint community, and you've done a nice job of summarizing a lot of the key points. I had contemplated blogging on CAS and creating custom security policies myself, but I think I'll just link to your post instead!

  • James, I use WSS_Medium for the code that is not signed. Of course if you sign all your code, starting with WSS_Minimal will work as well.

  • Great article, Jan. This is a problem not easily diagnosed. Your article gets right to the point in a clear and concise manner. I downloaded a menu web part that I wanted to modify to configure off an XML file rather than hardcode it (as the author did). I could see in his code lines that were commented out because he could not figure out how to read off the local drive. His commented code included attempts to read the file using an absolute path and using a URL. I'm sure he ran into the same security issues that I did when I started modifying the code. After a day and a half of changing user permissions, machine security, implementing various ways to read a file, debugging, googling, I was ready to throw in the towel and hard code my XML when I ran across your article. It worked like a charm. Thanks!

  • Thanks man...This was the issues which was creating the big problem for me since long time.

    Thanks a lot..


    Pushawart

  • Jan,

    Any idea if there are any changes with this process in v3/2007. After following these steps, and changing the 60 to 12, I am still having issues.

    Thanks for the great post!

    Dan

  • Well, to clarify, you mention that a copy of WSS_Minimal would be fine for signed assemblies. In my experience it was not for OM access. I made a copy of WSS_Medium and it seemed to work. All I wanted was OM access, which is defined as a permission in that file. I guess I could have added that permission to my custom WSS_Minimal. But the process does work.

    Thanks Jan!

  • This article (and everything else on this blog) is brilliant - no where else on the web have I seen demonstrations of how to make things work displayed so clearly and simply.
    Thanks for saving me a lot of hassle.

  • Does any extra security features need to be added when deploying a webpart that consumes a web service ??
    ankush.bhatia@lntinfotech.com

  • Erectile pharmacy online:
    Generics Supplier. [url=http://www.pharmacy-style.com/]Generics Supplier[/url]. erectile problems. [url=http://www.pharmacy-style.com/erectile-dysfunction.htm]erectile problems[/url]. buy viagra. [url=http://www.pharmacy-style.com/viagra.htm]buy viagra[/url]. buy cialis. [url=http://www.pharmacy-style.com/cialis.htm]buy cialis[/url]. buy levitra. [url=http://www.pharmacy-style.com/levitra.htm]buy levitra[/url]. soft viagra. [url=http://www.pharmacy-style.com/viagra-soft.htm]soft viagra[/url]. soft cialis. [url=http://www.pharmacy-style.com/cialis-soft.htm]soft cialis[/url].

  • This article allowed me to stay sane for at least one more day. Thanks so much. The world of CAS and Web Policies is a dark, dark place to be right now but this was my torch!!

Comments have been disabled for this content.