CVE-2026-15022 Overview
CVE-2026-15022 is a stored (second-order) SQL injection vulnerability in the Tutor LMS – eLearning and online course solution plugin for WordPress. The flaw affects all versions up to and including 4.0.0. The root cause is insufficient escaping of a user-supplied quiz answer array combined with an unprepared SQL query in the plugin's quiz data flow. Authenticated attackers with custom-level access or higher can persist a malicious payload through the wp_ajax_tutor_quiz_abandon handler. The injected SQL later executes when a privileged user or Tutor REST API key holder requests /wp-json/tutor/v1/quiz-attempt-details/{id}, enabling extraction of sensitive database contents. This vulnerability is tracked under [CWE-89].
Critical Impact
Authenticated low-privileged users can plant SQL payloads that execute in the context of privileged endpoint queries, exposing confidential WordPress database data including user credentials and course records.
Affected Products
- Tutor LMS – eLearning and online course solution plugin for WordPress (all versions ≤ 4.0.0)
- WordPress sites exposing the Tutor REST API endpoint /wp-json/tutor/v1/quiz-attempt-details/{id}
- Sites permitting custom-level (student/instructor) account registration on vulnerable installs
Discovery Timeline
- 2026-07-16 - CVE-2026-15022 published to NVD
- 2026-07-16 - Last updated in NVD database
Technical Details for CVE-2026-15022
Vulnerability Analysis
The vulnerability is a second-order SQL injection. The injection sink and the injection source are separated across two request contexts. An authenticated attacker submits a crafted quiz answer array through the AJAX endpoint wp_ajax_tutor_quiz_abandon. The plugin stores that attacker-controlled input in the database without adequate escaping or parameterization. Later, when an administrator or a Tutor REST API key holder queries /wp-json/tutor/v1/quiz-attempt-details/{id}, the stored payload is concatenated into a live SQL query executed against the WordPress database. Because the query lacks wpdb->prepare() protection, attackers can append additional SQL statements to exfiltrate data such as user records, password hashes, and session tokens. The confidentiality impact is high while integrity and availability remain unchanged.
Root Cause
The defect combines two coding weaknesses. First, the quiz answer array supplied at attempt time is not validated or escaped before insertion. Second, the downstream query in helpers/QueryHelper.php (around line 951) and the REST API handlers in restapi/REST_Quiz.php build SQL using string concatenation instead of prepared statements. See the WordPress Tutor QueryHelper source and the Tutor REST Quiz handler.
Attack Vector
Exploitation requires an authenticated account with custom-level access such as a student or instructor role. The attacker sends a malicious payload to the wp_ajax_tutor_quiz_abandon handler, embedding SQL syntax within the quiz answer array. The payload lies dormant until a higher-privileged user or an integration using a Tutor REST API key loads the quiz attempt details, at which point the query executes with the database credentials of the WordPress install. Refer to the Wordfence vulnerability report for additional analysis.
No verified public exploit code is available. The vulnerability mechanism is documented in the plugin source at Quiz.php line 442 and Quiz.php line 626.
Detection Methods for CVE-2026-15022
Indicators of Compromise
- Unexpected SQL syntax (UNION SELECT, SLEEP(, INFORMATION_SCHEMA) stored in the wp_tutor_quiz_attempts or related quiz attempt tables
- POST requests to admin-ajax.php with action=tutor_quiz_abandon originating from low-privileged accounts and containing suspicious characters in the attempt_answers parameter
- Requests to /wp-json/tutor/v1/quiz-attempt-details/{id} that return unusually large response payloads or trigger database errors in PHP logs
Detection Strategies
- Inspect stored quiz attempt payloads for SQL metacharacters and keywords before they are consumed by the REST endpoint
- Correlate wp_ajax_tutor_quiz_abandon submissions from a single low-privileged user with subsequent administrator or API access to quiz-attempt-details
- Enable MySQL general query log or slow query log temporarily to identify malformed statements originating from Tutor LMS quiz functions
Monitoring Recommendations
- Monitor WordPress wp-content/debug.log and PHP error logs for wpdb errors referencing tutor tables
- Alert on new or unusual Tutor REST API key usage against the quiz-attempt-details endpoint
- Baseline normal request rates for admin-ajax.php?action=tutor_quiz_abandon and alert on volume anomalies from individual accounts
How to Mitigate CVE-2026-15022
Immediate Actions Required
- Update the Tutor LMS plugin to a version later than 4.0.0 that includes the vendor fix as soon as it becomes available
- Audit existing custom-level user accounts and disable any that are unused or suspicious
- Review stored quiz attempt records for SQL syntax in answer arrays and purge or sanitize affected rows
Patch Information
A fix must be applied by upgrading beyond the vulnerable 4.0.0 release. Consult the Wordfence vulnerability report and the Tutor LMS plugin repository for the fixed release. Rotate any Tutor REST API keys after patching.
Workarounds
- Restrict access to /wp-json/tutor/v1/quiz-attempt-details/{id} at the web server or WAF layer to trusted IP ranges until the plugin is patched
- Disable open user registration and require administrator approval for new Tutor LMS accounts
- Deploy a WAF rule that inspects attempt_answers and related parameters posted to admin-ajax.php for SQL keywords such as UNION, SELECT, and --
# Example NGINX rule to block low-privileged access to quiz-attempt-details until patched
location ~ ^/wp-json/tutor/v1/quiz-attempt-details/ {
allow 10.0.0.0/8; # trusted admin network
deny all;
include fastcgi_params;
fastcgi_pass php-fpm;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

