Showing posts with label RunWithElevatedPrevilages. Show all posts
Showing posts with label RunWithElevatedPrevilages. Show all posts

Monday, 18 January 2016

Limitations with RunWithElevatedPrivelege in SharePoint

Hi all,


I just want to share couple of things about security issues with RunWithElevatedPriveleges in SharePoint.


Elevated Privilege can be used to bypass or work with security, and can be performed either through SPSecurity or through impersonation techniques involving the SPUserToken and the SPSite class.


Avoid using SPSecurity.RunwithElevatedPrivilege to access the SharePoint object model. Instead, use the SPUserToken to impersonate with SPSite. If you do use SPSecurity.RunwithElevatedPrivilege, dispose of all objects in the delegate. Do not pass SharePoint objects out of the RunwithElevatedPrivilege method.


Only use SPSecurity.RunwithElevatedPrivilege to make network calls under the application pool identity. Don't use it for elevation of privilege of SharePoint objects.


Here the sample code to show what is the issue with RunWithElevatedPrivileges.


SPList taskList=null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
      SPSite elevatedSite = SPContext.Current.Site;

      using (SPWeb elevatedWeb = elevatedSite.OpenWeb())
      {
           taskList = elevatedWeb.Lists["Tasks"]
      }
   }
});
//This code will succeed even outside the block as it is accessed via elevated SPWeb. Hence Security Risk.
taskList.Delete();



Always use the SPSite constructor with an SPUserToken to create an elevated privilege security context in SharePoint.


This is most recommend way and best practice  to perform impersonation in context of SharePoint. However,When using SPUserToken, you need ensure that the user exists whom you are impersonating, and that user has the proper permissions. In production scenarios, you may not know the user in advance and this technique may not work
Below is the example to impersonate SHAREPOINT\SYSTEM account.
SPWeb oWeb = SPContext.Current.Web;
SPUserToken token = oWeb.AllUsers[@"SHAREPOINT\SYSTEM"].UserToken;
using (SPSite elevatedSite = new SPSite(oWeb.Site.ID, token))
 {
    using (SPWeb elevatedweb = site.OpenWeb())
     {
      // Perform administrative actions by using the elevated site and web objects.
      // elevatedWeb.CurrentUser.LoginName gives SHAREPOINT\system
      // WindowsIdentity.GetCurrent().Name gives current logged-in username i.e. SPContext.Current.Web.CurrentUser.LoginName.
      // Hence,Only SharePoint Security context is changed while Windows Security context is not changed.
     }
 }



If you see the code above, WindowsIdentity.GetCurrent().Name is same as the Name of current user making the request which is SPContext.Current.Web.CurrentUser.


So  any call to external systems like DB or WebServices will be made by windows account of the current user. It succeeds or not depends on the permissions that the user have on that external system.


If you want make network calls under the application pool identity  or you don’t have a valid and known SPUser to retrieve SPUsertoken then SPSecurity.RunWithElevatedPrivileges is the only choice.



And also the tokens time out after 24 hours, so they can be used in the code that needs to impersonate users in the case of workflow actions or asynchronous event receivers occurring within 24 hours.After the  SPUserToken object is returned to the caller, it is the caller’s responsibility to not use the token after it is expired.
The token timeout value can be set by using the Windows PowerShell console or stsadm.
   
stsadm -o setproperty -propertyname token-timeout -propertyvalue 720

Sunday, 9 February 2014

How to run code Under administrator privileges in SharePoint

There are two ways to run a set of lines of code under administrator previlages.

Method 1:using runwithelivatedprevilages

this method runs under the Application Pool identity, which has site collection administrator privileges on all site collections hosted by that application pool.
NOTE: All the operations done inside this method should use a new SPSite Object. This means that the SPSite variables that are instantiated or created outside the subset code of this method can't be used for security elevation and it will result with the "Access denied error".

Wrong:

//SPSite Object created outside the RWEP Method
SPSite  site = new SPSite("siteURL");

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPWeb web = site.OpenWeb())
    {
        string user = web.CurrentUser.Name;
        //Operations that need high level access.
    } 


});

Correct:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    //New SPSite object.
     using (SPSite site = new SPSite(web.Site.ID))
     {
    //Do things by assuming the permission of the "system account".
     }
});

Remember that, don’t use an object created outside of the RunWithElevatedPrivileges delegate within the delegate, and dispose all SPSite and SPWeb objects created within the delegate before the delegate completes.
And also dont use SPContext.Current.Web; to get SPWeb reference within the RunWithElevatedPrivileges.


Method 2: Using SPUserToken

Alternative impersonation technique to RunWithElevatedPrivileges() method:

We can either create a new SPSite instance from the existing SPSite Object, whose constructor will be provided by the "UserToken" of the System Account or we can assign the "UserToken" property of the SPSite object, see the below code snippet.

//Creating a SPUsertoken object.
SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;
//passing to the constructor of the SPSite

SPSite spSite=new SPSite("siteURL",saUserToken);

or

SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;
SPSite spSite=new SPSite("siteURL");
//assigning the UserToken property of SpSite.

spSite.UserToken= saUserToken;  

Bellow is example for UserToken

SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;

using (var site3 = new SPSite(site.OpenWeb().Url, saUserToken ))
{
// This code runs under the security context of the SHAREPOINT system
//  for all objects accessed through the "site" reference. Note that it’s a
// different reference than SPContext.Current.Site.

   using (var elevatedWeb = site3.OpenWeb())
     {
       // Perform actions as SYSTEM here
       SPUser spUser = elevatedWeb.EnsureUser(username);
       SPGroup spGroup = elevatedWeb.SiteGroups["Partners"];
       if (spGroup != null)
        {
          site3.AllowUnsafeUpdates = true;
          spGroup.AddUser(spUser.ToString(), spUser.Email.ToString(),                                           spUser.Name.ToString(), spUser.Notes.ToString());
          site3.AllowUnsafeUpdates = false;
       }
    }
}

Performance impact with RunWithElevatedPrivileges creates a new thread with the App Pool's credentials, blocking your current thread until it finishes.