Beware KB979917

If you are using claims based authentication on SharePoint 2010 you will eventually see the following error from the Health Analyzer.

Title Web Applications using Claims authentication require an update.  
Severity 1 – Error  
Category Security  
Explanation Web Applications using Claims authentication are at risk for a potential security vulnerability, which may allow users elevation of privileges. 
Remedy A security update is required on each server in the farm. For more information about this rule, see "http://go.microsoft.com/fwlink/?LinkID=184705".

The security update is KB979917 – QFE for Sharepoint issues – Perf Counter fix & User Impersonation and it introduces a pretty major change to the behavior of the affected SharePoint Web Applications that can break your code.

You can read about the ‘fixes’ in this update here: http://support.microsoft.com/kb/979917.

The parts of interest here are:

Issue 1

You deploy some partially trusted Web parts on the SharePoint site. These Web parts have more permissions than they should have. This issue may create a security risk on the SharePoint site. For example, these Web parts may generate database requests or HTTP requests unexpectedly. This behavior creates a security risk.

Note Partially trusted Web parts are Web parts that are deployed to the Bin directory of a Web application.

And:

Issue 1

This issue occurs because of an error in the ASP.NET 2.0 authentication component. The error causes the partially trusted Web parts to impersonate the application pool account. Therefore, the Web parts have full permission to access the SharePoint site.

And:

Issue 1

This hotfix makes a new application setting available in ASP.NET 2.0. The new application setting is aspnet:AllowAnonymousImpersonation. You can enable this setting by adding the following section to the Web.config file:

<appSettings>

<add key="aspnet:AllowAnonymousImpersonation" value="true" />

</appSettings>

To enable this setting, you must have IIS 7 or IIS 7.5 running in Integrated mode. When this setting is enabled, the application runs under the security context of the IUSR identity.

This hotfix updates the .NET 2.0 framework’s System.Web assembly and makes a major change when aspnet:AllowAnonymousImpersonation is set to true in web.config. Instead of code running under the application pool account as is traditional, code now runs under NT Authority\IUSR – anonymous. If you have any code that depends on an authenticated identity or the specific app pool identity – SQL connections that use integrated security, for example, the code will break with Access Denied errors.

If you are doing any integration of legacy code based on ASP.NET 2.0, there is a good chance this security fix will break your code. The good news is you can turn it off by setting aspnet:AllowAnonymousImpersonation to false in web.config. The bad news is that, no matter how you change the value (by hand, PowerShell webconfigmod, or via a feature) if you edit the claim authentication provider settings in Central Admin, it will helpfully change it back to true.

So be careful, KB979917 is like a little bomb that has the potential to go off every once in a while to ruin your day and your user’s day.

Author: Doug Ware

Publishing in Sandbox Solutions – Create a Page

I recently built a publishing solution for a client that is deployed as a sandbox solution on Office 365. It was a fairly typical publishing solution containing master pages, page layouts, web parts, and other assets. Content production (putting words and media on pages) took place after deployment of this solution, but we had an initial site map. Therefore the solution built the site with a feature event receiver that created subsites, added blank publishing pages with custom page layouts, and configured navigation.

In a farm based deployment the creation of a publishing page is easy thanks to members of the Microsoft.SharePoint.Publishing assembly like AddPublishingPage method of the PublishingWeb class. Unfortunately the Microsoft.SharePoint.Publishing assembly is not available in the sandbox. Fortunately, the contents of the assembly are not obfuscated and I was able to use ILSpy to understand and recreate AddPublishingPage in my own assembly.

First I need a string that represents the new page’s markup.

internal static class CompiledTemplateStrings
			

{

    internal static string templateRedirectionPageMarkup = 

@"<%@ Page Inherits='Microsoft.SharePoint.Publishing.TemplateRedirectionPage,
Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c' %>

<%@ Reference VirtualPath='~TemplatePageUrl' %> <%@ Reference VirtualPath='~masterurl/custom.master' %>";

}

 

Then I need a class that creates a new SPFile from an array of bytes that represent the page content. Once created, the code sets the appropriate properties to make the new page an Article Page content type and set the PublishingPageLayout and Title. Finally, the file is checked in and approved.

internal class PublishingPageCreator
			

{

    private static byte[] pageAsBytes;

    private static readonly UTF8Encoding PageEncoder = new UTF8Encoding();

    internal static byte[] GeneratePageStreamAsBytes()

    {

        if (pageAsBytes == null)

        {

            byte[] bytes = PageEncoder.GetBytes(CompiledTemplateStrings.templateRedirectionPageMarkup);

            pageAsBytes = new byte[bytes.Length + 3];

            pageAsBytes[0] = 0xef;

            pageAsBytes[1] = 0xbb;

            pageAsBytes[2] = 0xbf;

            bytes.CopyTo(pageAsBytes, 3);

        }

        return pageAsBytes;

    }

 

    internal static SPListItem AddPublishingPage(string name, string title, string layout, SPFolder folder)

    {

        SPFileCollection files = folder.Files;

        byte[] file = GeneratePageStreamAsBytes();

        SPFile newFile = files.Add(name, file);

        SPListItem item = newFile.Item;

        item["ContentType"] = "Article Page";

        item["ContentTypeId"] = "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D";

        item["PublishingPageLayout"] = layout;

        item["Title"] = title; 

        item.Update();

        newFile.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);

        item.ModerationInformation.Status = SPModerationStatusType.Approved;

        item.Update();

        return item;

    }

}

 

Invoke AddPublishingPage as follows:

PublishingPageCreator.AddPublishingPage(pageName, "Page Title", rootWeb.Url + @"/_catalogs/masterpage/MyPageLayout.aspx, My Page Layout", pages.RootFolder);

 

Use your target site’s Url as rootWeb.Url. pages is an SPList instance of the Pages library.

You can read about an alternative approach using a module element in this excellent post: http://stefan-stanev-sharepoint-blog.blogspot.com/2010/07/provision-publishing-pages-in-sandbox.html

Author: Doug Ware