When you setup SQL Server Reporting Services [SSRS] in SharePoint Integrated mode, browsing http://servername/ReportServer will show you a directory listing view of SharePoint Site Collections that is security trimmed to you. However, there are some downsides to this view. Users can probe through the directory structure of your site that they have read access to, and users may see links to sites that you didn’t intend for them to see.
In my test farm, when a user named BobSmith browses, he sees the following:
If bobsmith clicks on the link for http://teams.jormanvmas.com, he is able to browse through the folder structure of the site collection. If he ever finds a report [RDL file], he could click on the RDL file and the report would try to render. Users may also discover URLs that they didn’t know existed, and the person that owns the site may not want them to know the site exists.
For example, in the above output, BobSmith sees a link for http://teams.jormanvmas.com/sites/cqwp. However, if he clicks that link he gets:
If he browses the URL directly in the browser, as opposed to going through Report Server, he gets the following:
This is odd, the Report Server page should return sites that BobSmith has permissions to, but for some reason, he’s unable to browse the URL returned. To track down why this is occurring, I turned to the Debugging Tools for Windows. I attached windbg to ReportingServicesService.exe, and broke in on managed exceptions [command : sxe clr]. This revealed that Report Services has an HttpHandler, that eventually calls OpenWeb for each site collection in the farm.
I confirmed that when this call fails, the link will not render. This means that BobSmith’s account is able to call OpenWeb on the Site, even though BobSmith is unable to browse the site. I then browsed the CQWP site as another account that has full access, and used the Check Permissions functionality to determine what permissions BobSmith has on the site. This showed that BobSmith has Limited Access, which was granted via the Style Resource Readers group.
I then checked the Limited Access Permission Set and found that the following are granted:
- View Application Pages - View forms, views, and application pages. Enumerate lists.
- Browse User Information - View information about users of the Web site.
- Use Remote Interfaces - Use SOAP, Web DAV, the Client Object Model or SharePoint Designer interfaces to access the Web site.
- Use Client Integration Features - Use features which launch client applications. Without this permission, users will have to work on documents locally and upload their changes.
- Open - Allows users to open a Web site, list, or folder in order to access items inside that container.
There we are, the link shows up because BobSmith has Open permissions, which is enough for Reporting Server to render the link. I wanted to confirm why BobSmith was in the Style Resource Readers group. This group is added by the Publishing Features, and the group contains the NT Authority\Authenticated Users group. For some information on Style Resource Readers group and the authenticated users group, see the following article http://technet.microsoft.com/en-us/library/cc262690.aspx
From the above, we know that any site with the Publishing Features enabled will show up in the list of links when a user browses /ReportServer/, and if a user has read access, they can probe into the directory structure of your site. There’s not an out of the box way to disable that view, so if you want to disable it, you’re looking at writing some code. I put together an HttpModule that will block incoming requests that will render that view. The trick is that the Report Viewer control also makes requests to the /ReportServer URL to render reports, so you can’t block all requests. I went with the following to determine if a request should be blocked:
- Request has rs:Command QueryString set to ListChildren
- There is not an rs:Command and the request is to /ReportServer or /ReportServer/
The first scenario covers users sending a ListChildren command to the ReportServer. The second scenario covers a user sending a GET to the ReportServer url in a browser, as well as users sending a POST request via PowerShell or some other language to the root. These filters will still allow other rs:Command values as well as calls to the ASMX web services in the /ReportServer URL.
Here’s the code for a sample HttpModule. There are 3 methods:
- Init – hook up the BeginRequest event to your Application_BeginRequest method
- Application_BeginRequest – This is where the URL is checked out
- FailRequest – This clears and ends the response
Once you build out the HttpModule, you add it to the <httpModules> section of the web.config for Report Server, then restart the SQL Server Reporting Services service. By default, the web.config is found at :
C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportServer\web.config
For example, if you build the above code into an assembly named Sample.SharePoint.ReportServer.dll, you would add the following to the <httpModules> section of the web.config [after the <clear/> tag]: