dinosn/CVE-2025-13673

GitHub: dinosn/CVE-2025-13673

Stars: 0 | Forks: 0

# CVE-2025-13673 — Tutor LMS SQL Injection Lab Unauthenticated SQL Injection in [Tutor LMS](https://wordpress.org/plugins/tutor/) WordPress plugin (<= 3.9.6) via the `coupon_code` parameter. ## Quick Start # 1. Clone and start the lab git clone https://github.com/dinosn/CVE-2025-13673.git cd CVE-2025-13673 ./setup.sh # Deploys WordPress + Tutor LMS 3.9.3 # 2. Run the exploit pip install requests # only dependency # Unauthenticated (time-based blind — no credentials needed) python3 exploit.py http://localhost:8080 # Authenticated (UNION-based — instant extraction) python3 exploit.py http://localhost:8080 -u testuser -p test123 --all ## Vulnerability Details | Field | Value | |-------|-------| | CVE | CVE-2025-13673 | | Affected | Tutor LMS <= 3.9.6 | | Fixed | 3.9.7 | | Type | SQL Injection (CWE-89) | | CVSS | 7.5 / 9.3 | | Auth | None (blind) / Subscriber (UNION) | ### Root Cause `QueryHelper::prepare_where_clause()` builds SQL WHERE clauses with raw string concatenation: // helpers/QueryHelper.php — VULNERABLE $value = is_numeric( $value ) ? $value : "'" . $value . "'"; No escaping. A single quote breaks out of the literal and allows arbitrary SQL. ### Attack Vectors **Unauthenticated:** `POST /` with `tutor_action=tutor_pay_now`. The WordPress `init` hook dispatches this for all visitors. The `_tutor_nonce` is embedded in every frontend page and valid for anonymous sessions. Data extraction via `SLEEP()`. ### Patch (3.9.7) - $val = is_numeric( $val ) ? $val : "'" . $val . "'"; + // Value now passed through $wpdb->prepare('%s', $value) ## Exploit Usage usage: exploit.py [-h] [-u USERNAME] [-p PASSWORD] [--course-id COURSE_ID] [--dump-users] [--db-info] [--options] [--all] [--delay DELAY] url Modes: Default (no -u/-p): Unauthenticated time-based blind SQLi With -u/-p: Authenticated UNION-based (fast) Examples: exploit.py http://target # unauth blind exploit.py http://target -u student -p pass --all # auth UNION ## Testing Different Versions # Test version 3.9.5 (has esc_sql partial mitigation) ./setup.sh 3.9.5 # Test version 3.9.7 (should be fixed) ./setup.sh 3.9.7 ## Files | File | Description | |------|-------------| | `exploit.py` | Dual-mode PoC: unauth blind + auth UNION | | `setup.sh` | One-command lab deployment | | `docker-compose.yml` | WordPress 6.7 + MySQL 8.0 | ## References - [Wordfence Advisory](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/tutor/tutor-lms-396-unauthenticated-sql-injection-via-coupon-code) - [Patchstack Advisory](https://patchstack.com/database/wordpress/plugin/tutor/vulnerability/wordpress-tutor-lms-plugin-3-9-6-unauthenticated-sql-injection-via-coupon-code-vulnerability) ## Disclaimer For authorized security testing and educational purposes only.