SharePoint Item Level Security means nothing to the BLOB Cache with anonymous access
[Update 9/10/2012: The fix for this was released in the August 2012 CU for SharePoint 2010. I have not tested this myself yet but once I do, I’ll confirm here if it is truly fixed. See the following blog post for more information on the update itself: http://blogs.technet.com/b/stefan_gossner/archive/2012/09/02/august-2012-cu-for-sharepoint-2010-has-been-released.aspx]
Now hold your horses, you’re saying “Well duh, it’s anonymous access” but follow closely, I’m talking about item level security on items where you have REMOVED Anonymous access. I’m going to show you how security is enforced with default SharePoint security, but broken when the BLOB Cache is enabled.
I ran across this issue the other day while working with one of my customers. Initially I was thinking this was a misconfiguration in their environment as it was pretty complex. To eliminate the possibility of it being a configuration issue in their environment, I setup a very simple repro in my lean SharePoint 2010 environment.
In a nutshell, with BLOB Caching enabled, it’s not guaranteed that individually secured items that do NOT have anonymous access won’t be served up to requests if they reside in a list/document library that allows Anonymous access. The steps laid out here, show that someone who does not have rights to a resource can still view documents that they shouldn’t.
Note: If you do NOT have the file types defined in the BlobCache element everything works fine. And, if you DO NOT have the BLOB Cache enabled, normal SharePoint security works just fine.
Let me add the caveat that it’s probably not a good idea to put items such as word/excel/pdf etc in the BLOB Cache, but some people have reason to do so.
Special thanks to Sean McDonough (http://sharepointinterface.com/) and Todd Klindt (http://www.toddklindt.com/blog/default.aspx) for letting me bounce some thoughts off of them, and their assistance with making sure I wasn’t going crazy J.
· Windows Server 2008 R2
· SQL 2008 R2
· SharePoint 2010 Server with Service Pack 1 applied.
Steps to reproduce behavior
First we’ll initialize Anonymous access for the web application and site collections we’ll be testing on.
Ensure that you have a web application that has Anonymous Access enabled.
Navigate to Application Management in Central Administration, then Manage web applications under the Web Applications section. Then select the web application of choice and select the Authentication Providers button on the ribbon.
Choose the zone you wish to configure,
Ensure Enable anonymous access is checked on in the Anonymous Access section.
Create a Site Collections and enable Anonymous Access at the site level.
For this example, I utilized the following naming convention on my site.
1 Site collection based on the Team Site ( A plain vanilla SharePoint site) http://extranet.jupiter.local/sites/team
For the site collection perform the following steps. (Note that the screen shots are showing a publishing portal, but the steps are the same for a plain team site.)
Select Site Permissions from the Site Actions button.
Select the Anonymous Access button on the Ribbon.
Select Entire Web site from the choices on the Anonymous Access dialog.
The resulting permissions list for the site will then look similar to the following on a publishing site.
At this point the default document libraries in the sites already have Anonymous Access enabled (since they are inheriting from the site (web) level. For a publishing site, the default document library is called “Documents” for a team site, it’s called “Shared Documents”. Just noting it when we get into the details of the ULS logs etc. My troubleshooting on this issue was initially on a publishing site, so there may be inclusions of that traffic in the details.
Now, it doesn’t matter if you have a folder hierarchy in the document libraries or not, as the root of the problem stems from checking at the list/document library level for Anonymous access, but we’re going to mix it up a bit by creating a subfolder in our document library and breaking inheritance on it as well, just to show the depth of the problem.
Setting up our document/folder hierarchy.
Perform the following steps in the “Shared Documents” folder on the team site.
Navigate to the document library and select Documents from Library Tools. Then select the New Folder button on the ribbon.
Name the new folder “secure” and select save.
From the drop down for the new folder, select Manage Permissions.
Select the Stop Inheriting Permissions button on the ribbon.
The end result of the permissions for the folder will now show that Anonymous users do not have access, and any new documents introduced into this folder will thus use the permissions of the folder for their security.
Important, if you do this on a publishing site, be sure you “APPROVE” the new “secure” folder so it’s visible to authenticated users.
Now let’s create some test files. The type of file doesn’t matter to reproduce the problem. It’s just a matter of that file extension being in the BlobCache setting in the web config. For purposes of my demonstration, I’m just going to create two simple text files. One called “unsecure.txt” and one called “secure.txt”
I have uploaded the unsercure.txt file to the root of the document library, and have uploaded the secure.txt file to the secure folder within the document library.
Important, on a publishing site, be sure you Check In/Publish and Approve the documents!
For the secure.txt document, also stop inheriting permissions from its parent. It’s currently inheriting from the secure folder, but let’s go ahead and give it item level security as well.
Showing how SharePoint Security Works as expected
Now let’s navigate to the site as an anonymous user, and you’ll see that we CAN navigate to the root of the document libraries, but we can NOT navigate to the secure folder in the libraries (nor see them) anonymously.
Now try to browse directly to the individual files. (Yes, you DO need to know the exact url to the file to show the problem, but how many times does that happen in an email forward or copy where you’re given the url to a file you shouldn’t have access too J).
For our test purposes, here are the direct URL’s to the files
What you’ll notice is that as an anonymous user, you can browse directly and view/download the unsecure.txt files, but NOT the secure.txt files which are expected behaviors. Everything is working like a charm. You know that your files that do NOT have anonymous access cannot be viewed by folks who should NOT be able to view them. The SharePoint security/authorization structure is working perfectly.
(Note: As I was preparing this, I was UNABLE to even view the root of the “Documents” folder in a Publishing site even though the document library DOES in fact allow anonymous access. This is different from the behavior of the team site, but that’s a whole different problem in itself, and I’ll post on that one separately. The key is that the unsecure.txt file CAN be viewed anonymously.)
Showing how SharePoint Security breaks with the BLOB Cache
Now, let’s completely break our security system by enabling the BlobCache.
If you want to read a good article on using the BLOB Cache in your sharepoint environment, check out Seans’ post here: http://sharepointinterface.com/2012/03/12/do-you-know-whats-going-to-happen-when-you-enable-the-sharepoint-blob-cache/
Edit the web.config for this web application, and find the BlobCache entry, and enable.
By default, the BlobCache element in the web.config will look as so:
<BlobCache location="C:\BlobCache.14" path="\.(gif|jpg|jpeg|jpe|jfif|bmp|dib|tif|tiff|ico|png|wdp|hdp|css|js|asf|avi|flv|m4v|mov|mp3|mp4|mpeg|mpg|rm|rmvb|wma|wmv)$" maxSize="10" enabled="false" />
To enable it, we set the enabled attribute to true rather than false. Now, this alone isn’t going to cause the problem, unless one of the documents you’re trying to keep secure is one of the file types listed in the path attribute. For instance, if the files you are trying to secure are mp3/mov files etc. the problem would in fact present itself. So in order to show our problem, let’s also add the txt file extension to the path attribute. The end result is a BlobCache element that looks similar to the following:
<BlobCache location="C:\BlobCache.14" path="\.(txt|gif|jpg|jpeg|jpe|jfif|bmp|dib|tif|tiff|ico|png|wdp|hdp|css|js|asf|avi|flv|m4v|mov|mp3|mp4|mpeg|mpg|rm|rmvb|wma|wmv)$" maxSize="10" enabled="true" />
Clear your browser cache or use InPrivate browsing, and refresh the file at http://extranet.jupiter.local/sites/team/Shared%20Documents/unsecure.txt
The file should of course open, but if you look at the folder hierarchy in the BlobCache folder you setup in the web.config, you’ll notice the file is now in the cache.
Now let’s browse to the secure.txt file which does NOT allow anonymous users access.
Be sure to clear your browser cache so that it does in fact make a request to the server for the file.
You MAY get prompted initially for credentials, but if so just hit cancel and refresh
Whoa! An anonymous user is now able to see a document you THOUGHT was secure!
Even if you clear the cache and do an iisreset, the problem will still persist.
Run the following commands in powershell to clear the blobcache (Changing the url to your own of course) then do an IIS reset.
$webApp = Get-SPWebApplication "http://extranet.jupiter.local"
If you now go back and disable the BlobCache (enabled=”false”) everything will start working for you. You’ll get a 401 unauthorized response as you would expect.
Now obviously the quick solution/workaround to this problem is to NOT include document types that may have security on them in the list of document types on the path attribute of the BlobCache. Especially if the performance improvements by using the Blobcache is important to your environment.
After poking around using reflection, it appears that with BLOB Caching, the only check when a resource is requested is at the list level. If the Caching layer sees that the list allows anonymous access, requests to the resource are cached and thus served to the end user.
What’s the correct behavior?
So this begs the question: “Which algorithm is right?”
1. Does SharePoint "officially" support per-item security in a list marked for anonymous access? If so, the BLOB Cache behavior is wrong.
2. If the BLOB Cache behavior is officially "right" according to Microsoft, then SharePoint itself isn’t properly handling permission checks (and should be allowing access).
Either way, something needs to be fixed/changed, and I would highly consider you checking your environment for this little “Gotcha”.
Hope this helps!