Second Life of a Hungarian SharePoint Geek

March 3, 2016

Access Denied when Setting Group Properties as Group Owner

Filed under: Bugs, Security, SP 2013 — Tags: , , — Peter Holpar @ 22:10

We have a SharePoint group whose members should administer group membership of other, business-related SharePoint groups. We assigned this group as a Group Owner to the other groups, thus they have the required permissions to group administration.

This week one of the group administrators was to change the description of one of the groups. Actually, it is not part they mission, however I don’t see any problem with that. SharePoint itself defines the rule of the group owner on the Change Group Settings page:

The owner can change anything about the group such as adding and removing members or deleting the group.

Yes, they can even delete the group, I have tested it.

However in this case the member of the group owner group received an Access Denied error, when he submitted the changes to the server. To be able to understand the reason, let’s first see the corresponding ULS logs:

03.01.2016 17:27    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           8e2s    Medium      Unknown SPRequest error occurred. More information: 0x80070005    e552649d-8539-f075-b98b-accc2d7bd4f5
03.01.2016 17:27    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           aix9j    High        SPRequest.AddOrUpdateItem: UserPrincipalName=i:0).w|s-1-5-21-1613396233-3282607421-4023646941-2481, AppPrincipalName= ,bstrUrl=
http://YourSharePoint ,bstrListName={F0FF0E7F-61FE-4BBF-993A-2F396E44E133} ,bAdd=False ,bSystemUpdate=False ,bPreserveItemVersion=False ,bPreserveItemUIVersion=False ,bUpdateNoVersion=False ,pbstrNewDocId=00000000-0000-0000-0000-000000000000 ,bHasNewDocId=False ,bstrVersion=23 ,bCheckOut=False ,bCheckin=False ,bUnRestrictedUpdateInProgress=False ,bMigration=False ,bPublish=False ,bstrFileName=<null>    e552649d-8539-f075-b98b-accc2d7bd4f5
03.01.2016 17:27    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           ai1wu    Medium      System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)), StackTrace:    at Microsoft.SharePoint.SPListItem.AddOrUpdateItem(Boolean bAdd, Boolean bSystem, Boolean bPreserveItemVersion, Boolean bNoVersion, Boolean bMigration, Boolean bPublish, Boolean bCheckOut, Boolean bCheckin, Guid newGuidOnAdd, Int32& ulID, Object& objAttachmentNames, Object& objAttachmentContents, Boolean suppressAfterEvents, String filename, Boolean bPreserveItemUIVersion)     at Microsoft.SharePoint.SPListItem.UpdateInternal(Boolean bSystem, Boolean bPreserveItemVersion, Guid newGuidOnAdd, Boolean bMigration, Boolean bPublish, Boolean bNoVersion, Boolean bCheckOut, Boolean bCheckin, Boolean suppressAfterEvents, String filename, Boolean bPreserveItemUIVersion)     at …    e552649d-8539-f075-b98b-accc2d7bd4f5
03/01/2016 17:27:28.61*    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           ai1wu    Medium      …Microsoft.SharePoint.SPListItem.Update()     at Microsoft.SharePoint.ApplicationPages.CBaseNewGroup.UpdateAdditionalProperties(Int32 groupId)     at Microsoft.SharePoint.ApplicationPages.EditGroup.DoOperation()     at Microsoft.SharePoint.ApplicationPages.CBaseNewGroup.BtnOK_Click(Object sender, EventArgs e)     at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)     at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)     at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)     at System.Web.UI.Page.ProcessRequest()     at System.Web.UI.Page.ProcessRequest(HttpContext context)     at System.Web.HttpApplication.CallHandlerExecutionStep.Syste…    e552649d-8539-f075-b98b-accc2d7bd4f5
03/01/2016 17:27:28.61*    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           ai1wu    Medium      …m.Web.HttpApplication.IExecutionStep.Execute()     at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)     at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)     at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)     at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)     at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)     at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)     at System.Web.Hosting.UnsafeII…    e552649d-8539-f075-b98b-accc2d7bd4f5
03/01/2016 17:27:28.61*    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           ai1wu    Medium      …SMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)     at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)     at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)     at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)      e552649d-8539-f075-b98b-accc2d7bd4f5
03.01.2016 17:27    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           ftd0    Medium      Access Denied. Exception: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)), StackTrace:   at Microsoft.SharePoint.Library.SPRequestInternalClass.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bPreserveItemUIVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bUnRestrictedUpdateInProgress, Boolean bMigration, Boolean bPublish, String bstrFileName, ISP2DSafeArrayWriter pListDataValidationCallback, ISP2DSafeArrayWriter pRestrictInsertCallback, ISP2DSafeArrayWriter pUniqueFieldCallback)  …    e552649d-8539-f075-b98b-accc2d7bd4f5
03/01/2016 17:27:28.61*    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             General                           ftd0    Medium      …   at Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bPreserveItemUIVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bUnRestrictedUpdateInProgress, Boolean bMigration, Boolean bPublish, String bstrFileName, ISP2DSafeArrayWriter pListDataValidationCallback, ISP2DSafeArrayWriter pRestrictInsertCallback, ISP2DSafeArrayWriter pUniqueFieldCallback).    e552649d-8539-f075-b98b-accc2d7bd4f5
03.01.2016 17:27    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             Micro Trace                       uls4    Medium      Micro Trace Tags: 0 nasq,6 agb9s,18 ak8dj,12 b4ly,0 b4ly,41 aix9j,0 ai1wu,0 ftd0    e552649d-8539-f075-b98b-accc2d7bd4f5
03.01.2016 17:27    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             Monitoring                        b4ly    Medium      Leaving Monitored Scope (Request (POST:
http://YourSharePoint/_layouts/15/editgrp.aspx?Group=YourGroup&Source=http%3A%2F%2FYourSharePoint%2F%5Flayouts%2F15%2Fpeople%2Easpx%3FMembershipGroupId%3D6650)). Execution Time=81,9053366451775    e552649d-8539-f075-b98b-accc2d7bd4f5
03.01.2016 17:27    w3wp.exe (0x339C)                           0x439C    SharePoint Foundation             Claims Authentication             amge7    Medium      SPFederationAuthenticationModule.IsRedirectToLogOnPage: Detected a redirection but the redirect is not to a known signin page:
http://YourSharePoint/_layouts/15/AccessDenied.aspx    e552649d-8539-f075-b98b-accc2d7bd4f5
03.01.2016 17:27    w3wp.exe (0x339C)                           0x49EC    SharePoint Foundation             Monitoring                        nasq    Medium      Entering monitored scope (Request (GET:
http://YourSharePoint/_layouts/15/AccessDenied.aspx)). Parent No    

As you can see, on the page editgrp.aspx we have an UnauthorizedAccessException: Access is denied. However, at first it seems to be not group-related, as it is thrown in the SPListItem.AddOrUpdateItem method. What’s that?

As I am aware of that the rich text description of a group is stored in the Notes field corresponding list item in the hidden user information list,and not in the SPGroup object itself, at this point I had already an idea, what might be the reason of the the issue. But let’s prove that scientifically!

Later in the stack trace we found the UpdateAdditionalProperties method of the Microsoft.SharePoint.ApplicationPages.CBaseNewGroup class, called by the DoOperation method of the Microsoft.SharePoint.ApplicationPages.EditGroup class.

The DoOperation method updates group properties stored in the SPGroup object itself, but the UpdateAdditionalProperties method updates the information stored in the list item fields in the user information list, like the description of the group, and other fields requested in optional query string parameters:

  1. protected void UpdateAdditionalProperties(int groupId)
  2. {
  3.     SPListItem itemById = base.Web.SiteUserInfoList.GetItemById(groupId);
  4.     string text = this.txtGrpDescription.Text;
  5.     itemById["Notes"] = text;
  6.     int num = 1;
  7.     while (true)
  8.     {
  9.         string str2 = base.Request.QueryString["FieldName" + num.ToString(CultureInfo.InvariantCulture)];
  10.         if (string.IsNullOrEmpty(str2))
  11.         {
  12.             break;
  13.         }
  14.         string str3 = base.Request.QueryString["FieldValue" + num.ToString(CultureInfo.InvariantCulture)];
  15.         itemById[str2] = str3;
  16.         num++;
  17.     }
  18.     itemById.Update();
  19. }

A minor detour about the user information list. As you know, it is a hidden list on the SharePoint site collection root web site, and typically accessed via the URL http://YourSharePoint/_catalogs/users/simple.aspx. However, it is a common misunderstanding, even in case of well-known SharePoint experts, that “This list is only visible to and accessible by administrators”. Based on my experience, it is true only for the webpage (_catalogs/users/simple.aspx), but not for the list itself. The list inherits its permissions from the root site, meaning anyone having read permission on the root site, can access the list.

For example, simply by using REST:

http://YourSharePoint/_api/Web/SiteUserInfoList

or (assuming the Guid is the ID of the list):

http://YourSharePoint/_api/Lists/GetById(‘6749e2d2-ca87-445f-8fc1-b7f7a4e410ad&#8217;)

However

http://YourSharePoint/_api/Lists/GetByTitle(‘User%20Information%20List&#8217;)

does not work, because it is a hidden list.

One can even list all site users via the URL:

http://YourSharePoint/_api/Web/SiteUserInfoList/Items?$select=Title,Name

To be sincerely, I’m not sure if it is a feature or simply a security vulnerability. I’ve also tried to update the list items of the user list from the client side using the managed client object model by the credentials of a user having write permission on the site, but up to know I have not “succeeded”, received access denied. But I don’t give up. Winking smile

After the detour, let’s back to our issue. Since in our case the user had no write permissions on the root site (and thus no write permissions on the list and the list items), the UpdateAdditionalProperties method was not able to set the group description (the Notes field of the list item) and resulted in the Access Denied error. Other members of the same owner group, having the write permission on the root site level, have no such problems.

It is important to point out, that even if the user has no write permission and get the Access Denied error, other changes in the group configuration (like the Name or “Who can edit the membership of the group“) are updated for the group, as they are already saved by the DoOperation method before the exception was thrown by the UpdateAdditionalProperties method. You can prove that by navigating back to the Change Group Settings page, and reload it in browser via F5. The same is true, when one sets the group properties by code, like the managed or JavaScript client object model or by REST request. The owner can change group properties stored in the SPGroup object without error, but not the list item in the user list.

I consider this behavior to be a bug, and I think the UpdateAdditionalProperties method should include an elevated privileges code block to enable group owners to change the properties stored in the list item fields as well.

That’s all I wanted to share about the error itself, but if you have time, you can read on for another story.

There is an other misunderstanding I read in other SharePoint blogs while researching the issue. One may think, that setting a group as its own group owner (Solution 1) and selecting the “Group Members” option for “Who can edit the membership of the group“ (Solution 2) are interchangeable (see Scott Baitz stating his Solution 2 “will provide the same functionality as the solution above”, Solution 1). That is definitely false. Let’s see the difference, starting with Solution 2, then comparing the extra permissions one get via Solution 1.

Solution 2

If you allow group members to edit group membership by implementing Solution 2, the group members can add other users to the group or remove users, even themselves from the group. (Note: If they removed themself  from the group, that action would be of course not reversible. They can not add themself back to the group, only if they have that permission via the group owner group or they have other administrative permission, like site collection administrator, or full control permission on the site.)

The group members have access to the page People and Groups : YourGroup (http://YourSharePoint/_layouts/15/people.aspx?MembershipGroupId=4600, assuming 4600 is the ID of your group). where they can list and change the group membership.

On this page they have the following options:

New menu:
Add Users

Actions menu:
E-Mail Users
Call/Message Selected Users
Remove Users from Group

Settings menu:
View Group Permissions

The group members can not edit group properties. The “Group Settings” is not displayed in the Settings menu, and even if they try to access the page by its URL (like http://YourSharePoint//_layouts/15/editgrp.aspx?Group=YourGroup), they get an error message:

Only owners of the group "YourGroup" can change its settings

(Actually, the permissions are checked in the InitPage method of the Microsoft.SharePoint.ApplicationPages.EditGroup class, by invoking the CanCurrentUserManageGroup method of the Microsoft.SharePoint.SPGroup class.)

Solution 1

As a group owner, you have the same options as in the case of Solution 1, and additionally you have the “Group Settings” in the Settings menu to access the People and Groups : Change Group Settings page and edit group properties. (Of course, if you remove yourself or your group from the Group Owner field, and you have no other extra permission on the site, you can not undo this action. It’s the same as above in Solution 2 with group membership.). If the group owner has no write permission of the root site, an Access Denied is thrown when setting group properties via the page, see the original issue in this post.

Finally, when a user browses the groups in a site, he can found that the “View Group Permissions” is displayed in the  Settings menu for one group, but it is not available for the other group. This option (as you can expect) is again permission dependent. The permissions are checked in the OnLoad method of the Microsoft.SharePoint.ApplicationPages.PeoplePage class (the code behind of the people.aspx page). The “View Group Permissions” option is visible, if the DoesCurrentUserHavePermission method of the Microsoft.SharePoint.WebControls.GroupPermissions class returns true:

internal static bool DoesCurrentUserHavePermission(SPWeb web, SPGroup group)
{
    if (!group.ContainsCurrentUser && !group.CanCurrentUserEditMembership)
    {
        return false;
    }
    return true;
}

(Note that the method has two parameters. The first one is of type SPWeb but that is not used at all in the method.)

That means, the “View Group Permissions” option is displayed only if the user is member of the group or can edit the group membership. On the other side, if the user can access the people.aspx page for the group, and see the group membership only because the group is configured to allow “Everyone” as “Who can view the membership of the group“, this option is not available. With other words, a user that is not in the group itself, not the owner of the group, and have no admin rights are not allowed to see the group permissions.

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: