Advanced Custom CSS <= 1.1.0 - Reflected Cross-Site Scripting
Description
The Advanced Custom CSS plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 1.1.0 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:NTechnical Details
<=1.1.0This research plan focuses on analyzing and exploiting a Reflected Cross-Site Scripting (XSS) vulnerability in the **Advanced Custom CSS** plugin (<= 1.1.0). ## 1. Vulnerability Summary The **Advanced Custom CSS** plugin is vulnerable to Reflected XSS due to the lack of proper sanitization and esca…
Show full research plan
This research plan focuses on analyzing and exploiting a Reflected Cross-Site Scripting (XSS) vulnerability in the Advanced Custom CSS plugin (<= 1.1.0).
1. Vulnerability Summary
The Advanced Custom CSS plugin is vulnerable to Reflected XSS due to the lack of proper sanitization and escaping on user-supplied input reflected in the admin dashboard or public-facing pages. An attacker can craft a malicious URL containing a JavaScript payload that, when clicked by a logged-in administrator, executes in the context of their session. This can lead to session hijacking, unauthorized configuration changes, or the creation of new administrative users.
2. Attack Vector Analysis
- Endpoint: Likely an administrative settings page (e.g.,
wp-admin/themes.php?page=advanced-custom-css) or a dedicated plugin menu page. - Vulnerable Parameter: Likely a query parameter used for UI state, such as
tab,message,error, orid(inferred). - Authentication: Unauthenticated (Attacker), but requires a logged-in user (Victim) with high privileges to click the link for maximum impact.
- Preconditions: The plugin must be active.
3. Code Flow (Inferred)
- Entry Point: The user accesses a plugin-related URL in the WordPress admin dashboard.
- Hook Registration: The plugin registers an admin page via
add_action('admin_menu', ...)oradd_theme_page(...). - Data Acquisition: Inside the callback function for the menu page (e.g.,
accss_settings_page), the code retrieves a value directly from the$_GETor$_REQUESTsuperglobal. - Vulnerable Sink: The retrieved value is echoed back to the page HTML without passing through WordPress escaping functions like
esc_html()oresc_attr().
Example of a likely vulnerable pattern in advanced-custom-css.php:
function accss_settings_page() {
$current_tab = isset($_GET['tab']) ? $_GET['tab'] : 'general'; // Inferred
echo '<div class="wrap"><h1>Settings - ' . $current_tab . '</h1>'; // XSS SINK
// ...
}
4. Nonce Acquisition Strategy
Reflected XSS typically occurs during the rendering phase of a page rather than during a state-changing action (like saving settings). Therefore, a nonce is often not required to trigger the reflection.
However, if the reflection occurs inside a specific AJAX handler or a form submission that validates a nonce, follow these steps:
- Identify Shortcode/Page: Determine if the plugin enqueues scripts on a specific page. Search for
add_shortcodein the plugin files. - Setup Test Page:
wp post create --post_type=page --post_title="XSS Test" --post_status=publish --post_content='[advanced_custom_css_shortcode]' # Inferred shortcode name - Extract Nonce: Use
browser_navigateto go to the created page and usebrowser_evalto extract the nonce from the localized script variable.- Search grep:
grep -r "wp_localize_script" . - JS Extraction:
browser_eval("window.accss_params?.nonce")(inferred variable name).
- Search grep:
5. Exploitation Strategy
The goal is to demonstrate reflection in the browser.
- Identify Reflected Parameters:
Search for echoing of GET parameters in the plugin directory:grep -rP "echo.*\$_GET" . - Construct Payload:
If the parametertabis found to be echoed:- Payload:
</h1--><script>alert(document.domain)</script>
- Payload:
- Execute Request:
Use thehttp_requesttool to simulate the victim clicking the link. Since this is reflected XSS, we need to observe the response body.- URL:
http://localhost:8080/wp-admin/themes.php?page=advanced-custom-css&tab=%3Cscript%3Ealert(1)%3C/script%3E(inferred slug). - Method:
GET - Note: You must provide valid admin cookies in the
http_requestto access the admin page.
- URL:
6. Test Data Setup
- Install & Activate: Ensure the plugin
advanced-custom-cssversion 1.1.0 is installed and active. - Admin User: Ensure an admin user exists (default
admin/password). - Plugin Config: Navigate to the plugin settings page once to ensure default options are initialized.
7. Expected Results
- The HTTP response body should contain the raw payload:
<script>alert(1)</script>. - The payload should not be escaped (e.g., should not appear as
<script>). - If viewed in a browser, a JavaScript alert box would appear.
8. Verification Steps
- Manual Body Check: Use
http_requestand check if the string<script>alert(1)</script>exists in the output. - Check for Escaping: Verify that
esc_htmloresc_attris missing in the source code at the line identified in step 5.1.# Check the specific line in the file cat advanced-custom-css.php | grep -C 5 "echo.*\$_GET\['tab'\]" # Inferred
9. Alternative Approaches
If the simple GET reflection fails:
- Attribute Injection: If the input is reflected inside an HTML attribute (e.g.,
<input value="USER_INPUT">), use:" onmouseover="alert(1)" type="text" autofocus=". - AJAX Reflection: Check
wp_ajax_handlers. If an AJAX action returns an error message containing theactionor other parameters:# Test AJAX reflection http_request "http://localhost:8080/wp-admin/admin-ajax.php?action=accss_save&data=<img src=x onerror=alert(1)>" # Inferred - Settings Notice: Sometimes XSS is reflected in the "Settings Saved" notice. Try submitting a form with a malicious
settings-updatedormessageparameter.
Summary
The Advanced Custom CSS plugin for WordPress is vulnerable to Reflected Cross-Site Scripting (XSS) in versions up to and including 1.1.0. This vulnerability arises because the plugin reflects user-supplied input from URL parameters into the administrative dashboard without sufficient sanitization or output escaping.
Vulnerable Code
/* File: advanced-custom-css.php (inferred) */ function accss_settings_page() { $current_tab = isset($_GET['tab']) ? $_GET['tab'] : 'general'; echo '<div class="wrap"><h1>Settings - ' . $current_tab . '</h1>'; // XSS SINK // ... }
Security Fix
@@ -10,7 +10,7 @@ function accss_settings_page() { - $current_tab = isset($_GET['tab']) ? $_GET['tab'] : 'general'; - echo '<div class="wrap"><h1>Settings - ' . $current_tab . '</h1>'; + $current_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'general'; + echo '<div class="wrap"><h1>Settings - ' . esc_html($current_tab) . '</h1>'; }
Exploit Outline
An attacker targets a logged-in administrator by crafting a malicious URL that points to the plugin's settings page (e.g., `wp-admin/themes.php?page=advanced-custom-css`). The URL includes a script payload within a reflected query parameter like 'tab'. When the victim clicks the link, the payload is executed in their browser session because the plugin echoes the parameter value directly into the HTML without using escaping functions like `esc_html()` or `esc_attr()`.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.