During one of our engagements we were investigating a Microsoft 365 environment. My colleague Rik discovered that many SharePoint sites were publicly available within the organization. We were surprised by the amount sites that were wide open this way. A lot of sensitive information was located on those sites, for example PII-information and passwords for critical systems.
Let’s go back in time
As penetration testers we performed many internal tests on the local networks of organizations. After gaining more and more experience, we developed a standard way of working. We would start by scanning the network for low hanging fruit. At the time I wrote a tool to automate this phase using Metasploit to make live easier.
One of the easiest low hanging fruit issues were open SMB-shares available on the internal network. The approach: scanning for open shares, than analyze the information that’s within those share. Such information might be useful in compromising other machines within the network.
Similar attacks
As you probably already noticed, both attacks (SharePoint and open shares) are pretty similar. Because of a misconfiguration, sensitive information is available to the attacker that may be used during the attack. This might be crucial information for an adversary to be successful.
The issue
So, why does this SharePoint issue occur? If a regular user creates a SharePoint website, he has the option to assign the Public option within the Privacy settings. Whenever a user selects this option, anyone within the organization can access the site. In other words: all authenticated users in the tenant.
Public Teams create Open Shares
Now in most organizations, it might not be very common for a regular user to create SharePoint sites at all. But this has changed with the rapid adoption of Microsoft Teams. And here comes the kicker: a Public Team creates a Public SharePoint site for it’s filestorage. In other words: Public Teams are Open Shares. Let that sink in.
As Teams is now the defacto standard for collaboration within many organizations, lots of employees have developed the habit to quickly spin up a new team for all kinds of reasons. A new project, a multidisciplinary team, an event, partner or customer engagement. To name a few. Such teams might start quite meaningless in terms of sensitive information. But they might just as well grow to become a huge trove of knowledge right there for grabs to an attacker snooping around.
Discovering public SharePoint sites within your organization
As an (SharePoint) administrator it is possible to view the sites that are set to public. Through the portal youncan find all Active Sites through the admin portal, select “SharePoint” -> Sites -> Active Sites. By clicking a specific site, its possible to view the Site members at the Permissions tab. If “Everyone except external users” is listed, it means the site is public within your organization.
As an alternative I wrote a Powershell one-liner. This Powershell query returns a list of all public available sites within your organizations tenant:
Get-SPOSite | ForEach-Object { try { $res = Get-SPOSiteGroup -Site $_.url | Where-Object {$_.Users -Match “spo-grid-all-users”}; if ($res -ne $null) { write-host $_.url } } Catch {} }
Detecting the creation of Public sites using Sentinel
For our SMB security app Attic we also decided to write a Sentinel query. The query detects the creation of a new public SharePoint sites. Whenever a user creates a public SharePoint site, the rule triggers. This allows an organization to monitor for misconfigured SharePoint sites and take particular measurements if needed (make it private). We have shared the rule on our GitHub page here.
Its important to note that the query currently only works for tenants with the English or Dutch language. If your tenants uses another language, add the correct group name to the Translations dynamic. It sucks, but it works for now ;-).
Using Graph API to find sites.
We can also use the OfficeActivity log to detect new sites being created. However that way we will miss the sites that already existed before starting the monitoring.
We looked into Graph API in order to find all the SharePoint sites and whether they are public. The interesting thing is that we could find the sites but were unable to see whether they are public or private. After digging for a while we found that we could detect sites based on the groups in the tenant. We use the Graph API “/v1.0/groups” endpoint. The endpoint returns different groups, you can detect SharePoint sites by searching for “SPO_<GUID>” in the proxyAddresses property.
We wrote a simple script to check whether your organization has SharePoint sites set to public using the Graph API:
Preventing users from creating Public SharePoint sites
The best solution would be to completely prevent the creation of new sites with the Public privacy settings. At time of writing this blog, we haven’t found a nice solution to completely prevent this, which kind of surprised us. Please let us know if you read this blog and do have a solution.
Rik made a statement which I kind of liked, because it seems true as more and more companies are moving to the cloud:
Public SharePoint sites are the new open shares
Attic and SharePoint sites
We added CHK-1520 to Attic. Every new SharePoint site that gets created with the access set to public will result in an alert. We’re currently looking to expand these types of checks and are looking into:
- Detect sites that haven’t been used for a while. Possibly combined with the fact that they are public.
- Detect public OneDrive libraries.
- Detect files being shared with direct links instead of based on email address or password.