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:
- Controllers handle user input, create ViewModels, and render pages.
- 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:
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: -
- Cipher - Provides access to encryption and decryption services using various algorithms.
- Encoding - Manages several common character encodings.
- 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: -
- WeakCipher
- WeakSignature
- WeakMac
- 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: -
- Using the "addHttpHeader()" method on the Response object.
- 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: -
- Using "${...}": Replace the ellipsis with the variable you want to display.
- 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: -
- getTokenName(): Returns the expected parameter name (as a string) associated with the CSRF token.
- generateToken(): Securely generates a unique token string for the logged-in user for each call.
- 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: -
- 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.
- Private Keys: Accessible through the script API using the "CertificateRef" and "KeyRef" classes. Utilize these classes to manage private keys securely.
- 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: -
- userLoggedIn: This middleware capability checks whether the request is from an authenticated user.
- validateLoggedIn: This function verifies that the user is authenticated to invoke a particular function.
- 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: -
- "<isredirect>" element: Used in ISML templates for redirecting.
- "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: -
- 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.
- 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.
- 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.
- 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