Security¶
- Develop securely according to web development ecommerce security best practices and industry standards:
- Don't add passwords & credentials in application code.
- Move it to an imported environmental file.
- Avoid committing passwords & credentials into git/SVN history.
- Move them to imported files, gitignore the file, and commit a sample file with dummy values.
- File-uploads should not be performed on a Miva store server.
- It's better to leverage a 3rd-party file-upload service or perform the upload with necessary security precautions on a separate server.
- Avoid revealing customer & order PII through inadequate authorization techniques.
- For example, we modify the default ORDS page to hide order ship/bill-to information & tracking links for logged out users when being viewed through the "Order History Lookup" (ORHL) page. This is done to prevent the ability to brute force attempts on the order history lookup submitting a known email with different zip codes to find a match that could reveal PII.
- Ensure global variables and user-input data is sanitized and validated appropriately. See Sanitize Your Inputs.
- Use the proper output encoding. See Encode and Escape Data.
Storing & Sharing Passwords¶
- Share passwords long-term with other employees using Bitwarden's Collections.
- For logins inside of shared Bitwarden Collections, avoid using Two-factor Authentication (2FA) methods that only you can access (ex. texting a code your cell phone, a Time-based One-time Password (TOTP) app on your phone, etc.). Instead setup 2FA with a TOTP code add then add the TOTP code to the login in the Bitwarden Collection everyone can access.
Know & Avoid the OWASP Top 10 Mistakes¶
- A01 Broken Access Control
- A02 Cryptographic Failures
- A03 Injection
- A04 Insecure Design
- A05 Security Misconfiguration
- A06 Vulnerable and Outdated Components
- A07 Identification and Authentication Failures
- A08 Software and Data Integrity Failures
- A09 Security Logging and Monitoring Failures
- A10 Server Side Request Forgery (SSRF)
Recommended Reading¶
Best Practices¶
Sanitize Your Inputs¶
Incorrect
<mvt:do file="g.Module_Library_Utilities" name="l.Send_Email" value="SendEmail( g.StoreEmail, g.Email, '', g.Subject, '', g.Message )" />
SendEmail
function.
Correct
<mvt:do file="g.Module_Admin" name="l.email_valid" value="Validate_Email( g.Email )" />
<mvt:if expr="NOT l.email_valid">
<!-- Error message handling here -->
</mvt:if>
Encode and Escape Data¶
"Contextual Output Encoding is a crucial security programming technique needed to stop XSS. This defense is performed on output, when you’re building a user interface, at the last moment before untrusted data is dynamically added to HTML. The type of encoding will depend on the location (or context) in the document where data is being displayed or stored." --OWASP: Encode & Escape Data
HTML Entity Encoding¶
Use &mvte:
or encodeentities()
when outputting strings in HTML content.
Global Variables Must be Encoded¶
Always HTML Entity Encode global variables.
Incorrect
&mvt:global:message;
Correct
&mvte:global:message;
Correct
<mvt:assign name="l.settings:clean_message" value="miva_html_strip(g.Message, '')" />
&mvte:clean_message;
Store Owner Supplied Content Can be Unencoded¶
The only time to use &mvt:
is when you are outputting Store-Owner supplied content where they might provide HTML content. For example:
Correct
&mvt:product:descrip;
&mvt:product:name;
&mvt:option:prompt;
Shopper-Provided Content Must be Encoded¶
Always HTML Entity Encode shoppper-provided content.
Incorrect
<mvt:foreach iterator="group" array="basket:groups">
<mvt:foreach iterator="option" array="group:options">
&mvt:option:prompt;: &mvt:option:data;
</mvt:foreach>
</mvt:foreach>
Correct
<mvt:foreach iterator="group" array="basket:groups">
<mvt:foreach iterator="option" array="group:options">
&mvt:option:prompt;: &mvte:option:data;
</mvt:foreach>
</mvt:foreach>
&mvt:option:prompt;
is ok because it is supplied by the Store-Owner. However, &mvt:option:data;
is provided by the Shopper and should be encoded.
Some common areas where we output shopper-provided content are:
- Product Attributes
&mvte:option:data;
- Bill-To/Ship-to Data
&mvte:customer:bill_fname;
&mvte:basket:bill_fname;
&mvte:order:bill_fname;
- Order Custom Fields
<mvt:item name="customfields" param="Read_Basket( 'order_instructions', l.settings:order_instructions )" /> Order Instructions: &mvte:order_instructions;
- Forms
&mvte:global:Search;
&mvte:global:Quantity;
&mvte:global:Customer_LoginEmail;
&mvte:global:Product_Attributes[1]:value;
HTML Attribute Encoding¶
Use &mvta:
when outputting strings in HTML Attributes.
Incorrect
<a href="mailto:&mvte:global:Store:email;?subject=Contact+About:+&mvt:product:code;">
Contact Us For Help
</a>
Correct
<a href="mailto:&mvte:global:Store:email;?subject=Contact+About:+&mvta:product:code;">
Contact Us For Help
</a>
JavaScript Encoding¶
Use &mvtj:
when outputting strings in JavaScript.
Incorrect
(function (mivaJS) {
mivaJS.Store_Code = '&mvt:global:store:code;';
mivaJS.Product_Code = '&mvt:product:code;';
mivaJS.Category_Code = '&mvte:category:code;';
mivaJS.Customer_Id = &mvt:global:customer:id;;
}(window.mivaJS || (window.mivaJS = {})));
Correct
(function (mivaJS) {
mivaJS.Store_Code = '&mvtj:global:store:code;';
mivaJS.Product_Id = '&mvtj:product:code;';
mivaJS.Category_Code = '&mvtj:category:code;';
mivaJS.Customer_Id = &mvtj:global:customer:id;;
}(window.mivaJS || (window.mivaJS = {})));
URL Encoding¶
Incorrect
window.location = '/mm5/merchant.mvc?Screen=PROD&Product_Code=' + product_code;
Correct
window.location = '/mm5/merchant.mvc?Screen=PROD&Product_Code=' + encodeURIComponent(product_code);