Showing posts with label code review. Show all posts
Showing posts with label code review. Show all posts

Understanding Cross-Site Scripting and SOQL Vulnerabilities in Salesforce

Salesforce has remained a popular choice for CRM platforms. From customizing workflows to building applications, businesses can seamlessly achieve their goals with this cloud-based platform. What’s more, the extended functionality, like Visualforce pages, Lightning Web Components (LWC), Aura Components, and Apex, aids development for the enterprises significantly. 
 
We saw few vulnerabilities and security controls provided by Salesforce platform in past couple of blogs. We are going to discuss about two more common and severe vulnerabilities - Cross-Site Scripting (XSS) and SOQL Injection in this blog. 

Cross-Site Scripting (XSS) in Salesforce

XSS occurs when an application takes untrusted user input and returns the response containing user input without encoding to the browser. Attackers take this opportunity to run malicious JavaScript in the victim’s browser and extract sensitive information.
 
In Salesforce, XSS can appear in:
  • Visualforce Pages: Using raw {!} expressions without escaping.
  • Aura Components / LWC: Unsafe DOM manipulation or improper attribute use.
  • JS Controllers:  Unvalidated data is passed straight into the user interface.
 
How to Detect XSS in Code
  • Unescaped Output in Visualforce → Flag <apex:outputText value="{!userInput}" escape="false"/> or direct use of {!userInput} without proper encoding
  • Improper aura:unescapedHtml in Aura → Any use of aura:unescapedHtml or dynamic attributes directly rendering user data
  • Direct innerHTML assignment in LWC/JS → Using element.innerHTML = userInput instead of textContent. Moreover, the usage of insecure JavaScript functions such as html(), eval()
  • Input Fields Without Validation → Inputs accepted from users (comments, descriptions, messages) should be validated or sanitized before use
Vulnerable Example in Salesforce
 
Visualforce Page (Vulnerable):
<apex:page controller="XSSExampleController">
       <apex:form>
           <apex:inputText value="{!userInput}" label="Enter your name:"/>
           <apex:commandButton value="Submit" action="{!processInput}"/>
           <br/>
           <!-- Directly rendering user input -->
           <apex:outputText value="{!userInput}" escape="false"/>
       </apex:form>
</apex:page>

Controller:
public class XSSExampleController {
       public String userInput {get; set;}
       public void processInput() {
           // No validation or sanitization here
       }
}

If the attacker enters, <script>alert('XSS Attack!');</script> attack vector it will execute in the victim’s browser. 

Safe Example
 
Visualforce Page (Safe):
<apex:outputText value="{!userInput}" escape="true"/>

By default, escape value is true. 
Or manually encode:
<apex:outputText value="{!HTMLENCODE(userInput)}"/>

In LWC, avoid assigning user input directly to innerHTML/html():

// Vulnerable
element.innerHTML = userInput;

// Safe
element.textContent = userInput;


Impact
By exploiting XSS vulnerability, an attacker can steal user session. Once an attacker gets access to user session, he can perform tasks on behalf of the user which can result in data loss. In other cases, an attacker can redirect user to phishing site or can deface the application.


SOQL Injection in Salesforce 

 
What is SOQL Injection?
SOQL Injection is similar to SQL Injection in traditional applications. This occurs when the untrusted user input is directly combined into a dynamic SOQL query string. Once coupled, the attackers may be able to access unauthorized data or bypass restrictions by manipulating the query. 

How to detect in Code 
When reviewing Salesforce Apex code, focus on how queries are built:
  • Dynamic SOQL with Concatenation → Flag any use of Database.query() or string concatenation (+) with user-supplied input
String q = 'SELECT Id FROM Account WHERE Name = \'' + userInput + '\'';
Database.query(q);   
  • Red flag when user input (e.g., from ApexPages.currentPage().getParameters(), form fields, or API requests) is directly concatenated
String searchKey = ApexPages.currentPage().getParameters().get('search');
String query = 'SELECT Id FROM Contact WHERE Email LIKE \'%' + searchKey + '%\'';
List<Contact> contacts = Database.query(query);

Apex Controller (Vulnerable):
public with sharing class SOQLInjectionExample {

        @AuraEnabled(cacheable=true)
        public static List<Account>searchAccounts(String inputName) {
// VULNERABLE: direct string concatenation
String query = 'SELECT Id, Name FROM Account WHERE Name LIKE \'%' + inputName + '%\'';
             return Database.query(query);       
         }
}

Here, an attacker could supply input like,
test%' OR Account LIKE '
This would alter the query to return all accounts, bypassing intended restrictions.

Secure Code in Apex:
  • Safe queries use bind variables (:variable) instead of concatenation.
String searchKey = ApexPages.currentPage().getParameters().get('search');
List<Contact> contacts = [SELECT Id, Name FROM Account WHERE LIKE :('%' + inputName + '%')];

  • Verify Input Validation and Escaping - even with dynamic queries, Salesforce provides String.escapeSingleQuotes() to neutralize malicious input.
String userInput = ApexPages.currentPage().getParameters().get('name');
userInput = String.escapeSingleQuotes(userInput);
String query = 'SELECT Id FROM Account WHERE Name = \'' + userInput + '\'';
List<Account> accList = Database.query(query);



Impact
Like any SQL Injection, a successful exploitation of SOQL Injection can result in data loss which will result in compliance violation and can cause damage to customer trust and reputation of the company.

 

Conclusion

Both XSS and SOQL Injection are serious vulnerabilities of Salesforce applications resulting from improper handling of user input. XSS works on the client side. This includes how data is rendered. Attackers use this to execute scripts within the user's browser. SOQL Injection works on the server side, allowing attackers to access Salesforce data by using an insecure query. We saw different vulnerabilities from the code perspective in these series of blogs. During the next blog, we will understand how a configuration review can help secure salesforce applications with a real-world example of one of our engagements. 

Understanding CRUD/FLS and Sharing Violation Vulnerabilities in Salesforce

Introduction

In the previous blog, we saw some of the vulnerabilities which we observe during Salesforce review. In this blog, we understand some of the security features provided by Salesforce platform and how can we leverage it to write secure code along with the method to detect insecure implementation. 
Salesforce requires developers to check object-level, field-level, and record-level permissions in their code.  Failure in addressing these issues could result in causing CRUD/FLS vulnerabilities, which ultimately can expose sensitive data to unauthorized users. 

CRUD/FLS Violation Vulnerability

What is CRUD/FLS?
CRUD (Create, Read, Update, Delete) terms whether a user is authorized to perform operations on an object like an account, contact, or opportunity.  FLS (Field-Level Security) determines whether a user can view or modify desired fields within an object, such as the Salary field in the Employee object.  Object (CRUD) and Field Level Security (FLS) are configured on profiles and permission sets and can be used to restrict access to standard and custom objects and individual fields. Force.com developers should design their applications to enforce the organization's CRUD and FLS settings on both standard and custom objects, and to gracefully degrade if a user's access has been restricted.

The CRUD/FLS violation is typically triggered when the Apex code fails to verify the user authorization before performing DML operations, querying objects, or fielding directly.


Insecure Apex Code Example

public class EmployeeController {
       @AuraEnabled 
       public List<Employee__c> getEmployees() {
           // No check for object-level or field-level security
           return [SELECT Id, Name, Salary__c FROM Employee__c];
       }

        @AuraEnabled 
        public void createEmployee(String name, Decimal salary) {
           // No check for Create access
           Employee__c emp = new Employee__c(Name = name, Salary__c = salary);
           insert emp;
       }
}


In this example:

  • A user without “View Salary” field access can still retrieve salary data.
  • A user without “Create Employee” permission can still insert a new record.

How to Detect in Code: 

During a manual code review, look for:

  • SOQL queries that directly select fields
  • DML statements (insert, update, delete, and upsert) executed without permission checks
  • Missing calls to Salesforce’s schema-based security methods:
  • Schema.sObjectType.ObjectName.isAccessible()
  • Schema.sObjectType.ObjectName.isCreateable()
  • Schema.sObjectType.ObjectName.isUpdateable()
  • Schema.sObjectType.ObjectName.isDeletable()
  • Schema.sObjectType.ObjectName.fields.FieldName.isAccessible()

 How to Fix in Code:
To rectify the problem, the code should effectively perform CRUD/FLS enforcement on both the object and the fields of the object. This will help the developer utilize various mechanisms based on the requirements and context of the application.

User Mode Execution – Apex code runs in System mode by default, which means that code will be executed with excessive permissions  regardless of the current user’s permissions. By allowing the User mode object and field-level permissions of the current user, the DML operation is performed. 
// Insert record with user-level permission checks
Database.SaveResult result = Database.insert (new Opportunity (Name = 'Big Deal', CloseDate = Date.today(), StageName = 'Prospecting'),
AccessLevel.USER_MODE
);


Traditional CRUD/FLS Enforcement Checks – isAccessible, isCreateable, isUpdateable, isDeleteable methods 
 

With Security Enforced – User’s object/field permissions are enforced by appending the “WITH SECURITY_ENFORCED” keyword in the SOQL query.  This keyword is only allowed to check permissions for read operations. 

// Enforces both CRUD and FLS at query time
List<Contact> cons = [
       SELECT Id, FirstName, LastName, Email
           FROM Contact
           WITH SECURITY_ENFORCED
];

 Note:  When the “WITH SECURITY_ENFORCED” keyword is used, the API version should be 48.0 or later. Additionally, this keyword does not support traversal of a polymorphic field’s relationship and TYPEOF expressions with an ELSE clause in queries.

Using stripInaccessible() – The stripInaccessible() method helps to enforce CRUD/FLS by removing the fields from query and subquery that users do not have access to.  This method  checks user’s access based on their field-level-security  for a specified operation – create, read, update, and upsert. 

List<Account> accounts =  [SELECT Id, Name, Phone, Email FROM Account];
// Strip fields that are not readable
SObjectAccessDecision decision = Security.stripInaccessible (AccessType.READABLE, accounts);
List<Account> sanitizedRecords = (List<Account>) decision.getRecords();



Impact
CRUD and FLS always need to be enforced for create, read, update, and delete operations on standard objects. In the vast majority of cases, CRUD and FLS should also be enforced on custom objects and fields. Any application performing creates/updates/deletes in Apex code, passing data types other than SObjects to VisualForce pages, using Apex web services or the @AuraEnabled” notation should be checked that it is calling the appropriate access control functions.

In the past, due to incorrect implementation of CRUS/FLS in application, we have observed that an employee can gain unauthorized access to personnel data or payroll information of everyone in the organization OR in customer support applications, weak CRUD checks allow agents to modify or delete records beyond their assigned accounts.

There is business and compliance risks involved when the proper enforcement of CRUS/FLS permissions are not in place. Such weaknesses can ultimately result in data breaches, regulatory penalties, financial loss, and reputational damage. 
 

Sharing Violation Vulnerability

What is Sharing in Salesforce?
Salesforce enforces record-level security through sharing rules,  determining which records a user can access. Apex classes run in the following modes:

  • With Sharing – Enforces record-level sharing rules of the logged-in user.
  • Without Sharing – Ignores record-level sharing rules and runs in system context, potentially exposing all records. A sharing violation occurs whenever Apex code runs without respecting the current user's record-level sharing rules.
  • Inherited Sharing – Declaring class will enforce (inherit) the sharing rules of the calling class.

 

Insecure Apex Code Example
public without sharing class AccountController {
       @AuraEnabled
       public List<Account> getAccounts() {
           // Returns all accounts, even those the user should not see
           if (Schema.sObjectType. Revenue__c.isAccessible() &&
               Schema.sObjectType. Revenue__c.fields.Name.isAccessible()) {
           return [SELECT Id, Name, Revenue__c FROM Account];
           }
       }
}


In this example, even if sharing rules restrict the user to accounts in their region, the class will return all accounts in the system. Even if CRUD-FLS permissions are checked before performing the query, it will still return all accounts. This is because CRUD-FLS permissions ensure field-level security, while sharing rules ensure record-level access.


How to Detect in Code
During a code review, look for:

  • Classes declared as without sharing.
  • Classes with no explicit sharing declaration (default is without sharing if not specified in a class used as an entry point).
  • DML operations and Queries returning sensitive records without additional filtering.


Secure Apex Code Example
public with sharing class AccountController {
       @AuraEnabled
       public List<Account> getAccounts() {
       if (Schema.sObjectType. Revenue__c.isAccessible() &&
               Schema.sObjectType. Revenue__c.fields.Name.isAccessible()) {
                  return [SELECT Id, Name, Revenue__c FROM Account];
           }
       }
}


If a class must operate in system mode (e.g., batch jobs, admin tasks), developers should:

  • Explicitly justify the use of without sharing.
  • Apply programmatic filters to enforce access (e.g., filtering records based on owner or custom sharing logic).

Impact

The Force.com platform makes extensive use of data sharing rules. Each object can have unique permissions for which users and profiles can read, create, edit, and delete. These restrictions are enforced when using all standard controllers. When using a custom Apex class, the built-in profile permissions and field-level security restrictions are not respected during execution. The default behaviour is that an apex class has the ability to read and update all data within the organization. Because these rules are not enforced, developers who use Apex must take care that they do not inadvertently expose sensitive data that would normally be hidden from users by profile-based permissions, field-level security, or organization-wide defaults. This is particularly true for Visualforce pages.

In the past, due to insecure implementation of sharing, we have observed vulnerabilities like, sharing violation exposes medical records, insurance details, or financial information to unauthorized staff, resulting in HIPAA, GDPR, or PCI DSS violations OR in sales environments, sales executive might get access to opportunities in another territory OR a support agent gets an access to cases belonging to another client.  

In regulated settings, this could allow unauthorized users to get access to personal financial and healthcare information, resulting in privacy breaches, regulatory non-compliance, and fines. When we have sharing violations, they are more than just a compliance issue. They create a lack of trust among the partners. They also disrupt the flow of business activities. Even more, they expose competitive data. Finally, all this leads to customers losing their trust and some reputational harm.

Conclusion

Salesforce platform provides CRUS/FLS and sharing implementation as a key feature to implement security and permissions however the most common vulnerabilities are inappropriate implementation of CRUD/FLS and Sharing Violation in the Salesforce application. To mitigate these risks, developers should take care of the below: -
  • Before executing any query or DML operation, always check the CRUD and FLS permissions.
  • Classes should be declared “with sharing” by default unless you have a good reason to bypass sharing rules.
  • Do manual code reviews along with automated scans to ensure that the security controls are implemented.
In the next blog, we will understand XSS and SOQL vulnerabilities in Salesforce platform.

Key Salesforce Vulnerabilities Beyond the OWASP Top 10

We had discussed in our previous blog post on why it is important to review applications developed in salesforce platform. In this one, we will discuss the common vulnerabilities we observe along with the method to detect the same in the code. 

1.     Open Redirects

An attacker uses an HTTP parameter that contains a URL value to cause the web application to redirect the request to this specified URL, which may be outside the application domain. An attacker sets up a phishing website in order to obtain a user’s login credentials.  The attacker then uses the redirection capacity to provide links that appear to point to a legitimate application domain, but actually point to a malicious page to capture login credentials. The stolen user credentials can then be used to log-in to legitimate web sites. Attackers can exploit this to redirect victims from trusted Salesforce domains to malicious websites.

How to Detect in Code

  • Look for use of PageReference in Apex code where the URL is directly consumed by user input without performing validation – 

String target = ApexPages.currentPage().getParameters().get('url');
return new PageReference(target); // ❌ Vulnerable

  • Another method is to check JavaScript in Visualforce, LWC, or Aura where navigation functions accept URLs without performing any validation.

Impact 
Attackers can use open redirects to launch phishing attacks, steal Salesforce credentials or trick users into downloading malware. Since the redirect originates from a trusted Salesforce domain, end users are far more likely to trust the malicious destination and become victim of this attack.

2.     Hardcoded Secrets in Apex / Insecure Storage of Sensitive Data

"Hardcoded Secrets" represents a critical security concern where sensitive information, such as passwords, API keys, OAuth tokens, cryptographic secrets or credentials, is embedded directly into an application's source code or configuration files specially in Apex classes, custom settings, or custom metadata. These secrets are often visible to anyone with access to the application's codebase, and they pose a significant risk.

 Many developers make the mistake of defining custom object fields as "public". This makes their secret values available in plain text. As an example, the metadata snippet shown below marks the API key field as visible.

How to Detect in Code

  • Hardcoded Secrets in Apex Code - Search for API keys, access tokens, passwords, or cryptographic keys directly assigned to variables. Check for sensitive constants declared in classes. Moreover, Search for suspicious keywords like "password", "apikey", "secret", "token".

// Insecure: Hardcoded API key
String apiKey = 'ABCD1234SECRETKEY';

  • Sensitive Data in Custom Objects or Metadata - Inspect custom object definitions (.object files in metadata). Look for <visibility>Public</visibility> in sensitive fields such as apiKey__c, secret__c, or token__c.


Insecure code in Object file 

<fields>
       <fullName>apiKey__c</fullName>
       <type>Text</type>
</fields>
<visibility>Public</visibility>


Secure Code in Object file

<fields>
       <fullName>apiKey__c</fullName>
       <type>Text</type>
</fields>
<visibility>Protected</visibility>


Impact
Hard-coded secrets are vulnerable to unauthorized access, exposure, and misuse, potentially leading to data breaches, security incidents, and compromised user accounts. In case of salesforce, if an API key meant for admins is leaked using one of the above mentioned method, an attacker can use the key to communicate with Salesforce and/or another external service and take data out of provisioned channels.

3.     Sensitive Data in Debug Logs

Salesforce allows developer to write information in logs using System.debug(). A privileged user i.e. administrator is able to access logs and can gain access to sensitive information i.e. PII data, financial records, SSN or PHI if logged.
How to Detect in Code

  • Review System.debug() statements in Apex for exposure of fields like SSNs, payment details, or authentication tokens.

System.debug('User password is: ' + password); //  Never log this


Impact
The risk of unauthorized disclosure increases if the logs are exported or shared. This also violates compliance requirements of GDPR, HIPAA, PCI-DSS.

4.     Wide OAuth Scope

Managing the overall access of the application is also very crucial. Excessively exposed integrations with apps or OAuth tokens featuring broad scopes, like full or refresh_token, put the app at risk by providing more access than necessary. 

How to Detect in Configurations/Code

  • Review OAuth connected app definitions and check requested scopes.
  • Look for integrations where the full scope is used instead of narrowly defined scopes.

Impact
Large volumes of Salesforce data could be read, modified, or even deleted by overly permissive OAuth tokens.

5. Insecure CORS Configuration

CORS is implemented to limit which other sites can request Salesforce’s resources. When configured to allow * (any origin) or unnecessary domains, it opens the door of cross domain attacks.

How to Detect in Configurations

  • Check Salesforce CORS settings under Setup → CORS.
  • Look for entries that allow overly broad or untrusted origins.


Impact
If CORS is not correctly configured, an attacker can create a site which can lead to Cross-Site Request Forgery (CSRF) or Cross-Site Scripting (XSS) attacks, where an attacker can exploit the permissive CORS policy to perform malicious actions on behalf of a user.

Conclusion

Salesforce apps can be exploited not only by generic web vulnerabilities but also by platform-specific misconfigurations or coding practices. Phishing is made easier by open redirection, and hardcoded secrets may expose the integrations. What’s more, sensitive data found in logs may fail compliance, wide scopes with OAuth may create unnecessary risk, and insecure CORS may lead to cross-origin attacks. These are just some of the examples but list is long…  Organizations can greatly improve the security of their Salesforce applications by implementing the principle of least privilege, enforcing secure coding practices, and conducting regular manual code reviews. In the next blog, we will learn how we can leverage platform features i.e. CRUD/FLS and Sharing Violation to write secure applications.

Salesforce Applications: Importance of Performing a Security Review

Salesforce has remained a top choice for enterprises when it comes to building applications. Thanks to its flexibility, scalability, and rich set of features, organizations can build applications tailored to their workflows seamlessly. But then again, a question arises: Do I need to worry about security if I write the application on salesforce platform?

A common misconception that the app is secure often comes up when businesses develop apps or customizations on the platform. And the answer is, “Yes” (reasons for the same are well described in another blog entry under “The Importance of Security Reviews for Applications on Enterprise Platforms” Even though Salesforce offers a robust and secure platform, it is your responsibility to secure your own custom code, configurations, and integrations.

Salesforce Application Overview

The applications built with Salesforce are normally structured across two core layers with a unique purpose. However, these layers also tend to introduce potential security considerations. 

  • Client-Side (User Interface Layer): As the name implies, the client-side layer that can be implemented in many frameworks is responsible for managing user interactions with the application.  Visualforce Pages is an older, page-based framework for creating user interfaces with business logic embedded inside. Aura Components and interface creation are great tools, but the mishandling of attributes and methods can pose security-related issues. Lightning Web Components (LWC) represent Salesforce’s modern, standards-based framework. In LWC, web components are used to enhance performance. Moreover, these components also offer strong security.  
  • Server-Side (Business Logic Layer): The application’s business logic, data processing are typically implemented on server-side layer. Salesforce programming language is Apex which is similar to Java. Apex code is mainly used for database operations, process and business rules implementation. Even though Apex code provides wide range of capabilities to build a business logic, the use of improper and unsafe coding at this layer may lead to serious security risks.  These layers definitely make the Salesforce applications flexible and scalable. However, they create multiple entry points that can cause security vulnerabilities if not checked or secured properly.

The Significance of Security Reviews

Salesforce undergoes rigorous security testing and compliance. Based on the requirements, either you, your team, or a partner develops custom apps, Apex code, Visualforce pages, Lightning, and integrations. If there are any flaws in any of the layers, attackers could gain access to Salesforce org, go through private client data, or raise compliance issues.

In other words, Salesforce ensures the platform security, while the application team must ensure the security of what they have built on the platform.

Choosing the Right Salesforce Testing Method: Black-Box vs. White-Box

When reviewing a Salesforce app, one can choose between - 

  • Black-box testing is the process of when the tools simulate an attack as if they were an outside attacker, without any prior knowledge. This helps to find issues such as injection points, misconfigured endpoints, and authentication problems.
  • White-box testing refers to the practice whereby the tester has full access to the code/configuration/metadata. This technique often reveals logical errors, dangerous storage, bad sharing policies, and API misuse that black-box analysis wouldn’t usually detect.

A combination of the two is the best strategy. The internal aspect of the configuration and logic is secured as a result of the white-box test. The black-box test verifies the attack surface externally.

Security Concerns to Take into Account in Salesforce

Understanding specific risks that go beyond those of conventional web applications is necessary when scoping a Salesforce security review. Here is the list of some of them - 

  • CRUD/FLS Bypass – if Create, Read, Update, Delete, or Field-Level Security checks are not performed properly, it may leak sensitive data.
  • Insecure Sharing Settings/Sharing Violation – Access to restricted records can be unintentionally shared if the code is running without sharing. 
  • SOQL Injection –. If user inputs are directly passed in SOQL queries (without any processing or validation) it can lead to data leakage due to SOQL query manipulation. 
  • Cross-Site Scripting (XSS) –   Fail to validate user inputs in Visualforce, Aura, or LWC can lead to XSS attack.
  • Open Redirects – Phishing or session hijacking can become very common if the JavaScript functions and PageReference redirections are used without validation.
  • Hardcoded Secrets in Apex / Insecure Storage of Sensitive Data – Credentials, tokens or sensitive information are stored in plaintext as part of the code or in configuration or database.
  • Sensitive Data in Debug Logs – if System.debug() is set, an administrator can get access to sensitive data by accessing logs of the application. 
  • Wide OAuth Scope – While integrating Salesforce with third party applications, typically OAuth protocol is used. In the implementation of OAuth, if OAuth scope is set to full instead of necessary requirement, it will allow third party applications to access excessive data and functionality of Salesforce. 
  • Insecure CORS Configuration – One can exploit weak implementation of CORS to make calls to Salesforce APIs.
  • Overexposed APIs – Sensitive data can be exposed if the application fails to restrict appropriate use of Salesforce APIs.

The Significance of Configuration Review and Permissions

Manual pen testing and code review go a long way in ensuring that security parameters are up to the mark but there are multiple permission settings and incorrectly configured security controls that can compromise even the most secure code. Examining Salesforce's permission model is just as crucial as running code tests:

  • Profiles and Permission Sets – Make sure users only have access to what is require.
  • Role Hierarchy and Sharing Rules – Avoid exposing too many private documents.
  • Field-Level Security (FLS) – Prevent unauthorized users from reading or altering sensitive fields.

Misconfigurations in these areas are one of the most common sources of breaches in Salesforce environments.

Conclusion

In conclusion, Salesforce platform provides a secure foundation, but the additional layers, functionalities and customization on the platform need to be reviewed to make sure that the security controls provided by Salesforce platforms are implemented correctly. To build a secure application, the focus of the review should be on platform specific vulnerabilities and use of secure coding best practices along with the classic web application vulnerabilities.  The combination of black-box, white-box along with deeper permission and configuration review will make sure that the application is secure. 

We are going to write about the key vulnerabilities we normally discover while performing salesforce security review in our next entry. 

Performing Security Code Review for Salesforce Commerce Cloud Application


Salesforce Commerce Cloud (SFCC), formerly known as Demandware, is a robust cloud platform tailored for building B2C e-commerce solutions. It offers a reference architecture, the Storefront Reference Architecture (SFRA), which serves as a foundational framework for website design. SFRA is carefully designed to act as a blueprint for developing custom storefronts. Given your familiarity with this platform, we will forego an extended introduction to Commerce Cloud. Instead, let's review some fundamental concepts before proceeding to the code review.

Access Levels
The platform offers -

  • Developer Access: For users involved in the development of storefront applications, this access level permits the creation of new sites or applications and the deployment of associated code.
  • Administrator Access: Primarily used for managing global settings across all storefront applications within the SFCC system. This level also enables "Merchant Level Access".
  • Merchant Level Access: Allowing users to manage site data (import/export), content libraries, customer lists, products, and marketing campaigns.

SFRA Architecture
SFRA typically includes an "app_storefront_base" cartridge and a server module. These components can be used with overlay plugin cartridges, LINK cartridges, and custom cartridges to create a cartridge stack for layering functionalities. A typical cartridge stack might look like this:

Source: https://developer.salesforce.com/

SFRA employs a variant of the Model-View-Controller (MVC) architecture. In this setup:

  1. Controllers handle user input, create ViewModels, and render pages.
  2. ViewModels request data from B2C Commerce, convert B2C Commerce Script API objects into pure JSON objects, and apply business logic.

The "app_storefront_base" cartridge includes various models that utilize the B2C Commerce Script API to retrieve data necessary for application functionality. These models then construct JSON objects, which are used to render templates.

In SFRA, defining an endpoint relies on the controller's filename and the routes specified within it. The server module registers these routes, mapping URLs to the corresponding code executed when B2C Commerce detects the URL. Additionally, the server module provides objects that contain data from HTTP requests and responses, including session objects.


Cartridge
In B2C Commerce, a "cartridge" serves as a modular package for organizing and deploying code, designed to encapsulate both generic and application-specific business functionalities. A cartridge may include controllers (server-side code where business logic is implemented), templates, scripts, form definitions, static content (such as images, CSS files, and client-side JavaScript files), and WSDL files. Typical base cartridge architecture:

Source: https://developer.salesforce.com/

SFCC Security
One of the key advantages of using platform-built applications is the inherent security provided by the platform. However, it is essential to ensure that configurations enhancing the security of the code are properly applied during implementation. To broadly review the security of a Salesforce Commerce Cloud application, consider the following pointers:


Encryption/Cryptography
In Salesforce, including B2C Commerce, the "dw.crypto" package is commonly used to enable developers to securely encrypt, sign, and generate cryptographically strong tokens and secure random identifiers. It is crucial to review the usage of classes within this package to ensure they meet security standards. For instance, the following classes in "dw.crypto" are considered secure: -

  1. Cipher - Provides access to encryption and decryption services using various algorithms.
  2. Encoding - Manages several common character encodings.
  3. SecureRandom - Offers a cryptographically strong random number generator (RNG).

However, the below classes suggest the use of deprecated ciphers and algorithms, and may introduce vulnerabilities: -

  1. WeakCipher
  2. WeakSignature
  3. WeakMac
  4. WeakMessageDiget

Declarative Security via HTTP Headers 

Certain HTTP headers serve as directives that configure security defenses in browsers. In B2C applications, these headers need to be configured appropriately using specific functions or files. HTTP headers can be set through two methods: -

  1. Using the "addHttpHeader()" method on the Response object.
  2. Using the "httpHeadersConf.json" file to automatically set HTTP response headers for all responses.

To ensure robust security, review the code to confirm the presence of important response headers such as Strict-Transport-Security, X-Frame-Options, and Content-Security-Policy etc.
 

Cross-Site Scripting / HTML Injection
B2C Commerce utilizes Internet Store Markup Language (ISML) templates to generate dynamic storefront pages. These templates consist of standard HTML markup, ISML tags, and script expressions. ISML templates offer two primary methods to print variable values: -

  1. Using "${...}": Replace the ellipsis with the variable you want to display.
  2. Using the "<isprint>" tag: This tag also outputs variable values.

When reviewing .isml files, it is crucial to examine the usage of these tags to identify potential vulnerabilities such as Cross-Site Scripting (XSS) or HTML Injection. These vulnerabilities allow attackers to inject malicious client-side scripts into webpages viewed by users. Example of vulnerable code: -

Script Injection
Server Script Injection (Remote Code Execution) occurs when attacker-injected data or code is executed on the server within a privileged context. This vulnerability typically arises when a script interprets part or all of unsafe or untrusted data input as executable code.
The "eval" method is a common vector for this type of vulnerability, as it executes a string as a script expression. To identify potential risks, review the code for the use of the global method "eval(string)", particularly where the string value is derived from user input.
 

Data Validation
In addition to the aforementioned security checks, it is crucial to validate all user input to prevent vulnerabilities. This can be achieved through functions like "Allowlisting" (whitelisting) and "Blocklisting" (blacklisting). Review these functions to ensure proper input and output validations and to verify how security measures are implemented around them.
 

Cross-Site Request Forgery
Salesforce B2C Commerce offers CSRF protection through the dw.web.CSRFProtection package, which includes the following methods: -

  1. getTokenName(): Returns the expected parameter name (as a string) associated with the CSRF token.
  2. generateToken(): Securely generates a unique token string for the logged-in user for each call.
  3. validateRequest(): Validates the CSRF token in the user's current request, ensuring it was generated for the logged-in user within the last 60 minutes.

Review the code to ensure that these methods are used for all sensitive business functions to protect against CSRF attacks.
 

Storage of Secrets
When building a storefront application, it is crucial to manage sensitive information such as usernames, passwords, API tokens, session identifiers, and encryption keys properly. To prevent leakage of this information, Salesforce B2C Commerce provides several mechanisms for protection: -

  1. Service Credentials: These can be accessed through the "dw.svc.ServiceCredential" object in the B2C Commerce API. Ensure that service credentials are never written to logs or included in any requests.
  2. Private Keys: Accessible through the script API using the "CertificateRef" and "KeyRef" classes. Utilize these classes to manage private keys securely.
  3. Custom Object Attributes: Customize attributes and their properties to use the type "PASSWORD" for storing secrets. This helps ensure that sensitive information is handled securely.

Review the code to verify that all secrets are stored using these methods and are not exposed or mishandled.
 

Authentication & Authorization
To ensure that business functions are carried out with appropriate privileges, developers can utilize certain pre-defined functions in Salesforce B2C Commerce: -

  1. userLoggedIn: This middleware capability checks whether the request is from an authenticated user.
  2. validateLoggedIn: This function verifies that the user is authenticated to invoke a particular function.
  3. validateLoggedInAjax: This function ensures that the user is authenticated for AJAX requests.

Review the code to confirm that these functions are used appropriately for any CRUD operations. Additionally, ensure that the code includes proper session validation checks for user permissions related to each action.
 

Redirection Attacks
In general, redirect locations should be set from the server side to prevent attackers from exploiting user-injected data to redirect users to malicious websites designed to steal information. To validate this, review the code for any instances where user input might be directly or indirectly sent to: -

  1. "<isredirect>" element: Used in ISML templates for redirecting.
  2. "dw.system.Response.redirect" object: Utilized to handle redirects in the script.

 

Supply Chain Security
The platform allows the use of various software sources through uploads, external linking, and static resources. However, this introduces the risk of including unwanted or insecure libraries in the storefront code. For SFRA implementations, ensure that the "addJs" and "addCss" helper methods use the integrity hash as an optional secondary argument to verify the integrity of the resources being added.
 

Secure Logging
Salesforce B2C Commerce logs are securely stored and accessible only to users with developer and administrator access. These logs can be accessed via the web interface or over WebDAV. To ensure the security of sensitive information, review the code to confirm that sensitive data such as keys, secrets, access tokens, and passwords are not logged. This is particularly important when using the "Logger" class. Ensure that sensitive information is not passed to any logging functions ("info", "debug", "warning") within the "Logger" class.
 

Business Logic Issues
Business logic issues can arise from various factors, such as excessive information revealed in responses or decisions based on client-side input. When reviewing SFCC code for logical vulnerabilities, focus on the following areas: -

  1. Reward Points Manipulation: In applications that add reward points based on purchases, ensure that the system validates the order number against the user and enforces that rewards are added only once per order. Rewards should also be deducted if an order is canceled or an item is returned. Failure to do so can allow users to manipulate reward points by passing arbitrary values as the order number.
  2. Price Manipulation: When submitting or confirming an order, verify that the final price of the product is calculated on the server side and not based solely on client-supplied values. This prevents users from purchasing products at lower prices by manipulating request data.
  3. Payment Processing: Since applications often leverage third-party payment gateways, ensure that calls to these gateways are made from the server side. If the client side handles payment processing, users might change order values. Review the logic to confirm that payment validation and processing occur server-side to prevent manipulation.
  4. Account Takeover: For password reset functionality, ensure that reset tokens are not sent in responses, that tokens cannot be reused, and that complex passwords are enforced. Avoid sending usernames from the client side for password resets to reduce the risk of account takeover.

Review the code for validation logic in each business function to uncover any exploitable scenarios resulting from missing or improper validations.
 

In a Nutshell
The above points highlight that, despite the robust security controls provided by the B2C platform, poor coding practices can undermine these protections and introduce security vulnerabilities into the application. It is essential not to rely solely on platform security features but also to conduct a thorough secure code review to identify and address potential issues in the implementation.
 

Useful Links

  • https://developer.salesforce.com/docs/commerce/sfra/guide/b2c-sfra-features-and-comps.html
  • https://developer.salesforce.com/docs/commerce/b2c-commerce/guide/b2c-cartridges.html
  • https://osapishchuk.medium.com/how-to-understand-salesforce-commerce-cloud-78d71f1016de
  • https://help.salesforce.com/s/articleView?id=cc.b2c_security_best_practices_for_developers.htm&type=5

Article by Maunik Shah & Krishna Choksi


Performing Secure Code Review of R Code – A Beginner’s Guide

Background
R is a programming language primarily used for statistical computing and graphical presentation to analyze and visualize data. R is an interpreted language, meaning R programs are not pre-compiled but executed by the R interpreter at runtime. An R file is a script written in the R programming language and saved with the .R file extension.

R language - Ecosystem
Comprehensive R Archive Network (CRAN)
CRAN is R's central software repository, supported by the R Foundation. It is an archive of the latest and previous versions of the R distribution, documentation, and contributed R packages.

Posit – Shiny
Shiny is an R package used to build interactive web applications that execute R language code on the back-end. It enables users to host standalone applications on a webpage, embed interactive charts in R Markdown documents, and build dashboards.

OSS Index

OSS Index is a free catalogue of open source components and scanning tools developed by Sonatype. It helps developers identify open source dependencies, known publicly disclosed vulnerabilities, understand risk, and keep their software secure. The vulnerability data is derived from public sources and does not include human-curated intelligence or expert remediation guidance.

Shiny Applications
A typical web application built using the Shiny package runs the `shinyApp(ui, server)` object. The `ui.R` and `server.R` files contain the code for the client-side and server-side, respectively, which makes up the major logic and code for the application.


 

 

 

R Markdown Files
Another important file type used in applications developed using R is the `.Rmd` file, which is an R Markdown file. It is a specific type of file format designed to produce documents that include both code and text. These files are typically used to generate report files for the results in formats like DOCX, HTML, and PDF.

Secure code review guidelines 

Get background information

  • Obtain a brief overview of the application's purpose
  • Understand the feature list
  • Identify the targeted audience and deployment environment


Assess Potential Vulnerabilities
R is a statistical programming language primarily used for domain-specific application development. Based on the application details, try to gauge what security vulnerabilities the code may be susceptible to.

Understand Code Structure
Examine how the code handles user input, imports and exports data file, manages configurations, processes data, makes external/third-party calls, utilizes libraries/packages, and generates the user interface.

Check for Vulnerable Packages

  • \Packages are typically listed at the beginning of .R files
  • Package versions can be found in the package_list.csv file
  • If the package list file is not available, installed packages and versions can be found using the following command:
  • Vulnerabilities for R language-based packages can be found on the OSS Index
  • The `oysteR` package is an R interface to the OSS Index that allows users to scan their installed R packages


HTTP Requests
Look for HTTP requests from the code files. The `httr` package is commonly used to make HTTP requests from R language code. Check the sensitivity of the data sent in the HTTP request, if applicable.

User Input Sanitization
Trace the input data received from the user interface
Ensure that input data is validated, escaped, and sanitized using blacklisting or whitelisting approaches
For file imports, check that the file data is properly sanitized before consuming it in the program logic
Various functions can be used to search for specific characters and/or patterns in R, such as `gsub`, `grepl`, `str_replace`, and `str_replace_all` from the `stringr` package

Hardcoded Secrets
Check for hardcoded secrets like passwords, keys, or tokens in the code.

Built-in Security Features
R comes with a variety of built-in security features that can help protect your software. Here are a few key features:

  • Secure Password Storage: R provides the `bcrypt` package for secure password hashing
  • Secure Communication: The `openssl` package in R can be used to encrypt communication, ensuring data confidentiality and integrity
  • Data Anonymization: R's `sdcMicro` package provides methods for anonymizing data, a key aspect of privacy preservation

Common security vulnerabilities in R code
The most common security vulnerabilities in R code primarily revolve around the handling of data serialization and deserialization, particularly with RDS (R Data Serialization) files. Here are some of the common vulnerabilities observed:

Arbitrary Code Execution

Recent findings have highlighted a critical vulnerability, which allows for arbitrary code execution through the deserialization of untrusted RDS files. This vulnerability exploits R's lazy evaluation and promise objects, enabling attackers to craft malicious RDS files that execute arbitrary code when loaded. This poses a significant risk, especially in environments where R packages are shared among developers and data scientists.

Supply Chain Attacks
The nature of R's package management system, particularly with repositories like CRAN, makes it susceptible to supply chain attacks. An attacker can overwrite legitimate R packages with malicious versions containing harmful code. When users load these compromised packages, the malicious code is executed, potentially leading to system compromise.

Input Validation Issues
Like many programming languages, R is vulnerable to injection attacks if user inputs are not properly validated. This includes risks associated with SQL injection and command injection, especially when R is used to interact with databases or execute system commands.

Lack of Access Controls
R applications often lack robust access control mechanisms, which can lead to unauthorized access to sensitive data or functionalities. Ensuring that proper authentication and authorization checks are in place is essential to mitigate this vulnerability.

Insecure Data Handling

Improper handling of sensitive data, such as failing to encrypt data at rest or in transit, can expose applications to data breaches. It is crucial to implement strong encryption practices when dealing with sensitive information in R.

Article by Maunik Shah & Krishna Choksi

Securing Legacy SaaS Accounting Software: A Comprehensive Review and Remediation

Client Overview
A rapidly growing company offering accounting software as a SaaS expanded its platform by adding features such as custom reports, cloud integrations, and API support. The platform, however, was built on legacy PHP code, and the traditional development approach, along with complex customizations, led to numerous security issues that were difficult to prioritize and resolve.

Challenges

  • The platform was built on outdated PHP code, which made it prone to security vulnerabilities.
  • The rapid addition of features introduced multiple layers of complexity, increasing the risk of security flaws.
  • The existing development process lacked modern security practices, resulting in a backlog of security issues that were hard to address and prioritize.
  • The company struggled to identify and fix security vulnerabilities efficiently, especially those related to input validation, output encoding, injections, and file uploads.


Blueinfy's Approach
To address these challenges, Blueinfy proposed a combined manual black-box testing and code review approach using their in-house tools. This approach was tailored to the specific needs of the legacy PHP environment and focused on identifying and resolving critical security issues.

1. Comprehensive Product Understanding
Blueinfy’s team took the time to thoroughly understand the product, its architecture, and the existing security measures in place. This deep understanding allowed them to tailor their approach to the unique challenges of the platform.
2. Manual Black-Box Testing
The team conducted manual black-box penetration testing to simulate real-world attack scenarios. This testing was aimed at uncovering security vulnerabilities without prior knowledge of the internal code, focusing on areas like input validation, output encoding, and file uploads.
3. In-Depth Code Review
Parallel to the black-box testing, Blueinfy’s code review team analyzed the PHP codebase to trace the root causes of the issues identified. The review focused on common security concerns such as SQL injection, cross-site scripting (XSS), and improper data handling.
4. Correlation of Findings
The code review team correlated the results from the black-box tests with the underlying code issues, identifying common root causes and providing targeted recommendations for remediation.

Results
The combined approach led to the identification of several high-severity vulnerabilities that were previously overlooked or not fully understood. Blueinfy delivered a detailed report that highlighted these findings and provided clear, actionable recommendations for fixing them.

  • The report prioritized the most critical security issues, enabling the client to focus on what mattered most.
  • Blueinfy’s recommendations were tailored to the legacy PHP environment, ensuring that the fixes were both effective and feasible to implement.
  • The client implemented the suggested fixes, resulting in a significantly more secure application.

Conclusion
Blueinfy’s combined manual black-box and code review approach provided the client with a clear path to securing their legacy PHP-based accounting software. By focusing on both the surface-level vulnerabilities and their underlying causes, Blueinfy helped the company address critical security issues, ensuring the platform was robust and secure for its users.

Article by Amish Shah