Welcome back to our series on strengthening your Salesforce security where we explore various vulnerabilities and best practices for protecting your Salesforce environment.
Imagine this scenario: A large retail company uses Salesforce to manage customer interactions and has set up an Experience Cloud site for their community of users, including a support forum where customers can post questions and feedback. One day, a user submits a forum post containing a script tag hidden within the comment. This post is saved into Salesforce and later displayed on the forum page accessed by other logged-in users and support staff.
Now, each time the forum page loads, the script executes. This script captures the session tokens of logged-in users and sends them to the attacker. This unauthorized access allows the attacker to impersonate users and support staff, accessing sensitive data and potentially posting unauthorized messages. The company now faces a data breach, operational disruptions, and a significant blow to its reputation.
This example highlights the importance of addressing Cross-Site Scripting (XSS) vulnerabilities in Salesforce. Organizations rely on flexible and accessible cloud-based platforms to manage their operations and data for several reasons, among the top reasons are compliance and security. However, the flexibility and accessibility of cloud platforms, like Salesforce, also expose those organizations to cybersecurity vulnerabilities which threaten their security posture and resiliency. This article is focusing on Cross-Site Scripting (XSS).
XSS is a type of security vulnerability typically found in web applications, and occurs when an attacker sends malicious code, generally in the form of a browser side script, anywhere a web application uses input from a user within the output it generates without validating or encoding it.
Read more here.
Salesforce’s customization capabilities allow companies the ability to extend the platform to meet their many needs. Developers and administrators can introduce new features and interfaces by writing custom code, incorporating third-party integrations, and using tools like Visualforce pages and Lightning Web Components. While these features enhance functionality, they also can open up the platform for potential attacks, including XSS.
The scenario above is just one example, there are different types of XSS to consider that can overlap and co-exist.
- Stored XSS occurs when a malicious script is stored on Salesforce servers, such as in a record field, and later rendered in a browser. Like in our example above.
- Reflected XSS occurs when user input is immediately returned by web applications in error messages or search results without proper HTML escaping.
- DOM-based XSS involves JavaScript that writes data to the Document Object Model (DOM) without proper sanitization.
Each of these types are unique in how they can manipulate our systems, however they are all addressed in similar best practices; Sanitizing Inputs, Encoding Outputs and Leveraging built in features and configurations.
Understanding XSS in Salesforce
The architecture of Salesforce provides us tools like custom fields and Visualforce pages, or the Lightning Framework that allow developers and administrators the ability to create interactive solutions to extend the offerings of the platform, quickly and easily. These tools, when leveraged without security in mind, open up the threat landscape significantly.
In Visualforce pages, we build custom user interfaces or display dynamic content using HTML, JavaScript, and Apex. Within these applications, we see the threat of XSS often.
Like Visualforce, the Lightning Framework helps us create intelligent, interactive and dynamic web applications. However, Salesforce introduced a security architecture that enforces security boundaries between components called Lightning Locker Service. While Lightning Locker reduces the risk of XSS attacks by using elements such as Content Security Policy (CSP) and controls and limiting direct access to the DOM, it does not make Lightning components completely immune to XSS vulnerabilities. Developers and administrators must still follow secure coding practices, and ensure that any third party libraries used to add functionality meet those same standards.
Note: on February 6th, 2024 Salesforce published an article outlining information about Lightning Web Security (LWS) which is a new client-side security architecture for Lightning Components.
The good news is that this technology doesn’t require refactoring of your LWC code because your code already abides by the security practices required by Lightning Locker. Most existing Lightning web components just work in this new architecture.
Even better news is you have the option to refactor your code to let your components take advantage of the new freedoms that this technology enables.
Read more here.
In addition to the customizable nature of the platform, Salesforce’s ability to integrate with a wide range of third party systems is one of its strengths. These integrations enable data sharing across various operational processes and tools, enhancing efficiency and how businesses operate. In most Salesforce implementations we see a wide range of integrations at work, all with varying setups and configurations.
When designing these integrations, it is best practice to plan for aspects such as error handling and data consistency across systems. However, what can sometimes be overlooked are the security implications. Especially when our day to day users are able to build their own integrations to work with their data.
Specifically, developers need to ensure that any data coming into Salesforce from third-party applications is thoroughly validated and sanitized to prevent the possible introduction of malicious scripts.
Apex in Action
In this Apex in Action section I’d like to break down some secure coding practices. We will also dive into Lightning Locker Service to discuss the enforcement of CSP and other configurable security settings often overlooked.
Secure Coding Practices
Encoding
But first, let’s talk about why? When we’re dealing with external data or dynamic user content that is included in page content (HTML or JavaScript), special characters within that input (such as <, >, “, ‘, and &) can be interpreted by a browser as part of the code. This is what leads to the execution of unintended scripts. By encoding these characters, we ensure they are treated as literal text rather than executable code, preventing the possible XSS attack.
In Visualforce, when displaying user generated content in HTML, we need to escape the content to prevent the possible execution of embedded scripts, this controls whether the text output should be escaped for HTML. To do this, we use the escape=”true” (which is the setting default) attribute. This ensures that any special characters are automatically escaped, rendering them as plain text.
This is what it might look like:
<apex:page controller="InputController">
<apex:pageMessages />
<h1>User Input Example</h1>
<!-- Displaying escaped user input -->
<p>Escaped User Input: <apex:outputText value="{!userInput}" escape="true" /></p>
<!-- Displaying raw user input -->
<p>Raa User Input: <apex:outputText value="{!userInput}" escape="false" /></p>
</apex:page>
However, there are specific scenarios where additional encoding methods are going to be necessary. For example, when user input needs to be included in JavaScript code. In order to achieve this we need to employ the use of a method that escapes strings such as the escapeEcmaScript(). These types of methods help us avoid script injections by escaping special characters.
Here’s an example:
InputController:
public with sharing class InputController {
public String userInput { get; set; }
public InputController() {
// Example user input
userInput = '<script>alert("Hello, world!");</script>';
}
// Method to get escaped JavaScript content
public String getEscapedInput() {
return userInput.escapeEcmaScript();
}
}
VF Page:
<apex:page controller="InputController">
<apex:pageMessages />
<h1>User Input Example</h1>
<script type="text/javascript">
// Using escaped user input in JavaScript
var userInput = '{!userInput}';
console.log(userInput);
</script>
</apex:page>
In LWCs this operates differently, since LWCs do not have a built in attribute like escape=true. As we discussed earlier, we will dive into Lightning Locker Service and how to enforce strict CSP to help mitigate XSS attacks in a later section, however with both VF and LWC, sanitization is still necessary.
Sanitizing
Sanitizing is a little bit different than encoding, rather than focus on the output, it ensures that user input is stripped of any harmful characters that could be executed as code before they are saved or rendered. This is important for data that will be stored and later displayed within the application. There are several methods to achieve this, here is one example:
private String sanitizeInput(String input) {
if (String.isBlank(input)) {
return '';
}
// Remove script tags and special characters
String sanitized = input.replaceAll('<', '')
.replaceAll('>', '')
.replaceAll('"', '')
.replaceAll("'", '')
.replaceAll('&', '')
.replaceAll('/', '');
return sanitized;
}
In this example we are passing in the user input to a method which is going to then search for and replace all possible harmful characters with ‘’ returning a clean and sanitized string for the database and rendering.
Configurable Security Settings for LWCs
In Salesforce, CSP can be configured to ensure that only trusted sources are allowed to load and execute content. In a nutshell, CSP restricts the source of content that can be loaded on a page by imposing rules. This is defined within the Trusted Sites settings under Security. These settings tell Salesforce which external resources are trusted and can be used within your Salesforce org.
Salesforce also has configurable settings for Clickjack protection and Cross-Site Request Forgery (CSRF), you may commonly see these notices within your orgs Health Check report.
Clickjack protection prevents bad actors from embedding your Salesforce pages within an iframe on their site, which can trick users into interacting with your site. CSRF protection ensures that requests are intentionally made by authenticated users, preventing attackers from exploiting user sessions to perform unauthorized actions.
Through this article we have talked about different ways that we can protect against XSS attacks. Cross-Site Scripting remains one of the most popular vulnerabilities that I see day to day that can compromise the integrity, confidentiality, and availability of your data.
Safeguarding against XSS in Salesforce involves a combination of input sanitization, output encoding, leveraging built-in security features, understanding different contexts, and performing regular security audits. By implementing the practices and configuration settings we have discussed in this article, you can significantly enhance the security of your Salesforce applications.
A Fast Audit for Enhanced Security
To ensure your Salesforce implementation is fully secure, consider engaging Red Argyle in a comprehensive Fast audit. Our Fast Audit is minimally invasive and can help you proactively identify and mitigate risks, ensuring your Salesforce environment remains secure and resilient against cybersecurity challenges.
This style of audit is designed to provide a high-level overview of your organization’s security posture, offering rapid insights into critical vulnerabilities and areas requiring attention. This expedited evaluation is tailored for organizations seeking immediate, actionable feedback without the depth or breadth of a standard comprehensive security audit.