Salesforce Lightning - Tinting the Windows
Table of Contents
Introduction
Since my previous blog post, a lot has happened. The post got the attention of the SaaS security experts at AppOmni, and I joined in November as a security engineer. I’ve been flooded with questions via LinkedIn and Twitter regarding Guest User misconfigurations. In total, 84% of these messages were from Salesforce consultants, architects, and Salesforce customers in general; expressing confusion on how these problems can be tackled without resorting to opening a support ticket directly with Salesforce. Evidently a piece on remediation and prevention is long overdue, so this it. Welcome to Tinting the Windows, a treatise on securing Guest User data access for your Salesforce communities.
Prerequisites
Environment
Naturally, modification of permission sets, configuration settings, and profiles, can have adverse effects on your Salesforce instance. This is somewhat alleviated by the fact that I will only be touching upon the Guest user. Regardless, in order to ensure the usability of your public communities is not affected, it is recommended to clone your configuration settings to a separate developer instance. The Ant Migration tool will assist greatly in copying over the metadata (configuration) but will not copy over the data itself. Therefore I would recommend the use of the Salesforce Data Loader to place a small amount of synthetic data to populate default and custom objects on the developer instance.
If you’ve read ahead, you may have also found that the information presented in the screenshots may not appear in the same fashion on your own instance. The reason being is that I’ve enabled the ‘Enhanced Profile User Interface’. In the interest of easy reproduction, I would highly recommend doing the same. To achieve this, search for ‘User Management’ in the Quick Find box and enable it.
Common Terminology
As was done in my previous article, I have provided a short list of common terms that are commonly used throughout this article, which admittedly contains some overlap. By understanding the concept of these terms, the overall understanding of the content in addition to the reading experience will be far better.
Objects - Effectively acting like database tables
Default Object - These are objects provided by Salesforce when the app is created for the first time.
Custom Object - These are objects created by admins. The ‘__c’ suffix denotes custom objects and fields.
Fields - Can be considered the 'columns' of a database. A small set of examples of fields in the 'User' object are: AboutMe, CompanyName, CommunityNickname.
Records - These are the 'rows' of a database (the actual entries of data).
Community - A branded area that can be created and deployed from your Salesforce instance, as a fully functioning website. In this article, a community will specifically refer to a space that is accessible by the public (as opposed to an exclusive partner or employee community).
Profile - These are created and assigned to users on Salesforce, for the purpose of defining their access levels and capabilities to perform certain actions. There are multiple Profiles available immediately upon creation of the instance, known as ‘Standard Profiles’.
Permission Set - Often confused with Profiles, Permission Sets are most commonly utilised to extend the access a specific user has, without modifying the Profile assigned to them.
Frequently Asked Questions:
Q. Is the ability for Guest users to directly query objects for record data a 0day?
A. No, it’s not a 0day. The Apex controllers used to extract data in my previous article have legitimate uses on Salesforce, and they are executed under the privileges of the current user. Insecure changes to settings, profiles, and permission sets over a period of time, are what allow for the data within object records to be seen.
Q. Am I vulnerable by default?
A. No, you’re not vulnerable by default, especially on newer instances which will have many of the more recent security updates applied from the get-go. However, if the Salesforce instance you’re managing is part of an older release, there may be security updates that have been released since that time which you will be required to apply yourself.
Getting Familiar with Release Updates
Prior to taking things into your own hands, the Release Updates section under Setup is invaluable for highlighting Guest user specific problems within the configuration. For old schoolers, you may be more familiar with this by its previous name, Security Alerts. Within your Salesforce instance, search for ‘Release Updates’ in the Quick Find box and navigate to it, you will be presented with a page similar to the following:
Specifically the items that we’re most concerned with resolving in this article are those relating to object visibility, record ownership, and sharing. These 3 specific areas are covered by the following updates:
If you’re puzzled as to what these updates actually mean, here’s a quick summary:
Assign Records Created by Guest Users to a Default Owner - Take a scenario in which unauthenticated users may submit case requests for issues they’re having with your product, which will be analysed by support whom will then reach out to you via email regarding the case status. These cases will likely contain sensitive information that you do not wish to share with anyone other than the support staff themselves. When you submit this case, a new record will be created in the Case default object that will hold case related information, such as your PII. Now, an administrator may think “Giving the Guest user access to their own case information is fine, since they created it”. However, the Guest user is a profile for all unauthenticated users, not just one specific person. As such, everyone may have access to all of the Case information that was created by other unauthenticated users, since their profile is the one that owns the records. On an important note, Salesforce organizations created after the Summer 20’ release will have the community owner as the default record owner if none are selected.
Remove View All Users Permission from Guest User Profiles - This one speaks for itself a little, and the User default object is one that’s more familiar to us. This setting prevents Guest users from being able to see information related to other users on the instance. Now, in rare cases this may be wanted behaviour if you have a public forum which intentionally pulls basic data such as CommunityNickname, CompanyName, FirstName and LastName fields etc et al. In contrast, a Salesforce instance that has no communities and should only be accessible upon authentication to force.com, will definitely not want Guest users having visibility of internal users.
Secure Guest Users’ Org-Wide Defaults and Sharing Model - Arguably the most confusing of the bunch. Simply put, all objects will now be ‘Private’ for the current and any new Guest user profiles created. In addition, to grant Guest users read access to certain objects (perhaps a Theme object required for a login page to function), a special sharing rule specifically just for Guest users will need to be created.
The ‘Get Started’ button will only provide a walkthrough checklist, as opposed to automatically enabling each setting for you. This makes complete sense, as different communities and instances will have different needs depending on their functionality. In the following subsections, I will go through the enablement of these settings in the order that they were listed above.
Default Owner Assignment for Records
Search for ‘Communities Settings’ in the Quick Find box and navigate to it. Select the ‘Assign new records created by guest users to the default owner’ option seen below and click ‘Save’.
Next, a default owner must be chosen. It’s important to note that the new default owner must have at least read access to any objects concerned. Once this is understood, follow this navigation flow to reach your ownership settings: All Communities > Workspaces > Administration > Preferences. Select a new owner via the search button and click ‘Save’.
The final matter of concern is what to do with the existing Guest owned records. For bulk migration of existing records to a new owner, I’ll shamelessly recommend once again the Data Loader tool. Here’s a quick guide for mass migrating Account object records to a new owner using the Data Loader, but it’s easily ported for objects that are more likely to have records owned by Guest users (such as Case, ContentDocument etc et al).
Removing Object Visibility
From my experience, the User object is the most commonly misconfigured and therefore often viewable by the Guest user. However as opposed to solely demonstrating the disabling of ‘View All Users’, it’s crucial to understand how to completely audit access to other default objects as well as custom ones. This section will be broken down into 3 separate parts; namely ‘Guest User Profile’, ‘Guest User Permission Set’, and the ‘Community Settings’ subsections.
Guest User Profile
Navigate to All Communities > Builder > Settings (cogwheel icon) > General. Click on the profile name under ‘Guest User Profile’:
Click into ‘Object Settings’ and you will be able to view the current access permissions specific to Guest users on all objects. As mentioned previously, the Guest user may be required to have read access to specific objects in order to perform basic functionality on the application. But for the most part, you’ll be looking for either double dashes (—) or ‘No access’ to make up the majority of the object permissions. These double dash characters signify that you may not grant any kind of access to the Guest user for the related object. Clicking on an object name, and subsequently clicking ‘Edit’, will allow for modification of the CRUD permissions on the object:
Once access has been directly modified via the ‘Object Permissions’ page, scroll down and click the ‘System Permissions’ option. These permissions can actually open access in more ways than just ‘Read’ through a simple checkbox, making it quite easy to over-extend access to certain objects.
As an example, if I were to enable the ‘Access Activities’ permission, I would actually grant read access to multiple objects in one go! The perceptive reader may have noticed that ‘View all Custom Settings’ is enabled for my Guest user. Custom settings are usually an amalgamation of data sets to be used with the API / Apex / and Flows, so this is definitely something I need to rectify. This is as easy as clicking ‘Edit’, unchecking the box, and clicking ‘Save’.
Bear with me, we’re nearly finished with this section. Now it’s important to validate the actual Guest user itself for any custom permissions that may be granted to it.
Guest User Permission Set(s)
From the Guest user profile, click ‘Manage Assignments’ and click the ‘Full Name’ of the Guest user:
Scroll down to ‘Permission Set Assignments’ and ensure that there are no extra permissions be granted to the Guest user unnecessarily, such as the example one below that provides read access to the Contact object. This area is often overlooked, as this extension in object permissions will not show up in the Guest profile itself:
Clicking' ‘Del’ under the ‘Action’ column will remove the permission set from the Guest user.
Community Settings
The community specific settings are arguably the most overlooked area with regard to object permissions. I would assume this is due to the fact that instead of a very explicit ‘View all’ / ‘Modify All’ statement beside an object, the configuration settings appear far more innocent at face value.
Navigate to: All Communities > Workspaces > Administration > Preferences:
In reference to the above image, the only particularly concerning option is ‘Let guest users see other members of this community’ (or what I refer to as ‘View all Users’). Remember when we modified the object permissions directly in the last subsection? This setting will entirely override that for the User object and it’s easily done. To remediate, untick the checkbox and click ‘Save’ at the bottom.
Guest record ownership and their CRUD permissions to objects has now been secured. The final subsection outlines how one may avoid issues relating to record access which arise from Sharing Rules.
Sharing Rules
One of the built-in features of Salesforce is the ability to extend access to records through what are known as ‘Sharing Rules’. What we’re most interested in with relation to these rules are records which have been shared with Guest users specifically. Earlier I explained how to configure default ownership of Guest user created records and migrating ownership of already existing records. If the Sharing Rules within your instance are misconfigured, this default ownership is effectively redundant for the security of your instance.
Navigate to ‘Sharing Settings’ by navigating to it through the Quick Find box. Scroll down to the ‘Other Settings’ section and ensure that the ‘Secure guest user record access’ is enabled:
Once this has been enabled, the organization-wide default for Guest users’ access to objects is set to Private. In order to once again grant any required access that has been lost as a result of this change, a Sharing Rule can be created and assigned to the Guest user on a per object basis. This is done through creating a Rule Type of ‘Guest user access, based on criteria’ and selecting ‘Share with’ in conjunction with the name of the Guest user.
Enablement of this setting also removes the ability for guest users to be a member of public groups or queues, and records can no longer be shared with them via Manual Sharing. Ensure that Guest users are removed from public groups and have any records manually shared with them removed. If you wish for the Guest user to maintain the same level of access to the data they had via Groups / Manual Sharing, simply setup a Sharing Rule instead.
Conclusion & Takeaways
At this point in time, you should now be familiar with the bread and butter of data access permissions in relation to Guest users and objects on Salesforce. Fortunately, the core aspects of each section (without the Guest user specifics) can be applied to other profiles and users. But by no means is this the ‘Malloc Maleficarum’ of Salesforce security. Other important areas of focus that were not touched upon include Assigned Application access, Apex class access, and many more. In addition, do not forget that if your community has self-registration enabled, it is equally as important to secure the permissions associated with the community member profile. Letting a simple ‘signup’ form lead to massively elevated levels of data access would be a tragic irony.
I wish I could say that there are no unintended consequences from following the steps I’ve illustrated, but if that was the case, I wouldn’t have requested that a secure semi-clone of your instance be the guinea pig as opposed to a production environment. If you’re a large enterprise, there’s a possibility that you have multiple instances with potentially several communities belonging to each; containing vast amounts of profiles, users, permission sets, and the like. In those scenarios, manual review is simply neither time efficient nor cost effective.
Instead, I would advise that your organization invest in an SSPM solution that has a deep understanding of Salesforce and other SaaS applications, such as AppOmni. While your org grows and introduces enhancements or further customizations, complexity scales appropriately. This complexity introduces a need for continuous visibility, posture monitoring, and detection capabilities. While I now work at AppOmni, I truly believe that the easiest way to determine whether your organization needs this type of solution is to sign up for AppOmni’s 1 hour risk assessment. It’s a free and expert driven security evaluation, which will identify all of these Guest user related issues and more.